From c9a2d4cca8a1a9d77684caa680ab059ad94da2b0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 13 Feb 2018 19:33:37 +0000 Subject: [PATCH] Fetch declared #version for each shader (will be needed on GLES) --- renderdoc/driver/gl/gl_driver.h | 3 +- renderdoc/driver/gl/gl_shader_refl.cpp | 20 +++++ renderdoc/driver/gl/gl_shader_refl.h | 1 + .../driver/gl/wrappers/gl_shader_funcs.cpp | 81 +++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 11a68391b..2bc7fe10c 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -288,7 +288,7 @@ private: struct ShaderData { - ShaderData() : type(eGL_NONE), prog(0) {} + ShaderData() : type(eGL_NONE), prog(0), version(0) {} GLenum type; vector sources; vector includepaths; @@ -296,6 +296,7 @@ private: std::string disassembly; ShaderReflection reflection; GLuint prog; + int version; void Compile(WrappedOpenGL &gl, ResourceId id, GLuint realShader); }; diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index a04c59a42..d822de364 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -835,6 +835,26 @@ void ReconstructVarTree(const GLHookSet &gl, GLenum query, GLuint sepProg, GLuin } } +int ParseVersionStatement(const char *version) +{ + if(strncmp(version, "#version", 8)) + return 0; + + version += 8; + while(isspace(*version)) + version++; + + int ret = 0; + while(*version >= '0' && *version <= '9') + { + ret *= 10; + ret += int(*version) - int('0'); + version++; + } + + return ret; +} + void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl, bool pointSizeUsed, bool clipDistanceUsed) { diff --git a/renderdoc/driver/gl/gl_shader_refl.h b/renderdoc/driver/gl/gl_shader_refl.h index 55b40a0ba..b352d41ac 100644 --- a/renderdoc/driver/gl/gl_shader_refl.h +++ b/renderdoc/driver/gl/gl_shader_refl.h @@ -27,6 +27,7 @@ class WrappedOpenGL; +int ParseVersionStatement(const char *version); void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl, bool pointSizeUsed, bool clipDistanceUsed); GLuint MakeSeparableShaderProgram(WrappedOpenGL &gl, GLenum type, std::vector sources, diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index 9841dea8d..2227be1df 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -77,6 +77,87 @@ void WrappedOpenGL::ShaderData::Compile(WrappedOpenGL &gl, ResourceId id, GLuint concatenated += sources[i]; } + size_t offs = concatenated.find("#version"); + + if(offs == std::string::npos) + { + // if there's no #version it's assumed to be 100 which we set below + version = 0; + } + else + { + // see if we find a second result after the first + size_t offs2 = concatenated.find("#version", offs + 1); + + if(offs2 == std::string::npos) + { + version = ParseVersionStatement(concatenated.c_str() + offs); + } + else + { + // slow path, multiple #version matches so the first one might be in a comment. We need to + // search from the start, past comments and whitespace, to find the first real #version. + const char *search = concatenated.c_str(); + const char *end = search + concatenated.size(); + + while(search < end) + { + // skip whitespace + if(isspace(*search)) + { + search++; + continue; + } + + // skip single-line C++ style comments + if(search + 1 < end && search[0] == '/' && search[1] == '/') + { + // continue until the next newline + while(search < end && search[0] != '\r' && search[0] != '\n') + search++; + + // continue, the whitespace skip above will skip the newline + continue; + } + + // skip multi-line C style comments + if(search + 1 < end && search[0] == '/' && search[1] == '*') + { + // continue until the ending marker + while(search + 1 < end && (search[0] != '*' || search[1] != '/')) + search++; + + // skip the end marker + search += 2; + + // continue, the whitespace skip above will skip the newline + continue; + } + + // missing #version is valid, so just exit + if(search + sizeof("#version") > end) + { + RDCERR("Bad shader - reached end of text after skipping all comments and whitespace"); + break; + } + + std::string versionText(search, search + sizeof("#version") - 1); + + // if we found the version, parse it + if(versionText == "#version") + version = ParseVersionStatement(search); + + // otherwise break - a missing #version is valid, and a legal #version cannot occur anywhere + // after this point. + break; + } + } + } + + // default to version 100 + if(version == 0) + version = 100; + reflection.encoding = ShaderEncoding::GLSL; reflection.rawBytes.assign((byte *)concatenated.c_str(), concatenated.size());