From bd9b6daaad9c2085969959666a5f0e3d7fd0bcbc Mon Sep 17 00:00:00 2001 From: TJnotJT Date: Thu, 6 Aug 2026 21:28:15 -0400 Subject: [PATCH] GS:HW: Reduce primid max value. Large values may cause errors in primid DATE on Mesa OpenGL. --- bin/resources/shaders/dx11/convert.fx | 16 ++++++++-------- bin/resources/shaders/opengl/convert.glsl | 10 +++++----- bin/resources/shaders/vulkan/convert.glsl | 10 +++++----- pcsx2/GS/Renderers/Common/GSShaderEnums.h | 11 +++++++++++ pcsx2/GS/Renderers/DX11/GSDevice11.cpp | 4 ++++ pcsx2/GS/Renderers/DX12/GSDevice12.cpp | 4 ++++ pcsx2/GS/Renderers/Metal/convert.metal | 8 ++++---- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp | 8 +++++++- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 11 +++++++++-- pcsx2/ShaderCacheVersion.h | 2 +- 10 files changed, 58 insertions(+), 26 deletions(-) diff --git a/bin/resources/shaders/dx11/convert.fx b/bin/resources/shaders/dx11/convert.fx index c0258efaf6..c47d475868 100644 --- a/bin/resources/shaders/dx11/convert.fx +++ b/bin/resources/shaders/dx11/convert.fx @@ -662,9 +662,9 @@ float ps_primid_image_init_0(PS_INPUT input) : SV_Target { float c; if ((127.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass) - c = float(-1); + c = float(PRIMID_MIN); else - c = float(0x7FFFFFFF); + c = float(PRIMID_MAX); return c; } #endif @@ -674,9 +674,9 @@ float ps_primid_image_init_1(PS_INPUT input) : SV_Target { float c; if (sample_c(input.t).a < (127.5f / 255.0f)) // >= 0x80 pass - c = float(-1); + c = float(PRIMID_MIN); else - c = float(0x7FFFFFFF); + c = float(PRIMID_MAX); return c; } #endif @@ -686,9 +686,9 @@ float ps_primid_image_init_2(PS_INPUT input) : SV_Target { float c; if ((254.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass) - c = float(-1); + c = float(PRIMID_MIN); else - c = float(0x7FFFFFFF); + c = float(PRIMID_MAX); return c; } #endif @@ -698,9 +698,9 @@ float ps_primid_image_init_3(PS_INPUT input) : SV_Target { float c; if (sample_c(input.t).a < (254.5f / 255.0f)) // >= 0x80 pass - c = float(-1); + c = float(PRIMID_MIN); else - c = float(0x7FFFFFFF); + c = float(PRIMID_MAX); return c; } #endif diff --git a/bin/resources/shaders/opengl/convert.glsl b/bin/resources/shaders/opengl/convert.glsl index 72397e26dd..8fbc8a4c7e 100644 --- a/bin/resources/shaders/opengl/convert.glsl +++ b/bin/resources/shaders/opengl/convert.glsl @@ -627,23 +627,23 @@ void ps_yuv() void main() { - o_col0 = vec4(0x7FFFFFFF); + o_col0 = vec4(PRIMID_MAX); #ifdef ps_primid_image_init_0 if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass) - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif #ifdef ps_primid_image_init_1 if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif #ifdef ps_primid_image_init_2 if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass) - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif #ifdef ps_primid_image_init_3 if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif } #endif diff --git a/bin/resources/shaders/vulkan/convert.glsl b/bin/resources/shaders/vulkan/convert.glsl index ba089ec919..2bb902eece 100644 --- a/bin/resources/shaders/vulkan/convert.glsl +++ b/bin/resources/shaders/vulkan/convert.glsl @@ -640,23 +640,23 @@ void ps_yuv() void main() { - o_col0 = vec4(0x7FFFFFFF); + o_col0 = vec4(PRIMID_MAX); #ifdef ps_primid_image_init_0 if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass) - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif #ifdef ps_primid_image_init_1 if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif #ifdef ps_primid_image_init_2 if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass) - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif #ifdef ps_primid_image_init_3 if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass - o_col0 = vec4(-1); + o_col0 = vec4(PRIMID_MIN); #endif } #endif diff --git a/pcsx2/GS/Renderers/Common/GSShaderEnums.h b/pcsx2/GS/Renderers/Common/GSShaderEnums.h index 394bab8ee4..f00df58ee4 100644 --- a/pcsx2/GS/Renderers/Common/GSShaderEnums.h +++ b/pcsx2/GS/Renderers/Common/GSShaderEnums.h @@ -63,4 +63,15 @@ enum class PS_ROV_DEPTH : uint32_t READ_ONLY = 2, }; +#if defined(__METAL_VERSION__) + #define CONSTANT constant +#else + #define CONSTANT +#endif + +static constexpr CONSTANT int PRIMID_MAX = (1 << 24) - 1; +static constexpr CONSTANT int PRIMID_MIN = -1; + +#undef CONSTANT + } // namespace GSShader diff --git a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp index 04728e6ddc..8358a7df83 100644 --- a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp +++ b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp @@ -249,6 +249,8 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle) ShaderMacro sm_ps; sm_ps.AddMacro("PIXEL_SHADER", 1); + sm_ps.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX); + sm_ps.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN); sm_ps.AddMacro("HAS_BILN", static_cast(shader.Biln())); sm_ps.AddMacro("HAS_STENCIL_OUTPUT", static_cast(shader.StencilOutput())); sm_ps.AddMacro("HAS_INTEGER_OUTPUT", static_cast(shader.IntegerOutputBpp() != 0)); @@ -582,6 +584,8 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle) const std::string entry_point_macro = WrapEntryPointMacro(entry_point); ShaderMacro sm_ps; sm_ps.AddMacro("PIXEL_SHADER", 1); + sm_ps.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX); + sm_ps.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN); sm_ps.AddMacro(entry_point_macro.c_str(), 1); m_date.primid_init_ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, sm_ps.GetPtr(), entry_point.c_str()); if (!m_date.primid_init_ps[i]) diff --git a/pcsx2/GS/Renderers/DX12/GSDevice12.cpp b/pcsx2/GS/Renderers/DX12/GSDevice12.cpp index 78063130a8..d030aafd45 100644 --- a/pcsx2/GS/Renderers/DX12/GSDevice12.cpp +++ b/pcsx2/GS/Renderers/DX12/GSDevice12.cpp @@ -2877,6 +2877,8 @@ bool GSDevice12::CompileConvertPipelines() ShaderMacro sm; sm.AddMacro("PIXEL_SHADER", 1); + sm.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX); + sm.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN); sm.AddMacro("HAS_BILN", static_cast(shader.Biln())); sm.AddMacro("HAS_STENCIL_OUTPUT", static_cast(shader.StencilOutput())); sm.AddMacro("HAS_INTEGER_OUTPUT", static_cast(shader.IntegerOutputBpp() != 0)); @@ -2930,6 +2932,8 @@ bool GSDevice12::CompileConvertPipelines() ShaderMacro sm; sm.AddMacro("PIXEL_SHADER", "1"); + sm.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX); + sm.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN); sm.AddMacro(entry_point_macro.c_str(), "1"); ComPtr ps(m_shader_cache.GetPixelShader(*source, sm.GetPtr(), entry_point.c_str())); diff --git a/pcsx2/GS/Renderers/Metal/convert.metal b/pcsx2/GS/Renderers/Metal/convert.metal index 6f11e50ddf..dfa2ffc27b 100644 --- a/pcsx2/GS/Renderers/Metal/convert.metal +++ b/pcsx2/GS/Renderers/Metal/convert.metal @@ -112,22 +112,22 @@ fragment void ps_datm0(float4 p [[position]], DirectReadTextureIn tex) fragment float4 ps_primid_init_datm1(float4 p [[position]], DirectReadTextureIn tex) { - return tex.read(p).a < (127.5f / 255.f) ? -1 : FLT_MAX; + return tex.read(p).a < (127.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX; } fragment float4 ps_primid_init_datm0(float4 p [[position]], DirectReadTextureIn tex) { - return tex.read(p).a > (127.5f / 255.f) ? -1 : FLT_MAX; + return tex.read(p).a > (127.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX; } fragment float4 ps_primid_rta_init_datm1(float4 p [[position]], DirectReadTextureIn tex) { - return tex.read(p).a < (254.5f / 255.f) ? -1 : FLT_MAX; + return tex.read(p).a < (254.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX; } fragment float4 ps_primid_rta_init_datm0(float4 p [[position]], DirectReadTextureIn tex) { - return tex.read(p).a > (254.5f / 255.f) ? -1 : FLT_MAX; + return tex.read(p).a > (254.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX; } fragment float4 ps_rta_correction(ConvertShaderData data [[stage_in]], ConvertPSRes res) diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp index 74765f6131..86fb04ac13 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp @@ -432,6 +432,8 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle) const char* name = shader.EntryPoint(); std::string macro; + macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX); + macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN); macro += fmt::format("#define HAS_BILN {}\n", static_cast(shader.Biln())); macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast(shader.StencilOutput())); macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast(shader.IntegerOutputBpp() != 0)); @@ -609,9 +611,13 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle) for (size_t i = 0; i < std::size(m_date.primid_ps); i++) { + std::string macro; + macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX); + macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN); + const std::string ps(GetShaderSource( fmt::format("ps_primid_image_init_{}", i), - GL_FRAGMENT_SHADER, *convert_glsl)); + GL_FRAGMENT_SHADER, *convert_glsl, macro)); m_shader_cache.GetProgram(&m_date.primid_ps[i], m_convert.vs, ps); m_date.primid_ps[i].SetFormattedName("PrimID Destination Alpha Init %d", i); } diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 90db0fd3a7..36c023bda7 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -4200,6 +4200,8 @@ bool GSDeviceVK::CompileConvertPipelines() gpb.SetColorWriteMask(0, shader.Mask()); std::string macro; + macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX); + macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN); macro += fmt::format("#define HAS_BILN {}\n", static_cast(shader.Biln())); macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast(shader.StencilOutput())); macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast(shader.IntegerOutputBpp() != 0)); @@ -4267,9 +4269,14 @@ bool GSDeviceVK::CompileConvertPipelines() for (u32 datm = 0; datm < 4; datm++) { + std::string macro; + macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX); + macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN); + + const std::string source_with_header = macro + *source; + const std::string entry_point(StringUtil::StdStringFromFormat("ps_primid_image_init_%d", datm)); - VkShaderModule ps = - GetUtilityFragmentShader(*source, entry_point.c_str()); + VkShaderModule ps = GetUtilityFragmentShader(source_with_header, entry_point.c_str()); if (ps == VK_NULL_HANDLE) return false; diff --git a/pcsx2/ShaderCacheVersion.h b/pcsx2/ShaderCacheVersion.h index c67ddb45cf..834753e797 100644 --- a/pcsx2/ShaderCacheVersion.h +++ b/pcsx2/ShaderCacheVersion.h @@ -3,4 +3,4 @@ /// Version number for GS and other shaders. Increment whenever any of the contents of the /// shaders change, to invalidate the cache. -static constexpr u32 SHADER_CACHE_VERSION = 111; // Last changed in PR 14824 (1) +static constexpr u32 SHADER_CACHE_VERSION = 112; // Last changed in PR 14824 (2)