Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ACGL
acgl
Commits
1903dc9b
Commit
1903dc9b
authored
Jul 02, 2013
by
Philip Trettner
Browse files
Made shader parser extendable
parent
3db02023
Changes
2
Hide whitespace changes
Inline
Side-by-side
include/ACGL/OpenGL/Objects/Shader.hh
View file @
1903dc9b
...
...
@@ -28,6 +28,12 @@
namespace
ACGL
{
namespace
OpenGL
{
/**
* @brief ShaderParser for processing shader source code
*
* Subclass this and provide alternative ShaderParserFactories to Creators in order to implement custom shader processing
* Override processPragma in order to create custom pragma handling
*/
class
ShaderParser
{
ACGL_NOT_COPYABLE
(
ShaderParser
)
...
...
@@ -45,10 +51,59 @@ public:
//! 0 == original file
std
::
string
getFileName
(
unsigned
int
i
)
const
{
return
mSourceFileNames
[
i
];
}
protected:
/**
* @brief registers a new SourceFile
* @param _name name of the file (may be an actual filename or a name that indicates automatic generation)
* @return an ID that is to be used in #line statements and getFileName-Index.
*/
int
registerSourceFile
(
std
::
string
const
&
_name
);
/**
* @brief adds a chunk of source to the shader
* @param _source source string
*
* Does not have to correspond to files
*/
void
addSource
(
std
::
string
const
&
_source
);
/**
* @brief constructs a line directive
* @param _lineNumber line number (starts at 1)
* @param _fileID file ID (usually from registerSourceFile)
* @return a string with the format "#line lineNr fileID\n"
*/
std
::
string
lineDirective
(
int
_lineNumber
,
int
_fileID
)
const
;
/**
* @brief processes a custom Pragma directive
* @param _tokens vector of tokens after #pragma (e.g. "#pragma myPragma 5" results in _tokens = { "myPragma", "5" })
*
* Override this function to implement custom pragma handling (no need to call base function)
*
* Recommended behavior:
* - Check if pragma is valid
* - Start with lineNumber 1
* - Register appropriate source file (using registerSourceFile(...))
* - Initialize source content with lineDirective(lineNumber, fileID)
* - Add custom source content
* - Call addSource(...) with your source content
*/
virtual
void
processPragma
(
std
::
vector
<
std
::
string
>
const
&
_tokens
)
{
}
/**
* @brief reads in a source file from file system
* @param _filename filename of the source file
*
* Override this function to implement custom file reading functionality
*/
virtual
void
readin
(
const
std
::
string
&
_filename
);
private:
void
readin
(
const
std
::
string
&
_filename
);
bool
lineContainsVersion
(
const
std
::
string
&
line
,
unsigned
int
&
version
);
bool
lineContainsImport
(
const
std
::
string
&
line
,
std
::
string
&
filename
);
bool
lineContainsPragma
(
const
std
::
string
&
line
,
std
::
vector
<
std
::
string
>
&
pragmaToken
);
std
::
vector
<
std
::
string
>
mSources
;
std
::
vector
<
std
::
string
>
mSourceFileNames
;
// holds at least one filename
...
...
src/ACGL/OpenGL/Objects/Shader.cc
View file @
1903dc9b
...
...
@@ -224,6 +224,20 @@ bool ShaderParser::lineContainsImport( const std::string &line, std::string &fil
return
false
;
}
bool
ShaderParser
::
lineContainsPragma
(
const
std
::
string
&
line
,
std
::
vector
<
std
::
string
>
&
pragmaToken
)
{
std
::
vector
<
std
::
string
>
token
=
StringHelpers
::
split
(
line
,
' '
);
if
(
token
.
size
()
>=
2
&&
token
[
0
]
==
"#pragma"
)
{
pragmaToken
.
clear
();
pragmaToken
.
insert
(
pragmaToken
.
begin
(),
token
.
begin
()
+
1
,
token
.
end
());
return
true
;
}
return
false
;
}
std
::
string
ShaderParser
::
getFileNamesPrintable
()
const
{
std
::
string
rString
;
...
...
@@ -233,6 +247,22 @@ std::string ShaderParser::getFileNamesPrintable() const
return
rString
;
}
int
ShaderParser
::
registerSourceFile
(
const
std
::
string
&
_name
)
{
mSourceFileNames
.
push_back
(
_name
);
return
mSourceFileNames
.
size
();
}
void
ShaderParser
::
addSource
(
const
std
::
string
&
_source
)
{
mSources
.
push_back
(
_source
);
}
std
::
string
ShaderParser
::
lineDirective
(
int
_lineNumber
,
int
_fileID
)
const
{
return
"#line "
+
StringHelpers
::
toString
(
_lineNumber
)
+
" "
+
StringHelpers
::
toString
(
_fileID
)
+
"
\n
"
;
}
void
ShaderParser
::
readin
(
const
std
::
string
&
_filename
)
{
std
::
string
line
=
""
;
...
...
@@ -240,11 +270,10 @@ void ShaderParser::readin( const std::string &_filename )
std
::
ifstream
fileStream
(
_filename
.
c_str
(),
std
::
ifstream
::
in
);
unsigned
int
lineNumber
=
1
;
mSourceFileNames
.
push_back
(
_filename
);
unsigned
int
fileNumber
=
mSourceFileNames
.
size
();
unsigned
int
fileNumber
=
registerSourceFile
(
_filename
);
// define the file and line number to get correct errors from the shader compiler:
std
::
string
fileContent
=
"#
line
"
+
StringHelpers
::
toString
(
lineNumber
)
+
" "
+
StringHelpers
::
toString
(
fileNumber
)
+
"
\n
"
;
std
::
string
fileContent
=
line
Directive
(
lineNumber
,
fileNumber
);
//debug() << "parse file " << _filename << std::endl;
...
...
@@ -256,37 +285,56 @@ void ShaderParser::readin( const std::string &_filename )
unsigned
int
version
;
std
::
string
fileToImport
;
if
(
lineContainsVersion
(
line
,
version
)
)
{
std
::
vector
<
std
::
string
>
pragmaToken
;
if
(
lineContainsVersion
(
line
,
version
)
)
{
mMaxVersion
=
std
::
max
(
version
,
mMaxVersion
);
fileContent
+=
"
\n
"
;
// remove the #version but keep a newline
lineNumber
++
;
}
else
if
(
lineContainsImport
(
line
,
fileToImport
)
)
{
}
else
if
(
lineContainsImport
(
line
,
fileToImport
)
)
{
// handle import
if
(
fileToImport
[
0
]
!=
'/'
)
{
// it's a relative path:
// remove "./" in case this was given explicitly:
if
(
fileToImport
.
size
()
>
2
&&
fileToImport
[
0
]
==
'.'
&&
fileToImport
[
1
]
==
'/'
)
{
if
(
fileToImport
.
size
()
>
2
&&
fileToImport
[
0
]
==
'.'
&&
fileToImport
[
1
]
==
'/'
)
fileToImport
=
fileToImport
.
substr
(
2
,
fileToImport
.
size
()
-
2
);
}
std
::
string
path
,
file
;
StringHelpers
::
splitLastFileOrFolder
(
_filename
,
path
,
file
);
fileToImport
=
path
+
"/"
+
fileToImport
;
}
if
(
std
::
find
(
mSourceFileNames
.
begin
(),
mSourceFileNames
.
end
(),
fileToImport
)
==
mSourceFileNames
.
end
())
{
if
(
std
::
find
(
mSourceFileNames
.
begin
(),
mSourceFileNames
.
end
(),
fileToImport
)
==
mSourceFileNames
.
end
())
{
// not imported yet:
// push what we have till now:
m
Source
s
.
push_back
(
fileContent
);
add
Source
(
fileContent
);
readin
(
fileToImport
);
lineNumber
++
;
fileContent
=
"#line "
+
StringHelpers
::
toString
(
lineNumber
)
+
" "
+
StringHelpers
::
toString
(
fileNumber
)
+
"
\n
"
;
}
else
{
fileContent
=
lineDirective
(
lineNumber
,
fileNumber
);
}
else
{
// ignore:
lineNumber
++
;
fileContent
+=
"
\n
"
;
}
}
else
{
}
else
if
(
lineContainsPragma
(
line
,
pragmaToken
)
)
{
// push what we have till now:
addSource
(
fileContent
);
// let subclasses process their own pragmas
processPragma
(
pragmaToken
);
// continue with a fresh chunk of source
lineNumber
++
;
fileContent
=
lineDirective
(
lineNumber
,
fileNumber
);
}
else
{
fileContent
+=
line
+
"
\n
"
;
lineNumber
++
;
}
...
...
@@ -301,5 +349,5 @@ void ShaderParser::readin( const std::string &_filename )
//debug() << "file: " << fileContent << std::endl;
m
Source
s
.
push_back
(
fileContent
);
add
Source
(
fileContent
);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment