From d7685279188a03095423603afcfe619bad0b1b75 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 23 Oct 2025 14:20:51 +0100 Subject: [PATCH] Check for discarding at a per-pixel level for test failures on GL --- renderdoc/driver/gl/gl_pixelhistory.cpp | 85 +++++++++++++++++++------ 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/renderdoc/driver/gl/gl_pixelhistory.cpp b/renderdoc/driver/gl/gl_pixelhistory.cpp index 42b155ba4..aff4530f0 100644 --- a/renderdoc/driver/gl/gl_pixelhistory.cpp +++ b/renderdoc/driver/gl/gl_pixelhistory.cpp @@ -105,11 +105,14 @@ struct GLPixelHistoryResources GLuint fullPrecisionFrameBuffer; GLuint primitiveIdFragmentShader; GLuint primitiveIdFragmentShaderSPIRV; + GLuint fixedColFragmentShader; + GLuint fixedColFragmentShaderSPIRV; GLuint msCopyComputeProgram; GLuint msCopyDepthComputeProgram; GLuint msCopyDstBuffer; GLuint msCopyUniformBlockBuffer; - std::unordered_map programs; + std::unordered_map primIdPrograms; + std::unordered_map fixedColPrograms; std::map copyFramebuffers; std::map shaderOutIntFramebuffers; }; @@ -120,6 +123,7 @@ enum class OpenGLTest ScissorTest, DepthClamp, DepthBounds, + Discard, StencilTest, DepthTest, SampleMask, @@ -133,11 +137,11 @@ enum class PerFragmentQueryType PrimitiveId }; -GLuint GetPrimitiveIdProgram(WrappedOpenGL *driver, GLReplay *replay, - GLPixelHistoryResources &resources, GLuint currentProgram) +GLuint GetFixedColProgram(WrappedOpenGL *driver, GLReplay *replay, + GLPixelHistoryResources &resources, GLuint currentProgram) { - auto programIterator = resources.programs.find(currentProgram); - if(programIterator != resources.programs.end()) + auto programIterator = resources.fixedColPrograms.find(currentProgram); + if(programIterator != resources.fixedColPrograms.end()) { return programIterator->second; } @@ -145,12 +149,36 @@ GLuint GetPrimitiveIdProgram(WrappedOpenGL *driver, GLReplay *replay, GLRenderState rs; rs.FetchState(driver); - GLuint primitiveIdProgram = driver->glCreateProgram(); - replay->CreateFragmentShaderReplacementProgram( - rs.Program.name, primitiveIdProgram, rs.Pipeline.name, resources.primitiveIdFragmentShader, - resources.primitiveIdFragmentShaderSPIRV); + GLuint ret = driver->glCreateProgram(); + replay->CreateFragmentShaderReplacementProgram(rs.Program.name, ret, rs.Pipeline.name, + resources.fixedColFragmentShader, + resources.fixedColFragmentShaderSPIRV); - return primitiveIdProgram; + resources.fixedColPrograms[currentProgram] = ret; + + return ret; +} + +GLuint GetPrimitiveIdProgram(WrappedOpenGL *driver, GLReplay *replay, + GLPixelHistoryResources &resources, GLuint currentProgram) +{ + auto programIterator = resources.primIdPrograms.find(currentProgram); + if(programIterator != resources.primIdPrograms.end()) + { + return programIterator->second; + } + + GLRenderState rs; + rs.FetchState(driver); + + GLuint ret = driver->glCreateProgram(); + replay->CreateFragmentShaderReplacementProgram(rs.Program.name, ret, rs.Pipeline.name, + resources.primitiveIdFragmentShader, + resources.primitiveIdFragmentShaderSPIRV); + + resources.primIdPrograms[currentProgram] = ret; + + return ret; } // Returns a Framebuffer that has the same depth and stencil formats of the currently bound @@ -592,30 +620,40 @@ bool PixelHistorySetupResources(WrappedOpenGL *driver, GLPixelHistoryResources & ShaderType shaderType = IsGLES ? ShaderType::GLSLES : ShaderType::GLSL; - rdcstr glslSource; + rdcstr primIdGLSL; if(glslVersion >= 330 || (IsGLES && glslVersion >= 300)) { - glslSource = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag), shaderType, + primIdGLSL = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag), shaderType, glslVersion); } else { - glslSource = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag), shaderType, + primIdGLSL = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag), shaderType, glslVersion, "#define INT_BITS_TO_FLOAT_NOT_SUPPORTED\n"); } + // SPIR-V shaders are always generated as desktop GL 430, for ease - rdcstr spirvSource = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag), + rdcstr primIdSPIRV = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag), ShaderType::GLSPIRV, 430); + rdcstr fixedColGLSL = + GenerateGLSLShader(GetEmbeddedResource(glsl_fixedcol_frag), shaderType, glslVersion); + rdcstr fixedColSPIRV = + GenerateGLSLShader(GetEmbeddedResource(glsl_fixedcol_frag), ShaderType::GLSPIRV, 430); + rdcstr msCopySource = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_mscopy_comp), shaderType, glslVersion); rdcstr msCopySourceDepth = GenerateGLSLShader( GetEmbeddedResource(glsl_pixelhistory_mscopy_depth_comp), shaderType, glslVersion); if(HasExt[ARB_gl_spirv]) - resources.primitiveIdFragmentShaderSPIRV = CreateSPIRVShader(eGL_FRAGMENT_SHADER, spirvSource); + { + resources.primitiveIdFragmentShaderSPIRV = CreateSPIRVShader(eGL_FRAGMENT_SHADER, primIdSPIRV); + resources.fixedColFragmentShaderSPIRV = CreateSPIRVShader(eGL_FRAGMENT_SHADER, fixedColSPIRV); + } - resources.primitiveIdFragmentShader = CreateShader(eGL_FRAGMENT_SHADER, glslSource); + resources.primitiveIdFragmentShader = CreateShader(eGL_FRAGMENT_SHADER, primIdGLSL); + resources.fixedColFragmentShader = CreateShader(eGL_FRAGMENT_SHADER, fixedColGLSL); resources.msCopyComputeProgram = CreateCShaderProgram(msCopySource); resources.msCopyDepthComputeProgram = CreateCShaderProgram(msCopySourceDepth); @@ -634,10 +672,11 @@ bool PixelHistoryDestroyResources(WrappedOpenGL *driver, const GLPixelHistoryRes driver->glDeleteBuffers(1, &resources.msCopyDstBuffer); driver->glDeleteBuffers(1, &resources.msCopyUniformBlockBuffer); - for(const std::pair &resourceProgram : resources.programs) - { + for(const std::pair &resourceProgram : resources.primIdPrograms) + driver->glDeleteProgram(resourceProgram.second); + + for(const std::pair &resourceProgram : resources.fixedColPrograms) driver->glDeleteProgram(resourceProgram.second); - } for(const auto &pair : resources.copyFramebuffers) { @@ -1370,6 +1409,13 @@ bool QueryTest(WrappedOpenGL *driver, GLPixelHistoryResources &resources, const if(HasExt[EXT_depth_bounds_test]) driver->glDisable(eGL_DEPTH_BOUNDS_TEST_EXT); } + if(test < OpenGLTest::Discard) + { + GLint currentProgram = 0; + driver->glGetIntegerv(eGL_CURRENT_PROGRAM, ¤tProgram); + + driver->glUseProgram(GetFixedColProgram(driver, driver->GetReplay(), resources, currentProgram)); + } if(test < OpenGLTest::StencilTest) { driver->glDisable(eGL_STENCIL_TEST); @@ -1457,6 +1503,7 @@ void QueryFailedTests(WrappedOpenGL *driver, GLPixelHistoryResources &resources, history[i].depthBoundsFailed = failedTest == OpenGLTest::DepthBounds; history[i].stencilTestFailed = failedTest == OpenGLTest::StencilTest; history[i].depthTestFailed = failedTest == OpenGLTest::DepthTest; + history[i].shaderDiscarded = failedTest == OpenGLTest::Discard; history[i].backfaceCulled = failedTest == OpenGLTest::FaceCulling; history[i].sampleMasked = failedTest == OpenGLTest::SampleMask; }