@@ -1523,10 +1523,10 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
15231523 std::string newShaderText;
15241524 std::string materialStruct = " \n struct Material {\n " ;
15251525 // 6 kb for materials
1526- const uint32_t count = ( 4096 + 2048 ) / shader->GetPaddedSize ();
1526+ const uint32_t count = ( 4096 + 2048 ) / shader->GetSTD430Size ();
15271527 std::string materialBlock = " layout(std140, binding = "
1528- + std::to_string ( BufferBind::MATERIALS )
1529- + " ) uniform materialsUBO {\n "
1528+ + std::to_string ( BufferBind::MATERIALS )
1529+ + " ) uniform materialsUBO {\n "
15301530 " Material materials[" + std::to_string ( count ) + " ]; \n "
15311531 " };\n\n " ;
15321532
@@ -1582,45 +1582,19 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
15821582 * #define uniformx materials[baseInstance].uniformx
15831583 */
15841584
1585- for ( GLUniform* uniform : shader->_uniforms ) {
1586- if ( uniform->IsGlobal () ) {
1587- continue ;
1588- }
1589-
1590- if ( !uniform->IsTexture () ) {
1591- materialStruct += " " + uniform->GetType () + " " + uniform->GetName ();
1592-
1593- if ( uniform->GetComponentSize () ) {
1594- materialStruct += " [ " + std::to_string ( uniform->GetComponentSize () ) + " ]" ;
1595- }
1596- materialStruct += " ;\n " ;
1597-
1598- // vec3 is aligned to 4 components, so just pad it with int
1599- // TODO: Try to move 1 component uniforms here to avoid wasting memory
1600- if ( uniform->GetSTD430Size () == 3 ) {
1601- materialStruct += " int " ;
1602- materialStruct += uniform->GetName ();
1603- materialStruct += " _padding;\n " ;
1604- }
1605- }
1585+ for ( GLUniform* uniform : shader->_materialSystemUniforms ) {
1586+ materialStruct += " " + uniform->GetType () + " " + uniform->GetName ();
16061587
1607- if ( uniform->IsTexture () ) {
1608- continue ;
1588+ if ( uniform->GetComponentSize () ) {
1589+ materialStruct += " [ " + std::to_string ( uniform-> GetComponentSize () ) + " ] " ;
16091590 }
1591+ materialStruct += " ;\n " ;
16101592
16111593 materialDefines += " #define " ;
16121594 materialDefines += uniform->GetName ();
16131595
1614- if ( uniform->IsTexture () ) { // Driver bug: AMD compiler crashes when using the SSBO value directly
1615- materialDefines += " _initial uvec2(" ; // We'll need this to create sampler objects later
1616- }
1617-
16181596 materialDefines += " materials[baseInstance & 0xFFF]." ;
16191597 materialDefines += uniform->GetName ();
1620-
1621- if ( uniform->IsTexture () ) {
1622- materialDefines += " )" ;
1623- }
16241598
16251599 materialDefines += " \n " ;
16261600 }
@@ -1645,13 +1619,11 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
16451619 while ( std::getline ( shaderTextStream, line, ' \n ' ) ) {
16461620 bool skip = false ;
16471621 if ( line.find ( " uniform" ) < line.find ( " //" ) && line.find ( " ;" ) != std::string::npos ) {
1648- for ( GLUniform* uniform : shader->_uniforms ) {
1649- if ( !uniform->IsGlobal () ) {
1650- const size_t pos = line.find ( uniform->GetName () );
1651- if ( pos != std::string::npos && !Str::cisalpha ( line[pos + strlen ( uniform->GetName () )] ) ) {
1652- skip = true ;
1653- break ;
1654- }
1622+ for ( GLUniform* uniform : shader->_materialSystemUniforms ) {
1623+ const size_t pos = line.find ( uniform->GetName () );
1624+ if ( pos != std::string::npos && !Str::cisalpha ( line[pos + strlen ( uniform->GetName () )] ) ) {
1625+ skip = true ;
1626+ break ;
16551627 }
16561628 }
16571629 }
@@ -1665,7 +1637,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
16651637
16661638 materialDefines += " \n " ;
16671639
1668- newShaderText = " #define USE_MATERIAL_SYSTEM\n " + materialStruct + materialBlock + texDataBlock + materialDefines; // + shaderMain;
1640+ newShaderText = " #define USE_MATERIAL_SYSTEM\n " + materialStruct + materialBlock + texDataBlock + materialDefines;
16691641 shaderMain.insert ( offset, newShaderText );
16701642 return shaderMain;
16711643}
@@ -2113,71 +2085,73 @@ uint32_t* GLUniform::WriteToBuffer( uint32_t* buffer ) {
21132085
21142086void GLShader::RegisterUniform ( GLUniform* uniform ) {
21152087 _uniforms.push_back ( uniform );
2116- textureCount += uniform->IsTexture ();
21172088}
21182089
21192090GLint GLShader::GetUniformLocation ( const GLchar *uniformName ) const {
21202091 ShaderProgramDescriptor* p = GetProgram ();
21212092 return glGetUniformLocation ( p->id , uniformName );
21222093}
21232094
2095+ static int FindUniformForAlignment ( std::vector<GLUniform*>& uniforms, const GLuint alignment ) {
2096+ for ( uint32_t i = 0 ; i < uniforms.size (); i++ ) {
2097+ if ( uniforms[i]->GetSTD430Size () == alignment ) {
2098+ return i;
2099+ }
2100+ }
2101+
2102+ if ( uniforms[uniforms.size () - 1 ]->GetSTD430Size () < alignment ) {
2103+ return uniforms.size () - 1 ;
2104+ }
2105+
2106+ return -1 ;
2107+ }
2108+
21242109// Compute std430 size/alignment and sort uniforms from highest to lowest alignment
21252110void GLShader::PostProcessUniforms () {
21262111 if ( !_useMaterialSystem ) {
21272112 return ;
21282113 }
21292114
2130- std::vector<GLUniform*> tmp;
2131-
2132- std::vector<GLUniform*> globalUniforms;
21332115 for ( GLUniform* uniform : _uniforms ) {
2134- if ( uniform->IsGlobal () || uniform-> IsTexture () ) {
2135- globalUniforms .emplace_back ( uniform );
2116+ if ( ! uniform->IsGlobal () ) {
2117+ _materialSystemUniforms .emplace_back ( uniform );
21362118 }
21372119 }
2138- for ( GLUniform* uniform : globalUniforms ) {
2139- _uniforms.erase ( std::remove ( _uniforms.begin (), _uniforms.end (), uniform ), _uniforms.end () );
2140- }
2120+
2121+ std::sort ( _materialSystemUniforms.begin (), _materialSystemUniforms.end (),
2122+ []( const GLUniform* lhs, const GLUniform* rhs ) {
2123+ return lhs->GetSTD430Size () > rhs->GetSTD430Size ();
2124+ }
2125+ );
21412126
21422127 // Sort uniforms from highest to lowest alignment so we don't need to pad uniforms (other than vec3s)
2143- const uint numUniforms = _uniforms .size ();
2144- GLuint structSize = 0 ;
2128+ const uint numUniforms = _materialSystemUniforms .size ();
2129+ std::vector<GLUniform*> tmp ;
21452130 while ( tmp.size () < numUniforms ) {
21462131 // Higher-alignment uniforms first to avoid wasting memory
2147- GLuint highestAlignment = 0 ;
2148- int highestUniform = 0 ;
2149- for ( uint i = 0 ; i < _uniforms.size (); i++ ) {
2150- if ( _uniforms[i]->GetSTD430Alignment () > highestAlignment ) {
2151- highestAlignment = _uniforms[i]->GetSTD430Alignment ();
2152- highestUniform = i;
2153- }
2132+ GLuint size = _materialSystemUniforms[0 ]->GetSTD430Size ();
2133+ GLuint components = _materialSystemUniforms[0 ]->GetComponentSize ();
2134+ size = components ? 4 * components : size;
2135+ GLuint alignmentConsume = 4 - size % 4 ;
21542136
2155- if ( highestAlignment == 4 ) {
2156- break ; // 4-component is the highest alignment in std430
2157- }
2158- }
2159-
2160- const GLuint size = _uniforms[highestUniform]->GetSTD430Size ();
2161- if ( _uniforms[highestUniform]->GetComponentSize () != 0 ) {
2162- structSize += ( size == 3 ) ? 4 * _uniforms[highestUniform]->GetComponentSize () :
2163- size * _uniforms[highestUniform]->GetComponentSize ();
2164- } else {
2165- structSize += ( size == 3 ) ? 4 : size;
2137+ tmp.emplace_back ( _materialSystemUniforms[0 ] );
2138+ _materialSystemUniforms.erase ( _materialSystemUniforms.begin () );
2139+
2140+ int uniform;
2141+ while ( ( alignmentConsume & 3 ) && _materialSystemUniforms.size ()
2142+ && ( uniform = FindUniformForAlignment ( _materialSystemUniforms, alignmentConsume ) ) != -1 ) {
2143+ alignmentConsume -= _materialSystemUniforms[uniform]->GetSTD430Size ();
2144+
2145+ tmp.emplace_back ( _materialSystemUniforms[uniform] );
2146+ _materialSystemUniforms.erase ( _materialSystemUniforms.begin () + uniform );
21662147 }
21672148
2168- tmp.emplace_back ( _uniforms[highestUniform] );
2169- _uniforms.erase ( _uniforms.begin () + highestUniform );
2149+ size = PAD ( size, 4 );
2150+ std430Size += size;
2151+ padding = alignmentConsume;
21702152 }
2171- _uniforms = tmp;
21722153
2173- const GLuint structAlignment = 4 ; // Material buffer is now a UBO, so it uses std140 layout, which is aligned to vec4
2174- if ( structSize > 0 ) {
2175- padding = ( structAlignment - ( structSize % structAlignment ) ) % structAlignment;
2176- }
2177- std430Size = structSize;
2178- for ( GLUniform* uniform : globalUniforms ) {
2179- _uniforms.emplace_back ( uniform );
2180- }
2154+ _materialSystemUniforms = tmp;
21812155}
21822156
21832157uint32_t GLShader::GetUniqueCompileMacros ( size_t permutation, const int type ) const {
@@ -2361,10 +2335,8 @@ void GLShader::SetRequiredVertexPointers()
23612335
23622336void GLShader::WriteUniformsToBuffer ( uint32_t * buffer ) {
23632337 uint32_t * bufPtr = buffer;
2364- for ( GLUniform* uniform : _uniforms ) {
2365- if ( !uniform->IsGlobal () && !uniform->IsTexture () ) {
2366- bufPtr = uniform->WriteToBuffer ( bufPtr );
2367- }
2338+ for ( GLUniform* uniform : _materialSystemUniforms ) {
2339+ bufPtr = uniform->WriteToBuffer ( bufPtr );
23682340 }
23692341}
23702342
0 commit comments