diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index a5a8b6e24..6feaae47f 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -96,6 +96,69 @@ void copy(rdctype::array &outvars, const vector sources, bool &pointSizeUsed, bool &clipDistanceUsed) +{ + pointSizeUsed = false; + clipDistanceUsed = false; + + for(size_t i=0; i < sources.size(); i++) + { + string &s = sources[i]; + + size_t offs = 0; + + while(true) + { + offs = s.find("gl_PointSize", offs); + + if(offs == string::npos) + break; + + // consider gl_PointSize used if we encounter a '=' before a ';' or the end of the string + + while(offs < s.length()) + { + if(s[offs] == '=') + { + pointSizeUsed = true; + break; + } + + if(s[offs] == ';') + break; + + offs++; + } + } + + offs = 0; + + while(true) + { + offs = s.find("gl_ClipDistance", offs); + + if(offs == string::npos) + break; + + // consider gl_ClipDistance used if we encounter a '=' before a ';' or the end of the string + + while(offs < s.length()) + { + if(s[offs] == '=') + { + clipDistanceUsed = true; + break; + } + + if(s[offs] == ';') + break; + + offs++; + } + } + } +} + // little utility function that if necessary emulates glCreateShaderProgramv functionality but using glCompileShaderIncludeARB static GLuint CreateSepProgram(const GLHookSet &gl, GLenum type, GLsizei numSources, const char **sources, GLsizei numPaths, const char **paths) { @@ -578,7 +641,7 @@ void ReconstructVarTree(const GLHookSet &gl, GLenum query, GLuint sepProg, GLuin } } -void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl) +void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl, bool pointSizeUsed, bool clipDistanceUsed) { refl.DebugInfo.entryFunc = "main"; refl.DebugInfo.compileFlags = 0; @@ -1424,6 +1487,13 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, #define IS_BUILTIN(builtin) !strncmp(nm, builtin, sizeof(builtin)-1) + // if these weren't used, they were probably added just to make a separable program + // (either by us or the program originally). Skip them from the output signature + if(IS_BUILTIN("gl_PointSize") && !pointSizeUsed) + continue; + if(IS_BUILTIN("gl_ClipDistance") && !clipDistanceUsed) + continue; + // VS built-in inputs if(IS_BUILTIN("gl_VertexID")) sig.systemValue = eAttr_VertexIndex; if(IS_BUILTIN("gl_InstanceID")) sig.systemValue = eAttr_InstanceIndex; diff --git a/renderdoc/driver/gl/gl_shader_refl.h b/renderdoc/driver/gl/gl_shader_refl.h index b9c9a6e21..2c8adcff7 100644 --- a/renderdoc/driver/gl/gl_shader_refl.h +++ b/renderdoc/driver/gl/gl_shader_refl.h @@ -26,5 +26,6 @@ #include "replay/replay_driver.h" -void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl); +void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl, bool pointSizeUsed, bool clipDistanceUsed); GLuint MakeSeparableShaderProgram(const GLHookSet &gl, GLenum type, std::vector sources, vector *includepaths); +void CheckVertexOutputUses(std::vector sources, bool &pointSizeUsed, bool &clipDistanceUsed); diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index ba09bcfff..7a308db88 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -152,6 +152,9 @@ bool WrappedOpenGL::Serialise_glCompileShader(GLuint shader) auto &shadDetails = m_Shaders[liveId]; + bool pointSizeUsed = false, clipDistanceUsed = false; + if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed); + GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, NULL); if(sepProg == 0) @@ -161,7 +164,7 @@ bool WrappedOpenGL::Serialise_glCompileShader(GLuint shader) else { shadDetails.prog = sepProg; - MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection); + MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++) @@ -341,10 +344,13 @@ bool WrappedOpenGL::Serialise_glCreateShaderProgramv(GLuint program, GLenum type auto &shadDetails = m_Shaders[liveId]; + bool pointSizeUsed = false, clipDistanceUsed = false; + if(Type == eGL_VERTEX_SHADER) CheckVertexOutputUses(src, pointSizeUsed, clipDistanceUsed); + shadDetails.type = Type; shadDetails.sources.swap(src); shadDetails.prog = real; - MakeShaderReflection(m_Real, Type, real, shadDetails.reflection); + MakeShaderReflection(m_Real, Type, real, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++) @@ -1063,6 +1069,9 @@ bool WrappedOpenGL::Serialise_glCompileShaderIncludeARB(GLuint shader, GLsizei c for(int32_t i=0; i < Count; i++) shadDetails.includepaths.push_back(pathstrings[i]); + bool pointSizeUsed = false, clipDistanceUsed = false; + if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed); + GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, &paths); if(sepProg == 0) @@ -1072,7 +1081,7 @@ bool WrappedOpenGL::Serialise_glCompileShaderIncludeARB(GLuint shader, GLsizei c else { shadDetails.prog = sepProg; - MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection); + MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++)