Skip to content

Commit 28210b6

Browse files
committed
Generalise shader post-processing
Will be required for PushBuffer. Also added back `_isTexture` to `GLUniform` because it will also be needed for PushBuffer.
1 parent d314a57 commit 28210b6

File tree

2 files changed

+88
-64
lines changed

2 files changed

+88
-64
lines changed

src/engine/renderer/gl_shader.cpp

Lines changed: 76 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,22 +1514,75 @@ void GLShaderManager::SaveShaderBinary( ShaderProgramDescriptor* descriptor ) {
15141514
cacheSaveCount++;
15151515
}
15161516

1517+
std::string GLShaderManager::RemoveUniformsFromShaderText( const std::string& shaderText, const std::vector<GLUniform*>& uniforms ) {
1518+
std::istringstream shaderTextStream( shaderText );
1519+
std::string shaderMain;
1520+
1521+
std::string line;
1522+
/* Remove local uniform declarations, but avoid removing uniform / storage blocks;
1523+
* their values will be sourced from a buffer instead
1524+
* Global uniforms (like u_ViewOrigin) will still be set as regular uniforms */
1525+
while ( std::getline( shaderTextStream, line, '\n' ) ) {
1526+
bool skip = false;
1527+
if ( line.find( "uniform" ) < line.find( "//" ) && line.find( ";" ) != std::string::npos ) {
1528+
for ( GLUniform* uniform : uniforms ) {
1529+
const size_t pos = line.find( uniform->_name );
1530+
if ( pos != std::string::npos && !Str::cisalpha( line[pos + uniform->_name.size()] ) ) {
1531+
skip = true;
1532+
break;
1533+
}
1534+
}
1535+
}
1536+
1537+
if ( skip ) {
1538+
continue;
1539+
}
1540+
1541+
shaderMain += line + "\n";
1542+
}
1543+
1544+
return shaderMain;
1545+
}
1546+
1547+
void GLShaderManager::GenerateUniformStructDefinesText( const std::vector<GLUniform*>& uniforms, const uint32_t padding,
1548+
const uint32_t paddingCount, const std::string& definesName,
1549+
std::string& uniformStruct, std::string& uniformDefines ) {
1550+
for ( GLUniform* uniform : uniforms ) {
1551+
uniformStruct += " " + ( uniform->_isTexture ? "uvec2" : uniform->_type ) + " " + uniform->_name;
1552+
1553+
if ( uniform->_components ) {
1554+
uniformStruct += "[" + std::to_string( uniform->_components ) + "]";
1555+
}
1556+
uniformStruct += ";\n";
1557+
1558+
uniformDefines += "#define ";
1559+
uniformDefines += uniform->_name;
1560+
1561+
if ( uniform->_isTexture ) {
1562+
uniformDefines += "_initial";
1563+
}
1564+
1565+
uniformDefines += " " + definesName + ".";
1566+
uniformDefines += uniform->_name;
1567+
1568+
uniformDefines += "\n";
1569+
}
1570+
1571+
// Array of structs is aligned to the largest member of the struct
1572+
for ( uint32_t i = 0; i < padding; i++ ) {
1573+
uniformStruct += " int uniform_padding" + std::to_string( i + paddingCount );
1574+
uniformStruct += ";\n";
1575+
}
1576+
1577+
uniformDefines += "\n";
1578+
}
1579+
15171580
// This will generate all the extra code for material system shaders
15181581
std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::string& shaderText, const uint32_t offset ) {
15191582
if ( !shader->std430Size ) {
15201583
return shaderText;
15211584
}
15221585

1523-
std::string newShaderText;
1524-
std::string materialStruct = "\nstruct Material {\n";
1525-
// 6 kb for materials
1526-
const uint32_t count = ( 4096 + 2048 ) / shader->GetSTD430Size();
1527-
std::string materialBlock = "layout(std140, binding = "
1528-
+ std::to_string( BufferBind::MATERIALS )
1529-
+ ") uniform materialsUBO {\n"
1530-
" Material materials[" + std::to_string( count ) + "]; \n"
1531-
"};\n\n";
1532-
15331586
std::string texBuf = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ?
15341587
"layout(std140, binding = "
15351588
+ std::to_string( BufferBind::TEX_DATA )
@@ -1569,7 +1622,6 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
15691622
"};\n\n"
15701623
"#define u_LightMap_initial lightMapData[( baseInstance >> 24 ) & 0xFF].u_LightMap\n"
15711624
"#define u_DeluxeMap_initial lightMapData[( baseInstance >> 24 ) & 0xFF].u_DeluxeMap\n\n";
1572-
std::string materialDefines;
15731625

15741626
/* Generate the struct and defines in the form of:
15751627
* struct Material {
@@ -1582,62 +1634,24 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
15821634
* #define uniformx materials[baseInstance].uniformx
15831635
*/
15841636

1585-
for( GLUniform* uniform : shader->_materialSystemUniforms ) {
1586-
materialStruct += " " + uniform->_type + " " + uniform->_name;
1587-
1588-
if ( uniform->_components ) {
1589-
materialStruct += "[" + std::to_string( uniform->_components ) + "]";
1590-
}
1591-
materialStruct += ";\n";
1592-
1593-
materialDefines += "#define ";
1594-
materialDefines += uniform->_name;
1595-
1596-
materialDefines += " materials[baseInstance & 0xFFF].";
1597-
materialDefines += uniform->_name;
1598-
1599-
materialDefines += "\n";
1600-
}
1601-
1602-
// Array of structs is aligned to the largest member of the struct
1603-
for ( uint i = 0; i < shader->padding; i++ ) {
1604-
materialStruct += " int material_padding" + std::to_string( i );
1605-
materialStruct += ";\n";
1606-
}
1637+
std::string materialStruct = "\nstruct Material {\n";
1638+
std::string materialDefines;
1639+
GenerateUniformStructDefinesText( shader->_materialSystemUniforms, shader->padding,
1640+
0, "materials[baseInstance & 0xFFF]", materialStruct, materialDefines );
16071641

16081642
materialStruct += "};\n\n";
1609-
materialDefines += "\n";
16101643

1611-
std::istringstream shaderTextStream( shaderText );
1612-
std::string shaderMain;
1613-
1614-
std::string line;
1615-
1616-
/* Remove local uniform declarations, but avoid removing uniform / storage blocks;
1617-
* their values will be sourced from a buffer instead
1618-
* Global uniforms (like u_ViewOrigin) will still be set as regular uniforms */
1619-
while( std::getline( shaderTextStream, line, '\n' ) ) {
1620-
bool skip = false;
1621-
if ( line.find( "uniform" ) < line.find( "//" ) && line.find( ";" ) != std::string::npos ) {
1622-
for ( GLUniform* uniform : shader->_materialSystemUniforms ) {
1623-
const size_t pos = line.find( uniform->_name );
1624-
if ( pos != std::string::npos && !Str::cisalpha( line[pos + strlen( uniform->_name.c_str() )] ) ) {
1625-
skip = true;
1626-
break;
1627-
}
1628-
}
1629-
}
1630-
1631-
if ( skip ) {
1632-
continue;
1633-
}
1634-
1635-
shaderMain += line + "\n";
1636-
}
1644+
// 6 kb for materials
1645+
const uint32_t count = ( 4096 + 2048 ) / shader->GetSTD430Size();
1646+
std::string materialBlock = "layout(std140, binding = "
1647+
+ std::to_string( BufferBind::MATERIALS )
1648+
+ ") uniform materialsUBO {\n"
1649+
" Material materials[" + std::to_string( count ) + "]; \n"
1650+
"};\n\n";
16371651

1638-
materialDefines += "\n";
1652+
std::string shaderMain = RemoveUniformsFromShaderText( shaderText, shader->_materialSystemUniforms );
16391653

1640-
newShaderText = "#define USE_MATERIAL_SYSTEM\n" + materialStruct + materialBlock + texDataBlock + materialDefines;
1654+
std::string newShaderText = "#define USE_MATERIAL_SYSTEM\n" + materialStruct + materialBlock + texDataBlock + materialDefines;
16411655
shaderMain.insert( offset, newShaderText );
16421656
return shaderMain;
16431657
}

src/engine/renderer/gl_shader.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,20 +322,23 @@ class GLUniform {
322322

323323
const bool _global; // This uniform won't go into the materials UBO if true
324324
const int _components;
325+
const bool _isTexture;
325326

326327
protected:
327328
GLShader* _shader;
328329
size_t _firewallIndex;
329330
size_t _locationIndex;
330331

331332
GLUniform( GLShader* shader, const char* name, const char* type, const GLuint std430Size, const GLuint std430Alignment,
332-
const bool global, const int components = 0 ) :
333+
const bool global, const int components = 0,
334+
const bool isTexture = false ) :
333335
_name( name ),
334336
_type( type ),
335337
_std430Size( std430Size ),
336338
_std430Alignment( std430Alignment ),
337339
_global( global ),
338340
_components( components ),
341+
_isTexture( isTexture ),
339342
_shader( shader ) {
340343
_shader->RegisterUniform( this );
341344
}
@@ -458,14 +461,21 @@ class GLShaderManager {
458461
ShaderProgramDescriptor* out );
459462
void SaveShaderBinary( ShaderProgramDescriptor* descriptor );
460463

464+
void GenerateUniformStructDefinesText( const std::vector<GLUniform*>& uniforms, const uint32_t padding,
465+
const uint32_t paddingCount, const std::string& definesName,
466+
std::string& uniformStruct, std::string& uniformDefines );
467+
std::string RemoveUniformsFromShaderText( const std::string& shaderText, const std::vector<GLUniform*>& uniforms );
461468
std::string ShaderPostProcess( GLShader *shader, const std::string& shaderText, const uint32_t offset );
462469
std::string BuildDeformShaderText( const std::string& steps );
463470
std::string ProcessInserts( const std::string& shaderText ) const;
471+
464472
void LinkProgram( GLuint program ) const;
465473
void BindAttribLocations( GLuint program ) const;
466474
void PrintShaderSource( Str::StringRef programName, GLuint object, std::vector<InfoLogEntry>& infoLogLines ) const;
475+
467476
std::vector<InfoLogEntry> ParseInfoLog( const std::string& infoLog ) const;
468477
std::string GetInfoLog( GLuint object ) const;
478+
469479
std::string BuildShaderText( const std::string& mainShaderText, const std::vector<GLHeader*>& headers, const std::string& macros );
470480
ShaderDescriptor* FindShader( const std::string& name, const std::string& mainText,
471481
const GLenum type, const std::vector<GLHeader*>& headers,
@@ -478,7 +488,7 @@ class GLUniformSampler : protected GLUniform {
478488
protected:
479489
GLUniformSampler( GLShader* shader, const char* name, const char* type ) :
480490
GLUniform( shader, name, type, glConfig2.bindlessTexturesAvailable ? 2 : 1,
481-
glConfig2.bindlessTexturesAvailable ? 2 : 1, true ) {
491+
glConfig2.bindlessTexturesAvailable ? 2 : 1, true, 0, true ) {
482492
}
483493

484494
inline GLint GetLocation() {

0 commit comments

Comments
 (0)