Skip to content

Commit 60ac8d9

Browse files
committed
Generalise uniform post-processing
Also adds `GLShader.pushSkip` and `GLShader._pushUniforms`. Add `padding` back to the `GLShader` size calculations in material system.
1 parent b355201 commit 60ac8d9

File tree

3 files changed

+79
-38
lines changed

3 files changed

+79
-38
lines changed

src/engine/renderer/Material.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,7 @@ void MaterialSystem::ProcessStage( MaterialSurface* surface, shaderStage_t* pSta
13131313

13141314
material.bspSurface = surface->bspSurface;
13151315
pStage->materialProcessor( &material, pStage, surface );
1316-
pStage->paddedSize = material.shader->GetSTD430Size();
1316+
pStage->paddedSize = material.shader->GetSTD430PaddedSize();
13171317

13181318
// HACK: Copy the shaderStage_t and MaterialSurface that we need into the material, so we can use it with glsl_restart
13191319
material.refStage = pStage;

src/engine/renderer/gl_shader.cpp

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str
16471647
materialStruct += "};\n\n";
16481648

16491649
// 6 kb for materials
1650-
const uint32_t count = ( 4096 + 2048 ) / shader->GetSTD430Size();
1650+
const uint32_t count = ( 4096 + 2048 ) / shader->GetSTD430PaddedSize();
16511651
std::string materialBlock = "layout(std140, binding = "
16521652
+ std::to_string( BufferBind::MATERIALS )
16531653
+ ") uniform materialsUBO {\n"
@@ -2113,59 +2113,91 @@ static int FindUniformForAlignment( std::vector<GLUniform*>& uniforms, const GLu
21132113
return -1;
21142114
}
21152115

2116-
// Compute std430 size/alignment and sort uniforms from highest to lowest alignment
2117-
void GLShader::PostProcessUniforms() {
2118-
if ( !_useMaterialSystem ) {
2119-
return;
2120-
}
2121-
2122-
for ( GLUniform* uniform : _uniforms ) {
2123-
if ( !uniform->_global ) {
2124-
_materialSystemUniforms.emplace_back( uniform );
2125-
}
2126-
}
2127-
2128-
std::sort( _materialSystemUniforms.begin(), _materialSystemUniforms.end(),
2116+
GLuint GLShaderManager::SortUniforms( std::vector<GLUniform*>& uniforms ) {
2117+
std::sort( uniforms.begin(), uniforms.end(),
21292118
[]( const GLUniform* lhs, const GLUniform* rhs ) {
21302119
return lhs->_std430Size > rhs->_std430Size;
21312120
}
21322121
);
21332122

2134-
// Sort uniforms from highest to lowest alignment so we don't need to pad uniforms (other than vec3s)
2135-
const uint numUniforms = _materialSystemUniforms.size();
2123+
const uint numUniforms = uniforms.size();
21362124
std::vector<GLUniform*> tmp;
2125+
GLuint structSize = 0;
21372126
while ( tmp.size() < numUniforms ) {
21382127
// Higher-alignment uniforms first to avoid wasting memory
2139-
GLuint size = _materialSystemUniforms[0]->_std430Size;
2140-
GLuint components = _materialSystemUniforms[0]->_components;
2128+
GLuint size = uniforms[0]->_std430Size;
2129+
GLuint components = uniforms[0]->_components;
21412130
size = components ? PAD( size, 4 ) * components : size;
21422131
GLuint alignmentConsume = 4 - size % 4;
2132+
GLuint usedSpace = size;
21432133

2144-
GLUniform* tmpUniform = _materialSystemUniforms[0];
2145-
tmp.emplace_back( _materialSystemUniforms[0] );
2146-
_materialSystemUniforms.erase( _materialSystemUniforms.begin() );
2134+
GLUniform* tmpUniform = uniforms[0];
2135+
tmp.emplace_back( uniforms[0] );
2136+
uniforms.erase( uniforms.begin() );
21472137

21482138
int uniform;
2149-
while ( ( alignmentConsume & 3 ) && _materialSystemUniforms.size()
2150-
&& ( uniform = FindUniformForAlignment( _materialSystemUniforms, alignmentConsume ) ) != -1 ) {
2151-
alignmentConsume -= _materialSystemUniforms[uniform]->_std430Size;
2139+
while ( ( alignmentConsume & 3 ) && uniforms.size()
2140+
&& ( uniform = FindUniformForAlignment( uniforms, alignmentConsume ) ) != -1 ) {
2141+
alignmentConsume -= uniforms[uniform]->_std430Size;
2142+
usedSpace += uniforms[uniform]->_std430Size;
21522143

2153-
tmpUniform = _materialSystemUniforms[uniform];
2144+
tmpUniform = uniforms[uniform];
21542145

2155-
tmp.emplace_back( _materialSystemUniforms[uniform] );
2156-
_materialSystemUniforms.erase( _materialSystemUniforms.begin() + uniform );
2146+
tmp.emplace_back( uniforms[uniform] );
2147+
uniforms.erase( uniforms.begin() + uniform );
21572148
}
21582149

2159-
if ( alignmentConsume ) {
2150+
if ( alignmentConsume & 3 ) {
21602151
tmpUniform->_std430Size += alignmentConsume;
21612152
}
21622153

2163-
size = PAD( size, 4 );
2164-
std430Size += size;
2165-
padding = alignmentConsume;
2154+
if ( uniforms.size() ) {
2155+
structSize += PAD( size, 4 );
2156+
} else {
2157+
structSize += usedSpace;
2158+
}
21662159
}
21672160

2168-
_materialSystemUniforms = tmp;
2161+
uniforms = tmp;
2162+
2163+
return structSize;
2164+
}
2165+
2166+
std::vector<GLUniform*> GLShaderManager::ProcessUniforms( const GLUniform::UpdateType minType, const GLUniform::UpdateType maxType,
2167+
const bool skipTextures,
2168+
std::vector<GLUniform*>& uniforms, GLuint& structSize, GLuint& padding ) {
2169+
std::vector<GLUniform*> tmp;
2170+
2171+
tmp.reserve( uniforms.size() );
2172+
for ( GLUniform* uniform : uniforms ) {
2173+
if ( uniform->_updateType >= minType && uniform->_updateType <= maxType
2174+
&& ( !uniform->_isTexture || !skipTextures ) ) {
2175+
tmp.emplace_back( uniform );
2176+
}
2177+
}
2178+
2179+
structSize = SortUniforms( tmp );
2180+
2181+
const GLuint structAlignment = 4; // Material buffer is now a UBO, so it uses std140 layout, which is aligned to vec4
2182+
if ( structSize > 0 ) {
2183+
padding = ( structAlignment - ( structSize % structAlignment ) ) % structAlignment;
2184+
}
2185+
2186+
return tmp;
2187+
}
2188+
2189+
// Compute std140 size/alignment and sort uniforms from highest to lowest alignment
2190+
void GLShader::PostProcessUniforms() {
2191+
if ( _useMaterialSystem ) {
2192+
_materialSystemUniforms = gl_shaderManager.ProcessUniforms( GLUniform::MATERIAL_OR_PUSH, GLUniform::MATERIAL_OR_PUSH,
2193+
true, _uniforms, std430Size, padding );
2194+
}
2195+
2196+
if ( glConfig2.pushBufferAvailable && !pushSkip ) {
2197+
GLuint unused;
2198+
_pushUniforms = gl_shaderManager.ProcessUniforms( GLUniform::CONST, GLUniform::FRAME,
2199+
false, _uniforms, unused, unused );
2200+
}
21692201
}
21702202

21712203
uint32_t GLShader::GetUniqueCompileMacros( size_t permutation, const int type ) const {

src/engine/renderer/gl_shader.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class GLShader {
106106
uint32_t padding = 0;
107107

108108
const bool worldShader;
109+
const bool pushSkip;
109110
protected:
110111
int _activeMacros = 0;
111112
ShaderProgramDescriptor* currentProgram;
@@ -120,13 +121,15 @@ class GLShader {
120121

121122
size_t _uniformStorageSize;
122123
std::vector<GLUniform*> _uniforms;
124+
std::vector<GLUniform*> _pushUniforms;
123125
std::vector<GLUniform*> _materialSystemUniforms;
124126
std::vector<GLUniformBlock*> _uniformBlocks;
125127
std::vector<GLCompileMacro*> _compileMacros;
126128

127129
GLShader( const std::string& name, uint32_t vertexAttribsRequired,
128130
const bool useMaterialSystem,
129-
const std::string newVertexShaderName, const std::string newFragmentShaderName ) :
131+
const std::string newVertexShaderName, const std::string newFragmentShaderName,
132+
const bool newPushSkip = false ) :
130133
_name( name ),
131134
_vertexAttribsRequired( vertexAttribsRequired ),
132135
_useMaterialSystem( useMaterialSystem ),
@@ -135,7 +138,8 @@ class GLShader {
135138
hasVertexShader( true ),
136139
hasFragmentShader( true ),
137140
hasComputeShader( false ),
138-
worldShader( false ) {
141+
worldShader( false ),
142+
pushSkip( newPushSkip ) {
139143
}
140144

141145
GLShader( const std::string& name,
@@ -148,7 +152,8 @@ class GLShader {
148152
hasVertexShader( false ),
149153
hasFragmentShader( false ),
150154
hasComputeShader( true ),
151-
worldShader( newWorldShader ) {
155+
worldShader( newWorldShader ),
156+
pushSkip( false ) {
152157
}
153158

154159
public:
@@ -218,8 +223,8 @@ class GLShader {
218223
_vertexAttribs &= ~bit;
219224
}
220225

221-
GLuint GetSTD430Size() const {
222-
return std430Size;
226+
GLuint GetSTD430PaddedSize() const {
227+
return std430Size + padding;
223228
}
224229

225230
bool UseMaterialSystem() const {
@@ -394,6 +399,10 @@ class GLShaderManager {
394399
void GenerateBuiltinHeaders();
395400
void GenerateWorldHeaders();
396401

402+
static GLuint SortUniforms( std::vector<GLUniform*>& uniforms );
403+
static std::vector<GLUniform*> ProcessUniforms( const GLUniform::UpdateType minType, const GLUniform::UpdateType maxType,
404+
const bool skipTextures, std::vector<GLUniform*>& uniforms, GLuint& structSize, GLuint& padding );
405+
397406
template<class T>
398407
void LoadShader( T*& shader ) {
399408
if ( !deformShaderCount ) {

0 commit comments

Comments
 (0)