Skip to content

Commit 0617470

Browse files
committed
Rewrite material system uniform SSBO packing
Fix some bugs and add more unit tests.
1 parent 79858d7 commit 0617470

File tree

2 files changed

+72
-39
lines changed

2 files changed

+72
-39
lines changed

src/engine/renderer/gl_shader.cpp

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,14 +2092,14 @@ GLint GLShader::GetUniformLocation( const GLchar *uniformName ) const {
20922092
return glGetUniformLocation( p->id, uniformName );
20932093
}
20942094

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]->_std430Size <= alignment ) {
2098-
return i;
2095+
static auto FindUniformForOffset( std::vector<GLUniform*>& uniforms, const GLuint baseOffset ) {
2096+
for ( auto it = uniforms.begin(); it != uniforms.end(); ++it ) {
2097+
if ( 0 == ( ( (*it)->_std430Alignment - 1 ) & baseOffset ) ) {
2098+
return it;
20992099
}
21002100
}
21012101

2102-
return -1;
2102+
return uniforms.end();
21032103
}
21042104

21052105
// Compute std430 size/alignment and sort uniforms from highest to lowest alignment
@@ -2108,52 +2108,36 @@ void GLShader::PostProcessUniforms() {
21082108
return;
21092109
}
21102110

2111+
std::vector<GLUniform*> uniformQueue;
21112112
for ( GLUniform* uniform : _uniforms ) {
21122113
if ( !uniform->_global ) {
2113-
_materialSystemUniforms.emplace_back( uniform );
2114+
uniformQueue.emplace_back( uniform );
21142115
}
21152116
}
21162117

2117-
std::sort( _materialSystemUniforms.begin(), _materialSystemUniforms.end(),
2118+
std::stable_sort( uniformQueue.begin(), uniformQueue.end(),
21182119
[]( const GLUniform* lhs, const GLUniform* rhs ) {
2119-
return lhs->_std430Size > rhs->_std430Size;
2120+
return lhs->_std430Alignment > rhs->_std430Alignment;
21202121
}
21212122
);
21222123

21232124
// Sort uniforms from highest to lowest alignment so we don't need to pad uniforms (other than vec3s)
2124-
const uint numUniforms = _materialSystemUniforms.size();
2125-
std::vector<GLUniform*> tmp;
2126-
while ( tmp.size() < numUniforms ) {
2127-
// Higher-alignment uniforms first to avoid wasting memory
2128-
GLuint size = _materialSystemUniforms[0]->_std430Size;
2129-
GLuint components = _materialSystemUniforms[0]->_components;
2130-
size = components ? PAD( size, 4 ) * components : size;
2131-
GLuint alignmentConsume = PAD( size, 4 ) - size;
2132-
2133-
GLUniform* tmpUniform = _materialSystemUniforms[0];
2134-
tmp.emplace_back( _materialSystemUniforms[0] );
2135-
_materialSystemUniforms.erase( _materialSystemUniforms.begin() );
2136-
2137-
int uniform;
2138-
while ( alignmentConsume && _materialSystemUniforms.size()
2139-
&& ( uniform = FindUniformForAlignment( _materialSystemUniforms, alignmentConsume ) ) != -1 ) {
2140-
alignmentConsume -= _materialSystemUniforms[uniform]->_std430Size;
2141-
2142-
tmpUniform = _materialSystemUniforms[uniform];
2143-
2144-
tmp.emplace_back( _materialSystemUniforms[uniform] );
2145-
_materialSystemUniforms.erase( _materialSystemUniforms.begin() + uniform );
2146-
}
2147-
2148-
if ( alignmentConsume ) {
2149-
tmpUniform->_std430Size += alignmentConsume;
2125+
GLuint align = 1;
2126+
std430Size = 0;
2127+
_materialSystemUniforms.clear();
2128+
while ( !uniformQueue.empty() || std430Size & ( align - 1 ) ) {
2129+
auto iterNext = FindUniformForOffset( uniformQueue, std430Size );
2130+
if ( iterNext == uniformQueue.end() ) {
2131+
// add 1 unit of padding
2132+
++std430Size;
2133+
++_materialSystemUniforms.back()->_std430Size;
2134+
} else {
2135+
std430Size += ( *iterNext )->_std430Size;
2136+
align = std::max( align, ( *iterNext )->_std430Alignment );
2137+
_materialSystemUniforms.push_back( *iterNext );
2138+
uniformQueue.erase( iterNext );
21502139
}
2151-
2152-
size = PAD( size, 4 );
2153-
std430Size += size;
21542140
}
2155-
2156-
_materialSystemUniforms = tmp;
21572141
}
21582142

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

src/engine/renderer/gl_shader_test.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,53 @@ TEST(MaterialUniformPackingTest, OneMatrix)
7373
EXPECT_EQ(uniforms[0]->_std430Size, 16u);
7474
}
7575

76+
TEST(MaterialUniformPackingTest, TwoFloats)
77+
{
78+
class Shader1 : public MaterialUniformPackingTestShaderBase,
79+
public u_DeformMagnitude, //float
80+
public u_InverseGamma //float
81+
{
82+
public:
83+
Shader1() : u_DeformMagnitude(this), u_InverseGamma(this) {}
84+
};
85+
86+
Shader1 shader1;
87+
std::vector<GLUniform*> uniforms = shader1.GetUniforms();
88+
EXPECT_EQ(shader1.GetSTD430Size(), 2u);
89+
ASSERT_EQ(uniforms.size(), 2);
90+
EXPECT_EQ(uniforms[0], Get<u_DeformMagnitude>(shader1));
91+
EXPECT_EQ(uniforms[0]->_std430Size, 1u);
92+
EXPECT_EQ(uniforms[1], Get<u_InverseGamma>(shader1));
93+
EXPECT_EQ(uniforms[1]->_std430Size, 1u);
94+
}
95+
96+
TEST(MaterialUniformPackingTest, Vec3Handling)
97+
{
98+
class Shader1 : public MaterialUniformPackingTestShaderBase,
99+
public u_DeformMagnitude, //float
100+
public u_SpecularExponent, //vec2
101+
public u_FogColor, //vec3
102+
public u_blurVec //vec3
103+
{
104+
public:
105+
Shader1() : u_DeformMagnitude(this),
106+
u_SpecularExponent(this),
107+
u_FogColor(this),
108+
u_blurVec(this) {}
109+
};
110+
111+
Shader1 shader1;
112+
std::vector<GLUniform*> uniforms = shader1.GetUniforms();
113+
EXPECT_EQ(shader1.GetSTD430Size(), 12u);
114+
ASSERT_EQ(uniforms.size(), 4);
115+
EXPECT_EQ(uniforms[0], Get<u_FogColor>(shader1));
116+
EXPECT_EQ(uniforms[0]->_std430Size, 3u);
117+
EXPECT_EQ(uniforms[1], Get<u_DeformMagnitude>(shader1));
118+
EXPECT_EQ(uniforms[1]->_std430Size, 1u);
119+
EXPECT_EQ(uniforms[2], Get<u_blurVec>(shader1));
120+
EXPECT_EQ(uniforms[2]->_std430Size, 4u);
121+
EXPECT_EQ(uniforms[3], Get<u_SpecularExponent>(shader1));
122+
EXPECT_EQ(uniforms[3]->_std430Size, 4u);
123+
}
124+
76125
} // namespace

0 commit comments

Comments
 (0)