diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 0d11399460..38d3896534 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -729,10 +729,10 @@ Render\Text - + GPU - + GPU diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index ed7de24771..21db0ab5cb 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -294,6 +294,8 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de packDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; hr = device_->CreateTexture2D(&packDesc, nullptr, &packTexture_); _assert_(SUCCEEDED(hr)); + + shaderLanguageDesc_.Init(HLSL_D3D11); } D3D11DrawContext::~D3D11DrawContext() { @@ -1205,7 +1207,10 @@ uint32_t D3D11DrawContext::GetDataFormatSupport(DataFormat fmt) const { // A D3D11Framebuffer is a D3D11Framebuffer plus all the textures it owns. class D3D11Framebuffer : public Framebuffer { public: - D3D11Framebuffer() {} + D3D11Framebuffer(int width, int height) { + width_ = width; + height_ = height; + } ~D3D11Framebuffer() { if (colorTex) colorTex->Release(); @@ -1220,8 +1225,6 @@ public: if (depthStencilRTView) depthStencilRTView->Release(); } - int width; - int height; ID3D11Texture2D *colorTex = nullptr; ID3D11RenderTargetView *colorRTView = nullptr; @@ -1236,9 +1239,7 @@ public: Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) { HRESULT hr; - D3D11Framebuffer *fb = new D3D11Framebuffer(); - fb->width = desc.width; - fb->height = desc.height; + D3D11Framebuffer *fb = new D3D11Framebuffer(desc.width, desc.height); if (desc.numColorAttachments) { fb->colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM; D3D11_TEXTURE2D_DESC descColor{}; @@ -1396,7 +1397,7 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x } // TODO: Check for level too! - if (width == src->width && width == dst->width && height == src->height && height == dst->height && x == 0 && y == 0 && z == 0 && dstX == 0 && dstY == 0 && dstZ == 0) { + if (width == src->Width() && width == dst->Width() && height == src->Height() && height == dst->Height() && x == 0 && y == 0 && z == 0 && dstX == 0 && dstY == 0 && dstZ == 0) { // Don't need to specify region. This might be faster, too. context_->CopyResource(dstTex, srcTex); return; @@ -1415,11 +1416,11 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x dstY -= y; y = 0; } - if (x + width > src->width) { - width = src->width - x; + if (x + width > src->Width()) { + width = src->Width() - x; } - if (y + height > src->height) { - height = src->height - y; + if (y + height > src->Height()) { + height = src->Height() - y; } D3D11_BOX srcBox{ (UINT)x, (UINT)y, (UINT)z, (UINT)(x + width), (UINT)(y + height), (UINT)(z + depth) }; context_->CopySubresourceRegion(dstTex, dstLevel, dstX, dstY, dstZ, srcTex, level, &srcBox); @@ -1441,11 +1442,11 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel _assert_(fb->colorFormat == DXGI_FORMAT_R8G8B8A8_UNORM); // TODO: Figure out where the badness really comes from. - if (bx + bw > fb->width) { - bw -= (bx + bw) - fb->width; + if (bx + bw > fb->Width()) { + bw -= (bx + bw) - fb->Width(); } - if (by + bh > fb->height) { - bh -= (by + bh) - fb->height; + if (by + bh > fb->Height()) { + bh -= (by + bh) - fb->Height(); } } @@ -1565,8 +1566,8 @@ void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Ren context_->OMSetRenderTargets(1, &fb->colorRTView, fb->depthStencilRTView); curRenderTargetView_ = fb->colorRTView; curDepthStencilView_ = fb->depthStencilRTView; - curRTWidth_ = fb->width; - curRTHeight_ = fb->height; + curRTWidth_ = fb->Width(); + curRTHeight_ = fb->Height(); } } else { if (curRenderTargetView_ == bbRenderTargetView_ && curDepthStencilView_ == bbDepthStencilView_) { @@ -1634,8 +1635,8 @@ uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int chann void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; if (fb) { - *w = fb->width; - *h = fb->height; + *w = fb->Width(); + *h = fb->Height(); } else { *w = bbWidth_; *h = bbHeight_; diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 4665f6933f..44a559ee50 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -670,6 +670,8 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID HRESULT fboINTZ = d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, FOURCC_INTZ); supportsINTZ = SUCCEEDED(displayINTZ) && SUCCEEDED(fboINTZ); } + + shaderLanguageDesc_.Init(HLSL_D3D9); } D3D9Context::~D3D9Context() { @@ -1072,26 +1074,26 @@ bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, si class D3D9Framebuffer : public Framebuffer { public: + D3D9Framebuffer(int width, int height) { + width_ = width; + height_ = height; + } ~D3D9Framebuffer(); - uint32_t id; - LPDIRECT3DSURFACE9 surf; - LPDIRECT3DSURFACE9 depthstencil; - LPDIRECT3DTEXTURE9 tex; - LPDIRECT3DTEXTURE9 depthstenciltex; - int width; - int height; + uint32_t id = 0; + LPDIRECT3DSURFACE9 surf = nullptr; + LPDIRECT3DSURFACE9 depthstencil = nullptr; + LPDIRECT3DTEXTURE9 tex = nullptr; + LPDIRECT3DTEXTURE9 depthstenciltex = nullptr; }; Framebuffer *D3D9Context::CreateFramebuffer(const FramebufferDesc &desc) { static uint32_t id = 0; - D3D9Framebuffer *fbo = new D3D9Framebuffer{}; - fbo->width = desc.width; - fbo->height = desc.height; + D3D9Framebuffer *fbo = new D3D9Framebuffer(desc.width, desc.height); fbo->depthstenciltex = nullptr; - HRESULT rtResult = device_->CreateTexture(fbo->width, fbo->height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fbo->tex, NULL); + HRESULT rtResult = device_->CreateTexture(desc.width, desc.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fbo->tex, NULL); if (FAILED(rtResult)) { ERROR_LOG(G3D, "Failed to create render target"); delete fbo; @@ -1101,12 +1103,12 @@ Framebuffer *D3D9Context::CreateFramebuffer(const FramebufferDesc &desc) { HRESULT dsResult; if (supportsINTZ) { - dsResult = device_->CreateTexture(fbo->width, fbo->height, 1, D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ, D3DPOOL_DEFAULT, &fbo->depthstenciltex, NULL); + dsResult = device_->CreateTexture(desc.width, desc.height, 1, D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ, D3DPOOL_DEFAULT, &fbo->depthstenciltex, NULL); if (SUCCEEDED(dsResult)) { dsResult = fbo->depthstenciltex->GetSurfaceLevel(0, &fbo->depthstencil); } } else { - dsResult = device_->CreateDepthStencilSurface(fbo->width, fbo->height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, &fbo->depthstencil, NULL); + dsResult = device_->CreateDepthStencilSurface(desc.width, desc.height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, &fbo->depthstencil, NULL); } if (FAILED(dsResult)) { ERROR_LOG(G3D, "Failed to create depth buffer"); @@ -1208,8 +1210,8 @@ void D3D9Context::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChan void D3D9Context::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo; if (fb) { - *w = fb->width; - *h = fb->height; + *w = fb->Width(); + *h = fb->Height(); } else { *w = targetWidth_; *h = targetHeight_; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 2dc7768029..ff5d0e08cf 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -350,6 +350,7 @@ public: return (uint32_t)ShaderLanguage::GLSL_1xx; } } + uint32_t GetDataFormatSupport(DataFormat fmt) const override; void SetErrorCallback(ErrorCallbackFn callback, void *userdata) override { @@ -601,6 +602,78 @@ OpenGLContext::OpenGLContext() { // TODO: Should this workaround be removed for newer devices/drivers? bugs_.Infest(Bugs::PVR_GENMIPMAP_HEIGHT_GREATER); } + + shaderLanguageDesc_.Init(GLSL_1xx); + + // Detect shader language features. + if (gl_extensions.IsGLES) { + if (gl_extensions.GLES3) { + shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx; + shaderLanguageDesc_.glslVersionNumber = 300; // GLSL ES 3.0 + shaderLanguageDesc_.fragColor0 = "fragColor0"; + shaderLanguageDesc_.texture = "texture"; + shaderLanguageDesc_.glslES30 = true; + shaderLanguageDesc_.bitwiseOps = true; + shaderLanguageDesc_.texelFetch = "texelFetch"; + shaderLanguageDesc_.varying_vs = "out"; + shaderLanguageDesc_.varying_fs = "in"; + shaderLanguageDesc_.attribute = "in"; + } else { + shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx; + shaderLanguageDesc_.glslVersionNumber = 100; // GLSL ES 1.0 + if (gl_extensions.EXT_gpu_shader4) { + shaderLanguageDesc_.bitwiseOps = true; + shaderLanguageDesc_.texelFetch = "texelFetch2D"; + } + if (gl_extensions.EXT_blend_func_extended) { + // Oldy moldy GLES, so use the fixed output name. + shaderLanguageDesc_.fragColor1 = "gl_SecondaryFragColorEXT"; + } + } + } else { + if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) { + if (gl_extensions.VersionGEThan(3, 3, 0)) { + shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx; + shaderLanguageDesc_.glslVersionNumber = 330; + shaderLanguageDesc_.fragColor0 = "fragColor0"; + shaderLanguageDesc_.texture = "texture"; + shaderLanguageDesc_.glslES30 = true; + shaderLanguageDesc_.bitwiseOps = true; + shaderLanguageDesc_.texelFetch = "texelFetch"; + shaderLanguageDesc_.varying_vs = "out"; + shaderLanguageDesc_.varying_fs = "in"; + shaderLanguageDesc_.attribute = "in"; + } else if (gl_extensions.VersionGEThan(3, 0, 0)) { + shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx; + shaderLanguageDesc_.glslVersionNumber = 130; + shaderLanguageDesc_.fragColor0 = "fragColor0"; + shaderLanguageDesc_.bitwiseOps = true; + shaderLanguageDesc_.texelFetch = "texelFetch"; + } else { + shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx; + shaderLanguageDesc_.glslVersionNumber = 110; + if (gl_extensions.EXT_gpu_shader4) { + shaderLanguageDesc_.bitwiseOps = true; + shaderLanguageDesc_.texelFetch = "texelFetch2D"; + } + } + } + } + + if (gl_extensions.IsGLES && gl_extensions.GLES3) { + caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch); + if (gl_extensions.EXT_shader_framebuffer_fetch) { + shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require"; + shaderLanguageDesc_.lastFragData = "gl_LastFragData[0]"; + } else if (gl_extensions.NV_shader_framebuffer_fetch) { + // GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop. + shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require"; + shaderLanguageDesc_.lastFragData = "gl_LastFragData[0]"; + } else if (gl_extensions.ARM_shader_framebuffer_fetch) { + shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require"; + shaderLanguageDesc_.lastFragData = "gl_LastFragColorARM"; + } + } } OpenGLContext::~OpenGLContext() { @@ -735,13 +808,16 @@ OpenGLTexture::~OpenGLTexture() { class OpenGLFramebuffer : public Framebuffer { public: - OpenGLFramebuffer(GLRenderManager *render) : render_(render) {} + OpenGLFramebuffer(GLRenderManager *render, GLRFramebuffer *framebuffer) : render_(render), framebuffer_(framebuffer) { + width_ = framebuffer->width; + height_ = framebuffer->height; + } ~OpenGLFramebuffer() { - render_->DeleteFramebuffer(framebuffer); + render_->DeleteFramebuffer(framebuffer_); } GLRenderManager *render_; - GLRFramebuffer *framebuffer = nullptr; + GLRFramebuffer *framebuffer_ = nullptr; }; // TODO: SSE/NEON optimize, and move to ColorConv.cpp. @@ -843,7 +919,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit aspect |= GL_DEPTH_BUFFER_BIT; if (channelBits & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; - renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag); + renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag); return true; } @@ -1239,8 +1315,8 @@ void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) { CheckGLExtensions(); - OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_); - fbo->framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil); + GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil); + OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_, framebuffer); return fbo; } @@ -1250,7 +1326,7 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth; GLRRenderPassAction stencil = (GLRRenderPassAction)rp.stencil; - renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag); + renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer_ : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag); } void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) { @@ -1266,7 +1342,7 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s if (channelBits & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; } - renderManager_.CopyFramebuffer(src->framebuffer, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer, GLOffset2D{ dstX, dstY }, aspect, tag); + renderManager_.CopyFramebuffer(src->framebuffer_, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer_, GLOffset2D{ dstX, dstY }, aspect, tag); } bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter, const char *tag) { @@ -1280,7 +1356,7 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in if (channels & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; - renderManager_.BlitFramebuffer(src->framebuffer, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag); + renderManager_.BlitFramebuffer(src->framebuffer_, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer_, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag); return true; } @@ -1294,14 +1370,14 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh aspect |= GL_DEPTH_BUFFER_BIT; if (channelBit & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; - renderManager_.BindFramebufferAsTexture(fb->framebuffer, binding, aspect, color); + renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, aspect, color); } void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; if (fb) { - *w = fb->framebuffer->width; - *h = fb->framebuffer->height; + *w = fb->Width(); + *h = fb->Height(); } else { *w = targetWidth_; *h = targetHeight_; diff --git a/Common/GPU/Shader.cpp b/Common/GPU/Shader.cpp index 79684874c3..f4bfe96b69 100644 --- a/Common/GPU/Shader.cpp +++ b/Common/GPU/Shader.cpp @@ -1 +1,81 @@ #include "Common/GPU/Shader.h" + +ShaderLanguageDesc::ShaderLanguageDesc(ShaderLanguage lang) { + Init(lang); +} + +void ShaderLanguageDesc::Init(ShaderLanguage lang) { + shaderLanguage = lang; + switch (lang) { + case GLSL_1xx: + // Just used in the shader test, and as a basis for the others in DetectShaderLanguage. + glslVersionNumber = 110; + attribute = "attribute"; + varying_vs = "varying"; + varying_fs = "varying"; + fragColor0 = "gl_FragColor"; + fragColor1 = "fragColor1"; + texture = "texture2D"; + texelFetch = nullptr; + bitwiseOps = false; + lastFragData = nullptr; + gles = false; + forceMatrix4x4 = true; + break; + case GLSL_3xx: + // Just used in the shader test. + glslVersionNumber = 300; // GLSL ES 3.0 + varying_vs = "out"; + varying_fs = "in"; + attribute = "in"; + fragColor0 = "fragColor0"; + fragColor1 = "fragColor1"; + texture = "texture"; + texelFetch = nullptr; + bitwiseOps = false; + lastFragData = nullptr; + gles = false; + forceMatrix4x4 = true; + glslES30 = true; + bitwiseOps = true; + texelFetch = "texelFetch"; + break; + case GLSL_VULKAN: + fragColor0 = "fragColor0"; + fragColor1 = "fragColor1"; + varying_fs = "in"; + varying_vs = "out"; + attribute = "in"; + bitwiseOps = true; + framebufferFetchExtension = nullptr; + gles = false; + glslES30 = true; + glslVersionNumber = 450; + lastFragData = nullptr; + texture = "texture"; + texelFetch = "texelFetch"; + forceMatrix4x4 = false; + coefsFromBuffers = true; + break; + case HLSL_D3D9: + case HLSL_D3D11: + fragColor0 = "outfragment.target"; + fragColor1 = "outfragment.target1"; + varying_fs = "in"; + varying_vs = "out"; + attribute = "in"; + bitwiseOps = lang == HLSL_D3D11; + framebufferFetchExtension = nullptr; + gles = false; + glslES30 = true; + glslVersionNumber = 0; + lastFragData = nullptr; + texture = "texture"; + texelFetch = "texelFetch"; + forceMatrix4x4 = false; + coefsFromBuffers = true; + vsOutPrefix = "Out."; + break; + } +} + diff --git a/Common/GPU/Shader.h b/Common/GPU/Shader.h index e5adc8b514..d574cd4738 100644 --- a/Common/GPU/Shader.h +++ b/Common/GPU/Shader.h @@ -23,8 +23,11 @@ enum class ShaderStage { }; struct ShaderLanguageDesc { + ShaderLanguageDesc() {} explicit ShaderLanguageDesc(ShaderLanguage lang); + void Init(ShaderLanguage lang); + int glslVersionNumber = 0; ShaderLanguage shaderLanguage; bool gles = false; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 5f5ad3b808..eabd2b0a72 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -497,7 +497,6 @@ public: void InvalidateCachedState() override; private: - VulkanTexture *GetNullTexture(); VulkanContext *vulkan_ = nullptr; @@ -760,6 +759,8 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const Textur VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) : vulkan_(vulkan), caps_{}, renderManager_(vulkan) { + shaderLanguageDesc_.Init(GLSL_VULKAN); + caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.samplerAnisotropy != 0; caps_.geometryShaderSupported = vulkan->GetDeviceFeatures().enabled.geometryShader != 0; caps_.tesselationShaderSupported = vulkan->GetDeviceFeatures().enabled.tessellationShader != 0; @@ -780,8 +781,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) case VULKAN_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break; case VULKAN_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break; case VULKAN_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break; - default: - caps_.vendor = GPUVendor::VENDOR_UNKNOWN; + default: caps_.vendor = GPUVendor::VENDOR_UNKNOWN; break; } if (caps_.vendor == GPUVendor::VENDOR_QUALCOMM) { @@ -1448,7 +1448,11 @@ uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const { // use this frame's init command buffer. class VKFramebuffer : public Framebuffer { public: - VKFramebuffer(VKRFramebuffer *fb) : buf_(fb) { _assert_msg_(fb, "Null fb in VKFramebuffer constructor"); } + VKFramebuffer(VKRFramebuffer *fb) : buf_(fb) { + _assert_msg_(fb, "Null fb in VKFramebuffer constructor"); + width_ = fb->width; + height_ = fb->height; + } ~VKFramebuffer() { _assert_msg_(buf_, "Null buf_ in VKFramebuffer - double delete?"); buf_->vulkan_->Delete().QueueCallback([](void *fb) { diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 1e7ddf0e75..055cb93e1e 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -347,6 +347,10 @@ public: class Framebuffer : public RefCountedObject { public: + int Width() { return width_; } + int Height() { return height_; } +protected: + int width_ = -1, height_ = -1; }; class Buffer : public RefCountedObject { @@ -359,7 +363,7 @@ public: int Height() { return height_; } int Depth() { return depth_; } protected: - int width_, height_, depth_; + int width_ = -1, height_ = -1, depth_ = -1; }; struct BindingDesc { @@ -496,6 +500,7 @@ struct DeviceCaps { bool framebufferBlitSupported; bool framebufferDepthCopySupported; bool framebufferDepthBlitSupported; + bool framebufferFetchSupported; std::string deviceName; // The device name to use when creating the thin3d context, to get the same one. }; @@ -548,6 +553,11 @@ public: virtual std::vector GetExtensionList() const { return std::vector(); } virtual std::vector GetDeviceList() const { return std::vector(); } + // Describes the primary shader language that this implementation prefers. + const ShaderLanguageDesc &GetShaderLanguageDesc() { + return shaderLanguageDesc_; + } + virtual uint32_t GetSupportedShaderLanguages() const = 0; virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {} @@ -663,6 +673,8 @@ protected: ShaderModule *vsPresets_[VS_MAX_PRESET]; ShaderModule *fsPresets_[FS_MAX_PRESET]; + ShaderLanguageDesc shaderLanguageDesc_; + int targetWidth_; int targetHeight_; diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index a4e542bf02..abfb9e40e6 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -66,11 +66,12 @@ struct CoreParameter { std::string *collectEmuLog = nullptr; bool headLess; // Try to avoid messageboxes etc - // Internal PSP resolution + // Internal PSP rendering resolution and scale factor. + int renderScaleFactor; int renderWidth; int renderHeight; - // Actual pixel output resolution (for use by glViewport and the like) + // Actual output resolution in pixels. int pixelWidth; int pixelHeight; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index b83bef2098..6d0744dea9 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -77,6 +77,7 @@ bool FramebufferManagerCommon::UpdateSize() { renderWidth_ = (float)PSP_CoreParameter().renderWidth; renderHeight_ = (float)PSP_CoreParameter().renderHeight; + renderScaleFactor_ = (float)PSP_CoreParameter().renderScaleFactor; pixelWidth_ = PSP_CoreParameter().pixelWidth; pixelHeight_ = PSP_CoreParameter().pixelHeight; bloomHack_ = g_Config.iBloomHack; @@ -340,14 +341,6 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame } } - float renderWidthFactor = renderWidth_ / 480.0f; - float renderHeightFactor = renderHeight_ / 272.0f; - - if (PSP_CoreParameter().compat.flags().Force04154000Download && params.fb_address == 0x04154000) { - renderWidthFactor = 1.0; - renderHeightFactor = 1.0; - } - // None found? Create one. if (!vfb) { vfb = new VirtualFramebuffer{}; @@ -356,28 +349,28 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfb->fb_stride = params.fb_stride; vfb->z_address = params.z_address; vfb->z_stride = params.z_stride; + + // The other width/height parameters are set in ResizeFramebufFBO below. vfb->width = drawing_width; vfb->height = drawing_height; vfb->newWidth = drawing_width; vfb->newHeight = drawing_height; vfb->lastFrameNewSize = gpuStats.numFlips; - vfb->renderWidth = (u16)(drawing_width * renderWidthFactor); - vfb->renderHeight = (u16)(drawing_height * renderHeightFactor); - vfb->bufferWidth = drawing_width; - vfb->bufferHeight = drawing_height; vfb->format = params.fmt; vfb->drawnFormat = params.fmt; vfb->usageFlags = FB_USAGE_RENDERTARGET; - SetColorUpdated(vfb, skipDrawReason); u32 byteSize = ColorBufferByteSize(vfb); if (Memory::IsVRAMAddress(params.fb_address) && params.fb_address + byteSize > framebufRangeEnd_) { framebufRangeEnd_ = params.fb_address + byteSize; } + // This is where we actually create the framebuffer. The true is "force". ResizeFramebufFBO(vfb, drawing_width, drawing_height, true); NotifyRenderFramebufferCreated(vfb); + SetColorUpdated(vfb, skipDrawReason); + INFO_LOG(FRAMEBUF, "Creating FBO for %08x (z: %08x) : %i x %i x %i", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, vfb->format); vfb->last_frame_render = gpuStats.numFlips; @@ -1046,6 +1039,7 @@ void FramebufferManagerCommon::DecimateFBOs() { } } +// Requires width/height to be set already. void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, int h, bool force, bool skipCopy) { _dbg_assert_(w > 0); _dbg_assert_(h > 0); @@ -1067,7 +1061,32 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, vfb->bufferHeight = std::max((int)vfb->bufferHeight, h); } - SetRenderSize(vfb); + bool force1x = false; + switch (bloomHack_) { + case 1: + force1x = vfb->bufferWidth <= 128 || vfb->bufferHeight <= 64; + break; + case 2: + force1x = vfb->bufferWidth <= 256 || vfb->bufferHeight <= 128; + break; + case 3: + force1x = vfb->bufferWidth < 480 || vfb->bufferWidth > 800 || vfb->bufferHeight < 272; // GOW uses 864x272 + break; + } + + if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) { + force1x = true; + } + + if (force1x && g_Config.iInternalResolution != 1) { + vfb->renderScaleFactor = 1.0f; + vfb->renderWidth = vfb->bufferWidth; + vfb->renderHeight = vfb->bufferHeight; + } else { + vfb->renderScaleFactor = renderScaleFactor_; + vfb->renderWidth = (u16)(vfb->bufferWidth * renderScaleFactor_); + vfb->renderHeight = (u16)(vfb->bufferHeight * renderScaleFactor_); + } // During hardware rendering, we always render at full color depth even if the game wouldn't on real hardware. // It's not worth the trouble trying to support lower bit-depth rendering, just @@ -1655,35 +1674,6 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS } } -void FramebufferManagerCommon::SetRenderSize(VirtualFramebuffer *vfb) { - float renderWidthFactor = renderWidth_ / 480.0f; - float renderHeightFactor = renderHeight_ / 272.0f; - bool force1x = false; - switch (bloomHack_) { - case 1: - force1x = vfb->bufferWidth <= 128 || vfb->bufferHeight <= 64; - break; - case 2: - force1x = vfb->bufferWidth <= 256 || vfb->bufferHeight <= 128; - break; - case 3: - force1x = vfb->bufferWidth < 480 || vfb->bufferWidth > 800 || vfb->bufferHeight < 272; // GOW uses 864x272 - break; - } - - if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) { - force1x = true; - } - - if (force1x && g_Config.iInternalResolution != 1) { - vfb->renderWidth = vfb->bufferWidth; - vfb->renderHeight = vfb->bufferHeight; - } else { - vfb->renderWidth = (u16)(vfb->bufferWidth * renderWidthFactor); - vfb->renderHeight = (u16)(vfb->bufferHeight * renderHeightFactor); - } -} - void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) { VirtualFramebuffer *vfb = currentRenderVfb_; if (vfb) { @@ -1695,10 +1685,11 @@ void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) { void FramebufferManagerCommon::Resized() { gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB; - int w, h; - presentation_->CalculateRenderResolution(&w, &h, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_); + int w, h, scaleFactor; + presentation_->CalculateRenderResolution(&w, &h, &scaleFactor, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_); PSP_CoreParameter().renderWidth = w; PSP_CoreParameter().renderHeight = h; + PSP_CoreParameter().renderScaleFactor = scaleFactor; if (UpdateSize()) { DestroyAllFBOs(); @@ -1736,6 +1727,11 @@ void FramebufferManagerCommon::DestroyAllFBOs() { tempFB.second.fbo->Release(); } tempFBOs_.clear(); + + for (auto iter : fbosToDelete_) { + iter->Release(); + } + fbosToDelete_.clear(); } Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h) { diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 905bdaed14..3df8b69acf 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -61,21 +61,24 @@ struct VirtualFramebuffer { u16 width; u16 height; - // renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions. - // The physical buffer may be larger than renderWidth/renderHeight. - u16 renderWidth; - u16 renderHeight; - - // bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than width/height. + // bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than or equal to width/height. // Actual physical buffer is this size times the render resolution multiplier. // The buffer may be used to render a width or height from 0 to these values without being recreated. u16 bufferWidth; u16 bufferHeight; + // renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions. + // The physical buffer may be larger than renderWidth/renderHeight. + u16 renderWidth; + u16 renderHeight; + + float renderScaleFactor; + u16 usageFlags; u16 newWidth; u16 newHeight; + int lastFrameNewSize; Draw::Framebuffer *fbo; @@ -396,9 +399,10 @@ protected: bool gameUsesSequentialCopies_ = false; - // Sampled in BeginFrame for safety. + // Sampled in BeginFrame/UpdateSize for safety. float renderWidth_ = 0.0f; float renderHeight_ = 0.0f; + float renderScaleFactor_ = 1.0f; int pixelWidth_; int pixelHeight_; int bloomHack_ = 0; diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index e4b966ff6f..58233a6d29 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -729,7 +729,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u draw_->BindPipeline(nullptr); } -void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa) { +void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) { // Check if postprocessing shader is doing upscaling as it requires native resolution std::vector shaderInfo; if (!g_Config.vPostShaderNames.empty() && g_Config.vPostShaderNames[0] != "Off") { @@ -776,4 +776,6 @@ void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool *width = 480 * zoom; *height = 272 * zoom; } + + *scaleFactor = zoom; } diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index 0102c3fbcf..959e516d5f 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -100,7 +100,7 @@ public: void SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidth, int bufferHeight); void CopyToOutput(OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1); - void CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa); + void CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa); protected: void CreateDeviceObjects(); diff --git a/GPU/Common/ShaderCommon.cpp b/GPU/Common/ShaderCommon.cpp index 45ba5ab357..360e7f9d8b 100644 --- a/GPU/Common/ShaderCommon.cpp +++ b/GPU/Common/ShaderCommon.cpp @@ -101,79 +101,3 @@ void init_resources(TBuiltInResource &Resources) { Resources.limits.generalVariableIndexing = 1; Resources.limits.generalConstantMatrixVectorIndexing = 1; } - -ShaderLanguageDesc::ShaderLanguageDesc(ShaderLanguage lang) { - shaderLanguage = lang; - switch (lang) { - case GLSL_1xx: - // Just used in the shader test, and as a basis for the others in DetectShaderLanguage. - glslVersionNumber = 110; - attribute = "attribute"; - varying_vs = "varying"; - varying_fs = "varying"; - fragColor0 = "gl_FragColor"; - fragColor1 = "fragColor1"; - texture = "texture2D"; - texelFetch = nullptr; - bitwiseOps = false; - lastFragData = nullptr; - gles = false; - forceMatrix4x4 = true; - break; - case GLSL_3xx: - // Just used in the shader test. - glslVersionNumber = 300; // GLSL ES 3.0 - varying_vs = "out"; - varying_fs = "in"; - attribute = "in"; - fragColor0 = "fragColor0"; - fragColor1 = "fragColor1"; - texture = "texture"; - texelFetch = nullptr; - bitwiseOps = false; - lastFragData = nullptr; - gles = false; - forceMatrix4x4 = true; - glslES30 = true; - bitwiseOps = true; - texelFetch = "texelFetch"; - break; - case GLSL_VULKAN: - fragColor0 = "fragColor0"; - fragColor1 = "fragColor1"; - varying_fs = "in"; - varying_vs = "out"; - attribute = "in"; - bitwiseOps = true; - framebufferFetchExtension = nullptr; - gles = false; - glslES30 = true; - glslVersionNumber = 450; - lastFragData = nullptr; - texture = "texture"; - texelFetch = "texelFetch"; - forceMatrix4x4 = false; - coefsFromBuffers = true; - break; - case HLSL_D3D9: - case HLSL_D3D11: - fragColor0 = "outfragment.target"; - fragColor1 = "outfragment.target1"; - varying_fs = "in"; - varying_vs = "out"; - attribute = "in"; - bitwiseOps = lang == HLSL_D3D11; - framebufferFetchExtension = nullptr; - gles = false; - glslES30 = true; - glslVersionNumber = 0; - lastFragData = nullptr; - texture = "texture"; - texelFetch = "texelFetch"; - forceMatrix4x4 = false; - coefsFromBuffers = true; - vsOutPrefix = "Out."; - break; - } -} - diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 5e2e716e32..2a90aaa4e4 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -420,8 +420,8 @@ void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, return; } - float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth; - float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight; + float srcXFactor = src->renderScaleFactor; + float srcYFactor = src->renderScaleFactor; const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2; if (srcBpp != bpp && bpp != 0) { srcXFactor = (srcXFactor * bpp) / srcBpp; @@ -431,8 +431,8 @@ void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int srcY1 = srcY * srcYFactor; int srcY2 = (srcY + h) * srcYFactor; - float dstXFactor = (float)dst->renderWidth / (float)dst->bufferWidth; - float dstYFactor = (float)dst->renderHeight / (float)dst->bufferHeight; + float dstXFactor = dst->renderScaleFactor; + float dstYFactor = dst->renderScaleFactor; const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2; if (dstBpp != bpp && bpp != 0) { dstXFactor = (dstXFactor * bpp) / dstBpp; diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 88730eec70..255c547ee9 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -89,7 +89,7 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const } ShaderManagerD3D11::ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel) - : ShaderManagerCommon(draw), device_(device), context_(context), featureLevel_(featureLevel), compat_(ShaderLanguage::HLSL_D3D11) { + : ShaderManagerCommon(draw), device_(device), context_(context), featureLevel_(featureLevel) { codeBuffer_ = new char[16384]; memset(&ub_base, 0, sizeof(ub_base)); memset(&ub_lights, 0, sizeof(ub_lights)); @@ -210,7 +210,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader ** std::string genErrorString; uint32_t attrMask; uint64_t uniformMask; - GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &genErrorString); + GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString); vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform); vsCache_[VSID] = vs; } else { @@ -224,7 +224,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader ** // Fragment shader not in cache. Let's compile it. std::string genErrorString; uint64_t uniformMask; - GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &genErrorString); + GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &genErrorString); fs = new D3D11FragmentShader(device_, featureLevel_, FSID, codeBuffer_, useHWTransform); fsCache_[FSID] = fs; } else { diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 140a9a3656..fe21710ad9 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -110,7 +110,6 @@ private: ID3D11Device *device_; ID3D11DeviceContext *context_; D3D_FEATURE_LEVEL featureLevel_; - ShaderLanguageDesc compat_; typedef std::map FSCache; FSCache fsCache_; diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 776cdcf7f3..951406c80d 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -383,8 +383,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { return; } - float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth; - float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight; + float srcXFactor = (float)src->renderScaleFactor; + float srcYFactor = (float)src->renderScaleFactor; const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2; if (srcBpp != bpp && bpp != 0) { srcXFactor = (srcXFactor * bpp) / srcBpp; @@ -394,8 +394,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { int srcY1 = srcY * srcYFactor; int srcY2 = (srcY + h) * srcYFactor; - float dstXFactor = (float)dst->renderWidth / (float)dst->bufferWidth; - float dstYFactor = (float)dst->renderHeight / (float)dst->bufferHeight; + float dstXFactor = (float)dst->renderScaleFactor; + float dstYFactor = (float)dst->renderScaleFactor; const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2; if (dstBpp != bpp && bpp != 0) { dstXFactor = (dstXFactor * bpp) / dstBpp; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 4aafbcb290..bb423ca233 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -502,7 +502,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { } ShaderManagerDX9::ShaderManagerDX9(Draw::DrawContext *draw, LPDIRECT3DDEVICE9 device) - : ShaderManagerCommon(draw), device_(device), compat_(HLSL_D3D9) { + : ShaderManagerCommon(draw), device_(device) { codeBuffer_ = new char[32768]; } @@ -582,7 +582,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat std::string genErrorString; uint32_t attrMask; uint64_t uniformMask; - if (GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &genErrorString)) { + if (GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString)) { vs = new VSShader(device_, VSID, codeBuffer_, useHWTransform); } if (!vs || vs->Failed()) { @@ -607,7 +607,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat // Can still work with software transform. uint32_t attrMask; uint64_t uniformMask; - bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &genErrorString); + bool success = GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString); _assert_(success); vs = new VSShader(device_, VSID, codeBuffer_, false); } @@ -624,7 +624,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat // Fragment shader not in cache. Let's compile it. std::string errorString; uint64_t uniformMask; - bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &errorString); + bool success = GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &errorString); // We're supposed to handle all possible cases. _assert_(success); fs = new PSShader(device_, FSID, codeBuffer_); diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 8e132e2a31..d8062ef881 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -111,7 +111,6 @@ private: void Clear(); LPDIRECT3DDEVICE9 device_; - ShaderLanguageDesc compat_; FShaderID lastFSID_; VShaderID lastVSID_; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index c0fd949930..6d625b2de5 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -315,8 +315,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, bool useBlit = gstate_c.Supports(GPU_SUPPORTS_FRAMEBUFFER_BLIT); - float srcXFactor = useBlit ? (float)src->renderWidth / (float)src->bufferWidth : 1.0f; - float srcYFactor = useBlit ? (float)src->renderHeight / (float)src->bufferHeight : 1.0f; + float srcXFactor = useBlit ? src->renderScaleFactor : 1.0f; + float srcYFactor = useBlit ? src->renderScaleFactor : 1.0f; const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2; if (srcBpp != bpp && bpp != 0) { srcXFactor = (srcXFactor * bpp) / srcBpp; @@ -326,8 +326,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int srcY1 = srcY * srcYFactor; int srcY2 = (srcY + h) * srcYFactor; - float dstXFactor = useBlit ? (float)dst->renderWidth / (float)dst->bufferWidth : 1.0f; - float dstYFactor = useBlit ? (float)dst->renderHeight / (float)dst->bufferHeight : 1.0f; + float dstXFactor = useBlit ? dst->renderScaleFactor : 1.0f; + float dstYFactor = useBlit ? dst->renderScaleFactor : 1.0f; const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2; if (dstBpp != bpp && bpp != 0) { dstXFactor = (dstXFactor * bpp) / dstBpp; @@ -360,6 +360,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, if (useBlit) { draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST, "BlitFramebuffer"); } else { + // TODO: Move this workaround out into thin3d, instead of dirtying up the code here. + draw_->BindFramebufferAsRenderTarget(dst->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitFramebuffer"); draw_->BindFramebufferAsTexture(src->fbo, 0, Draw::FB_COLOR_BIT, 0); @@ -376,7 +378,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, float srcW = src->bufferWidth; float srcH = src->bufferHeight; render_->BindProgram(draw2dprogram_); - DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); + DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h * dstYFactor, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); textureCacheGL_->ForgetLastTexture(); } diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index be3358c959..a8d23c88ba 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -572,95 +572,17 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu } ShaderManagerGLES::ShaderManagerGLES(Draw::DrawContext *draw) - : ShaderManagerCommon(draw), compat_(GLSL_1xx), fsCache_(16), vsCache_(16) { + : ShaderManagerCommon(draw), fsCache_(16), vsCache_(16) { render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); codeBuffer_ = new char[16384]; lastFSID_.set_invalid(); lastVSID_.set_invalid(); - DetectShaderLanguage(); } ShaderManagerGLES::~ShaderManagerGLES() { delete [] codeBuffer_; } -void ShaderManagerGLES::DetectShaderLanguage() { - ShaderLanguageDesc &compat = compat_; - - compat.gles = gl_extensions.IsGLES; - - if (compat.gles) { - if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) { - compat.shaderLanguage = ShaderLanguage::GLSL_3xx; - compat.glslVersionNumber = 300; // GLSL ES 3.0 - compat.fragColor0 = "fragColor0"; - compat.texture = "texture"; - compat.glslES30 = true; - compat.bitwiseOps = true; - compat.texelFetch = "texelFetch"; - compat.varying_vs = "out"; - compat.varying_fs = "in"; - compat.attribute = "in"; - } else { - compat.shaderLanguage = ShaderLanguage::GLSL_1xx; - compat.glslVersionNumber = 100; // GLSL ES 1.0 - if (gl_extensions.EXT_gpu_shader4) { - compat.bitwiseOps = true; - compat.texelFetch = "texelFetch2D"; - } - if (gl_extensions.EXT_blend_func_extended) { - // Oldy moldy GLES, so use the fixed output name. - compat.fragColor1 = "gl_SecondaryFragColorEXT"; - } - } - } else { - if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) { - if (gl_extensions.VersionGEThan(3, 3, 0)) { - compat.shaderLanguage = ShaderLanguage::GLSL_3xx; - compat.glslVersionNumber = 330; - compat.fragColor0 = "fragColor0"; - compat.texture = "texture"; - compat.glslES30 = true; - compat.bitwiseOps = true; - compat.texelFetch = "texelFetch"; - compat.varying_vs = "out"; - compat.varying_fs = "in"; - compat.attribute = "in"; - } else if (gl_extensions.VersionGEThan(3, 0, 0)) { - compat.shaderLanguage = ShaderLanguage::GLSL_1xx; - compat.glslVersionNumber = 130; - compat.fragColor0 = "fragColor0"; - compat.bitwiseOps = true; - compat.texelFetch = "texelFetch"; - } else { - compat.shaderLanguage = ShaderLanguage::GLSL_1xx; - compat.glslVersionNumber = 110; - if (gl_extensions.EXT_gpu_shader4) { - compat.bitwiseOps = true; - compat.texelFetch = "texelFetch2D"; - } - } - } - } - - if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) { - if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300) && gl_extensions.EXT_shader_framebuffer_fetch) { - compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require"; - compat.lastFragData = "fragColor0"; - } else if (gl_extensions.EXT_shader_framebuffer_fetch) { - compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require"; - compat.lastFragData = "gl_LastFragData[0]"; - } else if (gl_extensions.NV_shader_framebuffer_fetch) { - // GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop. - compat.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require"; - compat.lastFragData = "gl_LastFragData[0]"; - } else if (gl_extensions.ARM_shader_framebuffer_fetch) { - compat.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require"; - compat.lastFragData = "gl_LastFragColorARM"; - } - } -} - void ShaderManagerGLES::Clear() { DirtyLastShader(); for (auto iter = linkedShaderCache_.begin(); iter != linkedShaderCache_.end(); ++iter) { @@ -709,7 +631,7 @@ void ShaderManagerGLES::DirtyLastShader() { Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { uint64_t uniformMask; std::string errorString; - if (!GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &errorString)) { + if (!GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &errorString)) { ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str()); return nullptr; } @@ -722,7 +644,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { uint32_t attrMask; uint64_t uniformMask; std::string errorString; - if (!GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &errorString)) { + if (!GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &errorString)) { ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str()); return nullptr; } diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 2343f7d508..71e5541631 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -170,7 +170,6 @@ private: void Clear(); Shader *CompileFragmentShader(FShaderID id); Shader *CompileVertexShader(VShaderID id); - void DetectShaderLanguage(); struct LinkedShaderCacheEntry { LinkedShaderCacheEntry(Shader *vs_, Shader *fs_, LinkedShader *ls_) @@ -183,7 +182,6 @@ private: typedef std::vector LinkedShaderCache; GLRenderManager *render_; - ShaderLanguageDesc compat_; LinkedShaderCache linkedShaderCache_; bool lastVShaderSame_; diff --git a/GPU/Vulkan/FramebufferManagerVulkan.cpp b/GPU/Vulkan/FramebufferManagerVulkan.cpp index 8acc1cbe2f..d04021ff58 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.cpp +++ b/GPU/Vulkan/FramebufferManagerVulkan.cpp @@ -261,7 +261,6 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb, // We have to bind here instead of clear, since it can be that no framebuffer is bound. // The backend can sometimes directly optimize it to a clear. draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "ReformatFramebuffer"); - // draw_->Clear(Draw::FBChannel::FB_COLOR_BIT | Draw::FBChannel::FB_STENCIL_BIT, 0, 0.0f, 0); // Need to dirty anything that has command buffer dynamic state, in case we started a new pass above. // Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager. @@ -339,8 +338,10 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX return; } - float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth; - float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight; + float srcXFactor = (float)src->renderScaleFactor; + float srcYFactor = (float)src->renderScaleFactor; + + // Some games use wrong-format block transfers. Simulate that. const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2; if (srcBpp != bpp && bpp != 0) { srcXFactor = (srcXFactor * bpp) / srcBpp; @@ -350,8 +351,8 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX int srcY1 = srcY * srcYFactor; int srcY2 = (srcY + h) * srcYFactor; - float dstXFactor = (float)dst->renderWidth / (float)dst->bufferWidth; - float dstYFactor = (float)dst->renderHeight / (float)dst->bufferHeight; + float dstXFactor = (float)dst->renderScaleFactor; + float dstYFactor = (float)dst->renderScaleFactor; const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2; if (dstBpp != bpp && bpp != 0) { dstXFactor = (dstXFactor * bpp) / dstBpp; @@ -367,8 +368,6 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX return; } - // BlitFramebuffer can clip, but CopyFramebufferImage is more restricted. - // In case the src goes outside, we just skip the optimization in that case. const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1; const bool srcInsideBounds = srcX2 <= src->renderWidth && srcY2 <= src->renderHeight; const bool dstInsideBounds = dstX2 <= dst->renderWidth && dstY2 <= dst->renderHeight; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index fb80436d73..1dc70e488d 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -358,6 +358,7 @@ int main(int argc, const char* argv[]) coreParameter.startBreak = false; coreParameter.printfEmuLog = !autoCompare; coreParameter.headLess = true; + coreParameter.renderScaleFactor = 1; coreParameter.renderWidth = 480; coreParameter.renderHeight = 272; coreParameter.pixelWidth = 480;