diff --git a/Source/Core/VideoBackends/D3D/D3DMain.cpp b/Source/Core/VideoBackends/D3D/D3DMain.cpp index 9f75712ccd..b217218986 100644 --- a/Source/Core/VideoBackends/D3D/D3DMain.cpp +++ b/Source/Core/VideoBackends/D3D/D3DMain.cpp @@ -106,6 +106,7 @@ void VideoBackend::FillBackendInfo() g_Config.backend_info.bSupportsSSAA = true; g_Config.backend_info.bSupportsShaderBinaries = true; g_Config.backend_info.bSupportsPipelineCacheData = false; + g_Config.backend_info.bSupportsCoarseDerivatives = true; g_Config.backend_info.bSupportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter); g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames(); diff --git a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp index 68496c9ed6..3a33832dc1 100644 --- a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp +++ b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp @@ -82,6 +82,7 @@ void VideoBackend::FillBackendInfo() g_Config.backend_info.AAModes = DXContext::GetAAModes(g_Config.iAdapter); g_Config.backend_info.bSupportsShaderBinaries = true; g_Config.backend_info.bSupportsPipelineCacheData = true; + g_Config.backend_info.bSupportsCoarseDerivatives = true; // We can only check texture support once we have a device. if (g_dx_context) diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index 5887d37391..17e31c4418 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -55,6 +55,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsPartialDepthCopies = false; g_Config.backend_info.bSupportsShaderBinaries = false; g_Config.backend_info.bSupportsPipelineCacheData = false; + g_Config.backend_info.bSupportsCoarseDerivatives = false; // aamodes: We only support 1 sample, so no MSAA g_Config.backend_info.Adapters.clear(); diff --git a/Source/Core/VideoBackends/OGL/OGLMain.cpp b/Source/Core/VideoBackends/OGL/OGLMain.cpp index 3ca79d5c85..375b1d12c7 100644 --- a/Source/Core/VideoBackends/OGL/OGLMain.cpp +++ b/Source/Core/VideoBackends/OGL/OGLMain.cpp @@ -99,7 +99,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsGPUTextureDecoding = true; g_Config.backend_info.bSupportsBBox = true; - // Overwritten in Render.cpp later + // Overwritten in OGLRender.cpp later g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPaletteConversion = true; @@ -107,6 +107,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsDepthClamp = true; g_Config.backend_info.bSupportsST3CTextures = false; g_Config.backend_info.bSupportsBPTCTextures = false; + g_Config.backend_info.bSupportsCoarseDerivatives = false; g_Config.backend_info.Adapters.clear(); diff --git a/Source/Core/VideoBackends/OGL/OGLRender.cpp b/Source/Core/VideoBackends/OGL/OGLRender.cpp index 782d5e1747..76064920f2 100644 --- a/Source/Core/VideoBackends/OGL/OGLRender.cpp +++ b/Source/Core/VideoBackends/OGL/OGLRender.cpp @@ -483,6 +483,8 @@ Renderer::Renderer(std::unique_ptr main_gl_context, float backbuffer_ GLExtensions::Supports("GL_EXT_texture_compression_s3tc"); g_Config.backend_info.bSupportsBPTCTextures = GLExtensions::Supports("GL_ARB_texture_compression_bptc"); + g_Config.backend_info.bSupportsCoarseDerivatives = + GLExtensions::Supports("GL_ARB_derivative_control") || GLExtensions::Version() >= 450; if (m_main_gl_context->IsGLES()) { diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 021391e47c..8aba81b7ed 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -747,6 +747,7 @@ void ProgramShaderCache::CreateHeader() "%s\n" // shader image load store "%s\n" // shader framebuffer fetch "%s\n" // shader thread shuffle + "%s\n" // derivative control // Precision defines for GLSL ES "%s\n" @@ -826,6 +827,9 @@ void ProgramShaderCache::CreateHeader() "#extension GL_ARB_shader_image_load_store : enable" : "", framebuffer_fetch_string.c_str(), shader_shuffle_string.c_str(), + g_ActiveConfig.backend_info.bSupportsCoarseDerivatives ? + "#extension GL_ARB_derivative_control : enable" : + "", is_glsles ? "precision highp float;" : "", is_glsles ? "precision highp int;" : "", is_glsles ? "precision highp sampler2DArray;" : "", (is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ? diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index a0aa8e03c1..ca1f4304dd 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -84,6 +84,7 @@ void VideoSoftware::InitBackendInfo() g_Config.backend_info.bSupportsShaderBinaries = false; g_Config.backend_info.bSupportsPipelineCacheData = false; g_Config.backend_info.bSupportsBBox = true; + g_Config.backend_info.bSupportsCoarseDerivatives = false; // aamodes g_Config.backend_info.AAModes = {1}; diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index 6c58369204..16aa7872e7 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -286,6 +286,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config) config->backend_info.bSupportsLogicOp = false; // Dependent on features. config->backend_info.bSupportsLargePoints = false; // Dependent on features. config->backend_info.bSupportsFramebufferFetch = false; // No support. + config->backend_info.bSupportsCoarseDerivatives = true; // Assumed support. } void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index b2a1166fd6..dd2d9f41ad 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -628,15 +628,35 @@ uint WrapCoord(int coord, uint wrap, int size) {{ BitfieldExtract<&SamplerState::TM1::max_lod>("texmode1")); if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) - out.Write(R"( + { + if (g_ActiveConfig.backend_info.bSupportsCoarseDerivatives) + { + // The software renderer uses the equivalent of coarse derivatives, so use them here for + // consistency. This hasn't been hardware tested. + // Note that bSupportsCoarseDerivatives being false only means dFdxCoarse and dFdxFine don't + // exist. The GPU may still implement dFdx using coarse derivatives; we just don't have the + // ability to specifically require it. + out.Write(R"( + float2 uv_delta_x = abs(dFdxCoarse(float2(uv))); + float2 uv_delta_y = abs(dFdyCoarse(float2(uv))); +)"); + } + else + { + out.Write(R"( float2 uv_delta_x = abs(dFdx(float2(uv))); float2 uv_delta_y = abs(dFdy(float2(uv))); )"); + } + } else if (api_type == APIType::D3D) + { + ASSERT(g_ActiveConfig.backend_info.bSupportsCoarseDerivatives); out.Write(R"( - float2 uv_delta_x = abs(ddx(float2(uv))); - float2 uv_delta_y = abs(ddy(float2(uv))); + float2 uv_delta_x = abs(ddx_coarse(float2(uv))); + float2 uv_delta_y = abs(ddy_coarse(float2(uv))); )"); + } // TODO: LOD bias is normally S2.5 (Dolphin uses S7.8 for arbitrary mipmap detection and higher // IRs), but (at least per the software renderer) actual LOD is S28.4. How does this work? diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 495eef6c28..d4307c479a 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -230,6 +230,7 @@ struct VideoConfig final bool bSupportsDepthReadback = false; bool bSupportsShaderBinaries = false; bool bSupportsPipelineCacheData = false; + bool bSupportsCoarseDerivatives = false; } backend_info; // Utility