From f8e8ae13912b2eace3b53194c9b148a2ff8e664d Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 26 Feb 2015 17:58:41 +0000 Subject: [PATCH] Add in gl_PerVertex redeclarations individually * This means the redeclarations are a bit more flexible if a shader (like a geometry shader) redeclares one already, but not the other, we'll only substitute in the missing one. * Note this code is still a bit flakey e.g. in edge cases like if someone puts "in gl_PerVertex" in a comment, then it will fail. I want to avoid putting a full parser in, but perhaps stripping the source of any comments is a reasonable future step. --- renderdoc/driver/gl/gl_shader_refl.cpp | 189 +++++++++++++++---------- 1 file changed, 113 insertions(+), 76 deletions(-) diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index 0a7f6322b..d95a46f43 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -200,16 +200,24 @@ static GLuint CreateSepProgram(const GLHookSet &gl, GLenum type, GLsizei numSour GLuint MakeSeparableShaderProgram(const GLHookSet &gl, GLenum type, vector sources, vector *includepaths) { - string block = ""; + // in and out blocks are added separately, in case one is there already + const char *blockIdentifiers[2] = { "in gl_PerVertex", "out gl_PerVertex" }; + string blocks[2] = { "", "" }; if(type == eGL_VERTEX_SHADER) - block = "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; };\n"; + { + blocks[1] = "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; };\n"; + } else if(type == eGL_TESS_CONTROL_SHADER) - block = "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];\n" \ - "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_out[];\n"; + { + blocks[0] = "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];\n"; + blocks[1] = "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_out[];\n"; + } else - block = "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];\n" \ - "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; };\n"; + { + blocks[0] = "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];\n"; + blocks[1] = "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; };\n"; + } const char **strings = new const char*[sources.size()]; for(size_t i=0; i < sources.size(); i++) @@ -242,90 +250,119 @@ GLuint MakeSeparableShaderProgram(const GLHookSet &gl, GLenum type, vector= '0' && src[it] <= '9') - ++it; - - // skip whitespace - while(it < len && (src[it] == ' ' || src[it] == '\t')) - ++it; - - if(!strncmp(&src[it], "core" , 4)) it += sizeof("core")-1; - if(!strncmp(&src[it], "compatibility", 13)) it += sizeof("compatibility")-1; - if(!strncmp(&src[it], "es" , 2)) it += sizeof("es")-1; - - // now skip past comments, and any #extension directives - while(it < len) + for(size_t i=0; i < sources.size(); i++) { - // skip whitespace - while(it < len && (src[it] == ' ' || src[it] == '\t' || src[it] == '\r' || src[it] == '\n')) - ++it; - - // skip C++ style comments - if(it+1 < len && src[it] == '/' && src[it+1] == '/') + // if we find the 'identifier' (ie. the block name), + // assume this block is already present and stop + if(sources[i].find(identifier) != string::npos) { - // keep going until the next newline - while(it < len && src[it] != '\r' && src[it] != '\n') - ++it; - - // skip more things - continue; + already = true; + break; } - - // skip extension directives - const char extDirective[] = "#extension"; - if(!strncmp(src.c_str()+it, extDirective, sizeof(extDirective)-1) && - it+sizeof(extDirective)-1 < len && - (src[it+sizeof(extDirective)-1] == ' ' || src[it+sizeof(extDirective)-1] == '\t')) - { - // keep going until the next newline - while(it < len && src[it] != '\r' && src[it] != '\n') - ++it; - - // skip more things - continue; - } - - // skip C style comments - if(it+1 < len && src[it] == '/' && src[it+1] == '*') - { - // keep going until the we reach a */ - while(it+1 < len && (src[it] != '*' || src[it+1] != '/')) - ++it; - - // skip more things - continue; - } - - // nothing more to skip - break; } - substituted = src; + // only try and insert this block if the shader doesn't already have it + if(already) continue; - substituted.insert(it, block); + for(size_t i=0; i < sources.size(); i++) + { + string &src = sources[i]; - strings[i] = substituted.c_str(); + size_t len = src.length(); + size_t it = src.find("#version"); + if(it == string::npos) + continue; - break; + // skip #version + it += sizeof("#version")-1; + + // skip whitespace + while(it < len && (src[it] == ' ' || src[it] == '\t')) + ++it; + + // skip number + while(it < len && src[it] >= '0' && src[it] <= '9') + ++it; + + // skip whitespace + while(it < len && (src[it] == ' ' || src[it] == '\t')) + ++it; + + if(!strncmp(&src[it], "core" , 4)) it += sizeof("core")-1; + if(!strncmp(&src[it], "compatibility", 13)) it += sizeof("compatibility")-1; + if(!strncmp(&src[it], "es" , 2)) it += sizeof("es")-1; + + // now skip past comments, and any #extension directives + while(it < len) + { + // skip whitespace + while(it < len && (src[it] == ' ' || src[it] == '\t' || src[it] == '\r' || src[it] == '\n')) + ++it; + + // skip C++ style comments + if(it+1 < len && src[it] == '/' && src[it+1] == '/') + { + // keep going until the next newline + while(it < len && src[it] != '\r' && src[it] != '\n') + ++it; + + // skip more things + continue; + } + + // skip extension directives + const char extDirective[] = "#extension"; + if(!strncmp(src.c_str()+it, extDirective, sizeof(extDirective)-1) && + it+sizeof(extDirective)-1 < len && + (src[it+sizeof(extDirective)-1] == ' ' || src[it+sizeof(extDirective)-1] == '\t')) + { + // keep going until the next newline + while(it < len && src[it] != '\r' && src[it] != '\n') + ++it; + + // skip more things + continue; + } + + // skip C style comments + if(it+1 < len && src[it] == '/' && src[it+1] == '*') + { + // keep going until the we reach a */ + while(it+1 < len && (src[it] != '*' || src[it+1] != '/')) + ++it; + + // skip more things + continue; + } + + // nothing more to skip + break; + } + + substituted = src; + + substituted.insert(it, block); + + strings[i] = substituted.c_str(); + + break; + } } sepProg = CreateSepProgram(gl, type, (GLsizei)sources.size(), strings, numPaths, paths);