Skip to content

Commit

Permalink
Use a UBO for materials instead of an SSBO
Browse files Browse the repository at this point in the history
  • Loading branch information
VReaperV committed Jan 2, 2025
1 parent d742d7e commit 1772eea
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 35 deletions.
46 changes: 23 additions & 23 deletions src/engine/renderer/Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Material.h"
#include "ShadeCommon.h"

GLSSBO materialsSSBO( "materials", 0, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT );
GLBuffer texDataSSBO( "texData", 6, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT );
GLUBO materialsUBO( "materials", 0, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT );
GLBuffer texDataBuffer( "texData", 6, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT );
GLUBO lightmapDataUBO( "texData", 7, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT );

GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", 1, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT );
Expand Down Expand Up @@ -391,7 +391,7 @@ void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage ) {
void MaterialSystem::GenerateWorldMaterialsBuffer() {
Log::Debug( "Generating materials buffer" );

materialsSSBO.BindBuffer();
materialsUBO.BindBuffer();

// Sort by padded size to avoid extra padding
std::sort( materialStages.begin(), materialStages.end(),
Expand Down Expand Up @@ -435,8 +435,8 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() {
totalStageSize = offset;

// 4 bytes per component
glBufferData( GL_SHADER_STORAGE_BUFFER, offset * sizeof( uint32_t ), nullptr, GL_DYNAMIC_DRAW );
uint32_t* materialsData = materialsSSBO.MapBufferRange( offset );
glBufferData( GL_UNIFORM_BUFFER, offset * sizeof( uint32_t ), nullptr, GL_DYNAMIC_DRAW );
uint32_t* materialsData = materialsUBO.MapBufferRange( offset );

GenerateMaterialsBuffer( materialStages, offset, materialsData );

Expand Down Expand Up @@ -480,7 +480,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() {
}
}

materialsSSBO.UnmapBuffer();
materialsUBO.UnmapBuffer();
}

void MaterialSystem::GenerateMaterialsBuffer( std::vector<shaderStage_t*>& stages, const uint32_t size, uint32_t* materialsData ) {
Expand Down Expand Up @@ -580,10 +580,10 @@ void MaterialSystem::GenerateWorldCommandBuffer() {

texDataBufferType = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;

texDataSSBO.BindBuffer( texDataBufferType );
texDataSSBO.BufferStorage( texDataBufferType, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr );
texDataSSBO.MapAll( texDataBufferType );
TexBundle* textureBundles = ( TexBundle* ) texDataSSBO.GetData();
texDataBuffer.BindBuffer( texDataBufferType );
texDataBuffer.BufferStorage( texDataBufferType, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr );
texDataBuffer.MapAll( texDataBufferType );
TexBundle* textureBundles = ( TexBundle* ) texDataBuffer.GetData();
memset( textureBundles, 0, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * sizeof( uint32_t ) );

GenerateTexturesBuffer( texData, textureBundles );
Expand All @@ -595,9 +595,9 @@ void MaterialSystem::GenerateWorldCommandBuffer() {
dynamicTexDataOffset = texData.size() * TEX_BUNDLE_SIZE;
dynamicTexDataSize = dynamicTexData.size() * TEX_BUNDLE_SIZE;

texDataSSBO.FlushAll( texDataBufferType );
texDataSSBO.UnmapBuffer();
texDataSSBO.UnBindBuffer( texDataBufferType );
texDataBuffer.FlushAll( texDataBufferType );
texDataBuffer.UnmapBuffer();
texDataBuffer.UnBindBuffer( texDataBufferType );

lightmapDataUBO.BindBuffer();
lightmapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr );
Expand Down Expand Up @@ -1610,24 +1610,24 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stag
// Dynamic surfaces are those whose values in the SSBO can be updated
void MaterialSystem::UpdateDynamicSurfaces() {
if ( dynamicStagesSize > 0 ) {
materialsSSBO.BindBuffer();
uint32_t* materialsData = materialsSSBO.MapBufferRange( dynamicStagesOffset, dynamicStagesSize );
materialsUBO.BindBuffer();
uint32_t* materialsData = materialsUBO.MapBufferRange( dynamicStagesOffset, dynamicStagesSize );

GenerateMaterialsBuffer( dynamicStages, dynamicStagesSize, materialsData );

materialsSSBO.UnmapBuffer();
materialsUBO.UnmapBuffer();
}

if ( dynamicTexDataSize > 0 ) {
texDataSSBO.BindBuffer( texDataBufferType );
texDataBuffer.BindBuffer( texDataBufferType );
GL_CheckErrors();
TexBundle* textureBundles =
( TexBundle* ) texDataSSBO.MapBufferRange( texDataBufferType, dynamicTexDataOffset, dynamicTexDataSize );
( TexBundle* ) texDataBuffer.MapBufferRange( texDataBufferType, dynamicTexDataOffset, dynamicTexDataSize );
GL_CheckErrors();

GenerateTexturesBuffer( dynamicTexData, textureBundles );

texDataSSBO.UnmapBuffer();
texDataBuffer.UnmapBuffer();
}
}

Expand Down Expand Up @@ -1898,7 +1898,7 @@ void MaterialSystem::Free() {
surfaceCommandsSSBO.UnmapBuffer();
culledCommandsBuffer.UnmapBuffer();
atomicCommandCountersBuffer.UnmapBuffer();
texDataSSBO.UnmapBuffer();
texDataBuffer.UnmapBuffer();
lightmapDataUBO.UnmapBuffer();

if ( totalPortals > 0 ) {
Expand Down Expand Up @@ -2061,7 +2061,7 @@ void MaterialSystem::RenderMaterials( const shaderSort_t fromSort, const shaderS
frameStart = false;
}

materialsSSBO.BindBufferBase();
materialsUBO.BindBufferBase();

for ( MaterialPack& materialPack : materialPacks ) {
if ( materialPack.fromSort >= fromSort && materialPack.toSort <= toSort ) {
Expand Down Expand Up @@ -2203,7 +2203,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID )

atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB );

texDataSSBO.BindBufferBase( texDataBufferType );
texDataBuffer.BindBufferBase( texDataBufferType );
lightmapDataUBO.BindBufferBase();

if ( r_showGlobalMaterials.Get() && material.sort != 0
Expand Down Expand Up @@ -2320,7 +2320,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID )

atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB );

texDataSSBO.UnBindBufferBase( texDataBufferType );
texDataBuffer.UnBindBufferBase( texDataBufferType );
lightmapDataUBO.UnBindBufferBase();

if ( material.usePolygonOffset ) {
Expand Down
4 changes: 2 additions & 2 deletions src/engine/renderer/Material.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,8 @@ class MaterialSystem {
void UpdateFrameData();
};

extern GLSSBO materialsSSBO; // Global
extern GLBuffer texDataSSBO; // Global
extern GLUBO materialsUBO; // Global
extern GLBuffer texDataBuffer; // Global
extern GLUBO lightmapDataUBO; // Global

extern GLSSBO surfaceDescriptorsSSBO; // Global
Expand Down
13 changes: 7 additions & 6 deletions src/engine/renderer/gl_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1360,9 +1360,12 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str

std::string newShaderText;
std::string materialStruct = "\nstruct Material {\n";
std::string materialBlock = "layout(std430, binding = 0) restrict readonly buffer materialsSSBO {\n"
" Material materials[];\n"
// 6 kb for materials
const uint32_t count = ( 4096 + 2048 ) / shader->GetPaddedSize();
std::string materialBlock = "layout(std140, binding = 0) uniform materialsUBO {\n"
" Material materials[" + std::to_string( count ) + "]; \n"
"};\n\n";

std::string texBuf = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ?
"layout(std140, binding = 6) uniform texDataUBO {\n"
" TexData texData[" + std::to_string( MAX_TEX_BUNDLES ) + "]; \n"
Expand Down Expand Up @@ -2014,7 +2017,6 @@ void GLShader::PostProcessUniforms() {

// Sort uniforms from highest to lowest alignment so we don't need to pad uniforms (other than vec3s)
const uint numUniforms = _uniforms.size();
GLuint structAlignment = 0;
GLuint structSize = 0;
while ( tmp.size() < numUniforms ) {
// Higher-alignment uniforms first to avoid wasting memory
Expand All @@ -2025,9 +2027,7 @@ void GLShader::PostProcessUniforms() {
highestAlignment = _uniforms[i]->GetSTD430Alignment();
highestUniform = i;
}
if ( highestAlignment > structAlignment ) {
structAlignment = highestAlignment;
}

if ( highestAlignment == 4 ) {
break; // 4-component is the highest alignment in std430
}
Expand All @@ -2046,6 +2046,7 @@ void GLShader::PostProcessUniforms() {
}
_uniforms = tmp;

const GLuint structAlignment = 4; // Material buffer is now a UBO, so it uses std140 layout, which is aligned to vec4
if ( structSize > 0 ) {
padding = ( structAlignment - ( structSize % structAlignment ) ) % structAlignment;
}
Expand Down
8 changes: 4 additions & 4 deletions src/engine/renderer/tr_vbo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,8 @@ static void R_InitLightUBO()

static void R_InitMaterialBuffers() {
if( glConfig2.usingMaterialSystem ) {
materialsSSBO.GenBuffer();
texDataSSBO.GenBuffer();
materialsUBO.GenBuffer();
texDataBuffer.GenBuffer();
lightmapDataUBO.GenBuffer();

surfaceDescriptorsSSBO.GenBuffer();
Expand Down Expand Up @@ -861,8 +861,8 @@ void R_ShutdownVBOs()
}

if ( glConfig2.usingMaterialSystem ) {
materialsSSBO.DelBuffer();
texDataSSBO.DelBuffer();
materialsUBO.DelBuffer();
texDataBuffer.DelBuffer();
lightmapDataUBO.DelBuffer();

surfaceDescriptorsSSBO.DelBuffer();
Expand Down

0 comments on commit 1772eea

Please sign in to comment.