Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions RenderSystems/GLSupport/include/GLSL/OgreGLSLPreprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,13 @@ namespace Ogre {
/// A stack of 32 booleans packed into one value :)
unsigned EnableOutput;
unsigned EnableElif;
unsigned Passthrough;
/// The list of macros defined so far
std::forward_list<Macro> MacroList;

/// List of define prefixes to pass through
std::vector<const char*> PassthroughList;

/**
* Private constructor to re-parse a single token.
*/
Expand Down Expand Up @@ -444,6 +448,14 @@ namespace Ogre {
/// Destroy the preprocessor object
virtual ~CPreprocessor ();

/** Define-prefixes from this list cause the #if directive not to be expanded

useful to test GLSL extension support at runtime
@param lst the list. Supposed to contain string literals. Make sure that the memory pointed
is available throughout the lifetime of CPreprocessor otherwise.
*/
void setPassthroughDefines(const std::vector<const char*>& lst) { PassthroughList = lst; }

/**
* Define a macro without parameters.
* @param iMacroName
Expand Down
46 changes: 38 additions & 8 deletions RenderSystems/GLSupport/src/GLSL/OgreGLSLPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,7 @@ namespace Ogre {

EnableElif <<= 1;
EnableOutput <<= 1;
Passthrough <<= 1;
if (val)
EnableOutput |= 1;
else
Expand Down Expand Up @@ -1118,6 +1119,22 @@ namespace Ogre {
return true;
}

static const char* strnstr(const char* haystack, size_t length, const char* needle)
{
size_t needle_length = strlen(needle);
for (size_t i = 0; i < length; i++)
{
if (i + needle_length > length)
{
return NULL;
}
if (strncmp(&haystack[i], needle, needle_length) == 0)
{
return &haystack[i];
}
}
return NULL;
}

CPreprocessor::Token CPreprocessor::HandleDirective (Token &iToken, int iLine)
{
Expand Down Expand Up @@ -1178,6 +1195,19 @@ namespace Ogre {
}
Done:

if (strncmp(directive, "if", 2) == 0)
{
for(auto def : PassthroughList)
{
if(strnstr(t.String, t.Length, def))
{
Passthrough |= 1;
}
}
}

bool passthrough = Passthrough & 1;

#define IS_DIRECTIVE(s) \
(dirlen == strlen(s) && (strncmp (directive, s, dirlen) == 0))

Expand All @@ -1188,9 +1218,9 @@ namespace Ogre {
rc = HandleDefine (t, iLine);
else if (IS_DIRECTIVE ("undef") && outputEnabled)
rc = HandleUnDef (t, iLine);
else if (IS_DIRECTIVE ("ifdef"))
else if (IS_DIRECTIVE ("ifdef") && !passthrough)
rc = HandleIfDef (t, iLine);
else if (IS_DIRECTIVE ("ifndef"))
else if (IS_DIRECTIVE ("ifndef") && !passthrough)
{
rc = HandleIfDef (t, iLine);
if (rc)
Expand All @@ -1199,19 +1229,18 @@ namespace Ogre {
EnableElif ^= 1;
}
}
else if (IS_DIRECTIVE ("if"))
else if (IS_DIRECTIVE ("if") && !passthrough)
rc = HandleIf (t, iLine);
else if (IS_DIRECTIVE ("elif"))
else if (IS_DIRECTIVE ("elif") && !passthrough)
rc = HandleElif (t, iLine);

else if (IS_DIRECTIVE ("else"))
else if (IS_DIRECTIVE ("else") && !passthrough)
rc = HandleElse (t, iLine);
else if (IS_DIRECTIVE ("endif"))
else if (IS_DIRECTIVE ("endif") && !passthrough)
rc = HandleEndIf (t, iLine);
else
{
//Error (iLine, "Unknown preprocessor directive", &iToken);
//return Token (Token::TK_ERROR);
if(IS_DIRECTIVE ("endif")) Passthrough &= ~1;

// Unknown preprocessor directive, roll back and pass through
Line = old_line;
Expand Down Expand Up @@ -1272,6 +1301,7 @@ namespace Ogre {
BOL = true;
EnableOutput = 1;
EnableElif = 0;
Passthrough = 0;

// Accumulate output into this token
Token output (Token::TK_TEXT);
Expand Down
2 changes: 1 addition & 1 deletion RenderSystems/GLSupport/src/GLSL/OgreGLSLShaderCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ namespace Ogre {
// Preprocess the GLSL shader in order to get a clean source
CPreprocessor cpp;

cpp.setPassthroughDefines({"GL_ARB", "GL_EXT", "GL_OES", "__VERSION__"});
// Define "predefined" macros.
// TODO: decide, should we define __VERSION__, and with what value.
if(getLanguage() == "glsles")
cpp.Define("GL_ES", 5, 1);

Expand Down
17 changes: 17 additions & 0 deletions Tests/RenderSystems/GLSupport/GLSLTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ TEST(CPreprocessorTests, MacroExpansion)
free(out);
}

TEST(CPreprocessorTests, Passthrough)
{
CPreprocessor prep;
prep.setPassthroughDefines({"GL_ARB"});
String src = "#ifdef GL_ARB_shader_texture_lod\n"
"textureCubeLod\n"
"#else\n"
"textureCube\n"
"#endif";

size_t olen;
char* out = prep.Parse(src.c_str(), src.size(), olen);
String str(out, olen);
EXPECT_EQ(src, str);
free(out);
}

TEST(CPreprocessorTests, IfDef)
{
CPreprocessor prep;
Expand Down