Fetch declared #version for each shader (will be needed on GLES)

This commit is contained in:
baldurk
2018-02-13 21:10:08 +00:00
parent 5c859b20a6
commit c9a2d4cca8
4 changed files with 104 additions and 1 deletions
+2 -1
View File
@@ -288,7 +288,7 @@ private:
struct ShaderData
{
ShaderData() : type(eGL_NONE), prog(0) {}
ShaderData() : type(eGL_NONE), prog(0), version(0) {}
GLenum type;
vector<string> sources;
vector<string> includepaths;
@@ -296,6 +296,7 @@ private:
std::string disassembly;
ShaderReflection reflection;
GLuint prog;
int version;
void Compile(WrappedOpenGL &gl, ResourceId id, GLuint realShader);
};
+20
View File
@@ -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)
{
+1
View File
@@ -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<std::string> sources,
@@ -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());