From ebb9b93de36543a1b8890276e10ab383d9d88ff2 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Fri, 23 Aug 2024 00:09:44 +0300 Subject: [PATCH 01/16] Allocate material memory for stages rather than surfaces Allocate memory for each stage of used shaders rather than for each stage in all used shaders for each surface that uses them. Change some of the material system functions to use `shaderStage_t*` instead of `drawSurf_t*` etc as input. Textures are put into a different storage buffer, following the structure of `textureBundle_t`. This allows decreasing the total amount of memory used, and changing the material buffer to be a UBO instead. The lightmap and deluxemap handles are put into another UBO, because they're per-surface, rather than per-shader-stage. Also moved some duplicate code into a function. --- src/engine/renderer/Material.cpp | 775 ++++++++++-------- src/engine/renderer/Material.h | 121 ++- src/engine/renderer/ShadeCommon.h | 4 +- src/engine/renderer/gl_shader.cpp | 72 +- src/engine/renderer/gl_shader.h | 14 +- .../renderer/glsl_source/generic_vp.glsl | 5 +- .../renderer/glsl_source/heatHaze_vp.glsl | 5 +- .../renderer/glsl_source/lightMapping_vp.glsl | 4 +- .../renderer/glsl_source/liquid_vp.glsl | 5 +- .../renderer/glsl_source/material_fp.glsl | 8 +- .../glsl_source/reflection_CB_vp.glsl | 5 +- .../renderer/glsl_source/skybox_fp.glsl | 4 +- src/engine/renderer/tr_backend.cpp | 2 +- src/engine/renderer/tr_local.h | 81 +- src/engine/renderer/tr_shade.cpp | 6 +- src/engine/renderer/tr_shader.cpp | 6 +- src/engine/renderer/tr_vbo.cpp | 4 + 17 files changed, 689 insertions(+), 432 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 9093b92fb1..62b0572b22 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -38,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ShadeCommon.h" GLSSBO materialsSSBO( "materials", 0, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLSSBO texDataSSBO( "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 ); GLSSBO surfaceCommandsSSBO( "surfaceCommands", 2, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); @@ -114,69 +116,6 @@ static void ComputeDynamics( shaderStage_t* pStage ) { } } - for ( textureBundle_t& bundle : pStage->bundle ) { - for ( size_t i = 0; i < bundle.numTexMods; i++ ) { - switch ( bundle.texMods[i].type ) { - case texMod_t::TMOD_NONE: - case texMod_t::TMOD_SCALE: - case texMod_t::TMOD_TRANSFORM: - break; - - case texMod_t::TMOD_TURBULENT: - case texMod_t::TMOD_ENTITY_TRANSLATE: - case texMod_t::TMOD_SCROLL: - { - pStage->texMatricesDynamic = true; - break; - } - - case texMod_t::TMOD_STRETCH: - { - if( bundle.texMods->wave.func != genFunc_t::GF_NONE ) { - pStage->texMatricesDynamic = true; - } - break; - } - - case texMod_t::TMOD_ROTATE: - { - pStage->texMatricesDynamic = true; - break; - } - - case texMod_t::TMOD_SCROLL2: - case texMod_t::TMOD_SCALE2: - case texMod_t::TMOD_CENTERSCALE: - case texMod_t::TMOD_SHEAR: - { - if ( bundle.texMods[i].sExp.numOps || bundle.texMods[i].tExp.numOps ) { - pStage->texMatricesDynamic = true; - } - break; - } - - case texMod_t::TMOD_ROTATE2: - { - if( bundle.texMods[i].rExp.numOps ) { - pStage->texMatricesDynamic = true; - } - break; - } - - default: - break; - } - } - } - - // TODO: Move this to a different buffer? - for ( const textureBundle_t& bundle : pStage->bundle ) { - if ( bundle.isVideoMap || bundle.numImages > 1 ) { - pStage->texturesDynamic = true; - break; - } - } - // Can we move this to a compute shader too? // Doesn't seem to be used much if at all, so probably not worth the effort to do that pStage->dynamic = pStage->dynamic || pStage->ifExp.numOps; @@ -187,31 +126,30 @@ static void ComputeDynamics( shaderStage_t* pStage ) { || pStage->fogDensityExp.numOps || pStage->fresnelBiasExp.numOps || pStage->fresnelPowerExp.numOps || pStage->fresnelScaleExp.numOps || pStage->normalIntensityExp.numOps || pStage->refractionIndexExp.numOps; - pStage->dynamic = pStage->dynamic || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->texturesDynamic; + pStage->dynamic = pStage->dynamic || pStage->colorDynamic; } // UpdateSurface*() functions will actually write the uniform values to the SSBO // Mirrors parts of the Render_*() functions in tr_shade.cpp -void UpdateSurfaceDataNONE( uint32_t*, Material&, drawSurf_t*, const uint32_t ) { +void UpdateSurfaceDataNONE( uint32_t*, Material&, shaderStage_t* ) { ASSERT_UNREACHABLE(); } -void UpdateSurfaceDataNOP( uint32_t*, Material&, drawSurf_t*, const uint32_t ) { +void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ) { } -void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; gl_genericShaderMaterial->BindProgram( material.deformIndex ); @@ -229,18 +167,6 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, drawSu Tess_ComputeColor( pStage ); gl_genericShaderMaterial->SetUniform_Color( tess.svars.color ); - Tess_ComputeTexMatrices( pStage ); - gl_genericShaderMaterial->SetUniform_TextureMatrix( tess.svars.texMatrices[TB_COLORMAP] ); - - // bind u_ColorMap - if ( pStage->type == stageType_t::ST_STYLELIGHTMAP ) { - gl_genericShaderMaterial->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, GetLightMap( drawSurf ) ) - ); - } else { - gl_genericShaderMaterial->SetUniform_ColorMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); - } - bool hasDepthFade = pStage->hasDepthFade; if ( hasDepthFade ) { gl_genericShaderMaterial->SetUniform_DepthScale( pStage->depthFadeValue ); @@ -249,44 +175,35 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, drawSu gl_genericShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; gl_lightMappingShaderMaterial->BindProgram( material.deformIndex ); gl_lightMappingShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - lightMode_t lightMode; - deluxeMode_t deluxeMode; - SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); - - // u_Map, u_DeluxeMap - image_t* lightmap = SetLightMap( drawSurf, lightMode ); - image_t* deluxemap = SetDeluxeMap( drawSurf, deluxeMode ); - // u_ColorModulate colorGen_t rgbGen = SetRgbGen( pStage ); alphaGen_t alphaGen = SetAlphaGen( pStage ); Tess_ComputeColor( pStage ); - SetVertexLightingSettings( lightMode, rgbGen ); - - bool enableGridLighting = ( lightMode == lightMode_t::GRID ); - bool enableGridDeluxeMapping = ( deluxeMode == deluxeMode_t::GRID ); + // HACK: This only has effect on vertex-lit surfaces + if ( pStage->vertexLit ) { + SetVertexLightingSettings( lightMode_t::VERTEX, rgbGen ); + } // u_ColorModulate - gl_lightMappingShaderMaterial->SetUniform_ColorModulateColorGen( rgbGen, alphaGen, false, lightMode != lightMode_t::FULLBRIGHT ); + gl_lightMappingShaderMaterial->SetUniform_ColorModulateColorGen( rgbGen, alphaGen, false, !pStage->fullbright ); // u_Color gl_lightMappingShaderMaterial->SetUniform_Color( tess.svars.color ); @@ -294,37 +211,13 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, dra // u_AlphaThreshold gl_lightMappingShaderMaterial->SetUniform_AlphaTest( pStage->stateBits ); - // bind u_HeightMap + // HeightMap if ( pStage->enableReliefMapping ) { float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); depthScale *= shader->reliefDepthScale; gl_lightMappingShaderMaterial->SetUniform_ReliefDepthScale( depthScale ); gl_lightMappingShaderMaterial->SetUniform_ReliefOffsetBias( shader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) { - gl_lightMappingShaderMaterial->SetUniform_HeightMapBindless( - GL_BindToTMU( BIND_HEIGHTMAP, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - // bind u_DiffuseMap - gl_lightMappingShaderMaterial->SetUniform_DiffuseMapBindless( - GL_BindToTMU( BIND_DIFFUSEMAP, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); - - if ( pStage->type != stageType_t::ST_LIGHTMAP ) { - Tess_ComputeTexMatrices( pStage ); - gl_lightMappingShaderMaterial->SetUniform_TextureMatrix( tess.svars.texMatrices[TB_DIFFUSEMAP] ); - } - - // bind u_NormalMap - if ( !!r_normalMapping->integer || pStage->hasHeightMapInNormalMap ) { - gl_lightMappingShaderMaterial->SetUniform_NormalMapBindless( - GL_BindToTMU( BIND_NORMALMAP, pStage->bundle[TB_NORMALMAP].image[0] ) - ); } // bind u_NormalScale @@ -335,13 +228,6 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, dra gl_lightMappingShaderMaterial->SetUniform_NormalScale( normalScale ); } - // bind u_MaterialMap - if ( pStage->enableSpecularMapping || pStage->enablePhysicalMapping ) { - gl_lightMappingShaderMaterial->SetUniform_MaterialMapBindless( - GL_BindToTMU( BIND_MATERIALMAP, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - } - if ( pStage->enableSpecularMapping ) { float specExpMin = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); float specExpMax = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); @@ -349,47 +235,20 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, dra gl_lightMappingShaderMaterial->SetUniform_SpecularExponent( specExpMin, specExpMax ); } - // bind u_LightMap - if ( !enableGridLighting ) { - gl_lightMappingShaderMaterial->SetUniform_LightMapBindless( - GL_BindToTMU( BIND_LIGHTMAP, lightmap ) - ); - } - - // bind u_DeluxeMap - if ( !enableGridDeluxeMapping ) { - gl_lightMappingShaderMaterial->SetUniform_DeluxeMapBindless( - GL_BindToTMU( BIND_DELUXEMAP, deluxemap ) - ); - } - - // bind u_GlowMap - if ( !!r_glowMapping->integer ) { - gl_lightMappingShaderMaterial->SetUniform_GlowMapBindless( - GL_BindToTMU( BIND_GLOWMAP, pStage->bundle[TB_GLOWMAP].image[0] ) - ); - } - gl_lightMappingShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; - - // bind u_NormalMap - gl_reflectionShaderMaterial->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); + pStage->bufferInitialized = true; // bind u_ColorMap vec3_t position; @@ -415,98 +274,76 @@ void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, drawS gl_reflectionShaderMaterial->SetUniform_NormalScale( normalScale ); } - // bind u_HeightMap u_depthScale u_reliefOffsetBias + // u_depthScale u_reliefOffsetBias if ( pStage->enableReliefMapping ) { float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); float reliefDepthScale = shader->reliefDepthScale; depthScale *= reliefDepthScale == 0 ? 1 : reliefDepthScale; gl_reflectionShaderMaterial->SetUniform_ReliefDepthScale( depthScale ); gl_reflectionShaderMaterial->SetUniform_ReliefOffsetBias( shader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) { - gl_reflectionShaderMaterial->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } } gl_reflectionShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; gl_skyboxShaderMaterial->BindProgram( material.deformIndex ); - // bind u_ColorMap - gl_skyboxShaderMaterial->SetUniform_ColorMapCubeBindless( - GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) - ); - // u_AlphaThreshold gl_skyboxShaderMaterial->SetUniform_AlphaTest( GLS_ATEST_NONE ); gl_skyboxShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; gl_screenShaderMaterial->BindProgram( pStage->deformIndex ); // bind u_CurrentMap /* FIXME: This is currently unused, but u_CurrentMap was made global for other shaders, this seems to be the only material system shader that might need it to not be global */ - gl_screenShaderMaterial->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &drawSurf->shader->stages[stage].bundle[TB_COLORMAP] ) ); + gl_screenShaderMaterial->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); gl_screenShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; float deformMagnitude = RB_EvalExpression( &pStage->deformMagnitudeExp, 1.0 ); gl_heatHazeShaderMaterial->SetUniform_DeformMagnitude( deformMagnitude ); - // bind u_NormalMap - gl_heatHazeShaderMaterial->SetUniform_NormalMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - if ( pStage->enableNormalMapping ) { - gl_heatHazeShaderMaterial->SetUniform_TextureMatrix( tess.svars.texMatrices[TB_NORMALMAP] ); - vec3_t normalScale; SetNormalScale( pStage, normalScale ); @@ -517,18 +354,17 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, drawSur gl_heatHazeShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; float fogDensity = RB_EvalExpression( &pStage->fogDensityExp, 0.001 ); vec4_t fogColor; @@ -563,16 +399,8 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, drawSurf_ depthScale *= reliefDepthScale == 0 ? 1 : reliefDepthScale; gl_liquidShaderMaterial->SetUniform_ReliefDepthScale( depthScale ); gl_liquidShaderMaterial->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) { - gl_liquidShaderMaterial->SetUniform_HeightMapBindless( GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) ); - } } - // bind u_NormalMap - gl_liquidShaderMaterial->SetUniform_NormalMapBindless( GL_BindToTMU( 3, pStage->bundle[TB_NORMALMAP].image[0] ) ); - // bind u_NormalScale if ( pStage->enableNormalMapping ) { vec3_t normalScale; @@ -585,18 +413,17 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, drawSurf_ gl_liquidShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataFog( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ) { - shader_t* shader = drawSurf->shader; - shaderStage_t* pStage = &shader->stages[stage]; +void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ) { + shader_t* shader = pStage->shader; - const uint32_t paddedOffset = drawSurf->materialsSSBOOffset[stage] * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); materials += paddedOffset; - bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + bool updated = !pStage->bufferInitialized || pStage->dynamic; if ( !updated ) { return; } - drawSurf->initialized[stage] = true; + pStage->bufferInitialized = true; const fog_t* fog = material.fog; @@ -609,30 +436,20 @@ void UpdateSurfaceDataFog( uint32_t* materials, Material& material, drawSurf_t* /* * Buffer layout: * // Static surfaces data: -* // Material0 -* // Surface/stage0_0: +* // Stage0: * uniform0_0 * uniform0_1 * .. * uniform0_x * optional_struct_padding -* // Surface/stage0_1: +* // Stage1: * .. -* // Surface/stage0_y: +* // Stage_y: * uniform0_0 * uniform0_1 * .. * uniform0_x * optional_struct_padding -* optional_material1_padding -* // Material1 -* // Surface/stage1_0: -* .. -* // Surface/stage1_y: -* .. -* .. -* // Materialz: -* .. * .. * // Dynamic surfaces data: * // Same as the static layout @@ -642,125 +459,151 @@ void UpdateSurfaceDataFog( uint32_t* materials, Material& material, drawSurf_t* void MaterialSystem::GenerateWorldMaterialsBuffer() { Log::Debug( "Generating materials buffer" ); - uint32_t offset = 0; - materialsSSBO.BindBuffer(); - // Compute data size for static surfaces - for ( MaterialPack& pack : materialPacks ) { - for ( Material& material : pack.materials ) { - // Any new material in the buffer must start on an offset that is an integer multiple of - // the padded size of the material struct - const uint32_t paddedSize = material.shader->GetPaddedSize(); - const uint32_t padding = ( offset % paddedSize == 0 ) ? 0 : paddedSize - ( offset % paddedSize ); + // Sort by padded size to avoid extra padding + std::sort( materialStages.begin(), materialStages.end(), + [&]( const shaderStage_t* lhs, const shaderStage_t* rhs ) { + if ( !lhs->dynamic && rhs->dynamic ) { + return true; + } - offset += padding; - material.staticMaterialsSSBOOffset = offset; - offset += paddedSize * material.totalStaticDrawSurfCount; - } - } + if ( !rhs->dynamic && lhs->dynamic ) { + return false; + } + + return materialPacks[lhs->materialPackID].materials[lhs->materialID].shader->GetPaddedSize() + < materialPacks[rhs->materialPackID].materials[rhs->materialID].shader->GetPaddedSize(); + } ); + uint32_t offset = 0; + uint32_t dynamicOffset = 0; + dynamicStagesOffset = 0; bool dynamicDrawSurfOffsetSet = false; - // Compute data size for dynamic surfaces - for ( MaterialPack& pack : materialPacks ) { - for ( Material& material : pack.materials ) { - // Any new material in the buffer must start on an offset that is an integer multiple of - // the padded size of the material struct - const uint32_t paddedSize = material.shader->GetPaddedSize(); - const uint32_t padding = ( offset % paddedSize == 0 ) ? 0 : paddedSize - ( offset % paddedSize ); - - offset += padding; - - // Make sure padding is taken into account for dynamicDrawSurfsOffset + // Compute data size for stages + for ( shaderStage_t* pStage : materialStages ) { + const uint32_t paddedSize = materialPacks[pStage->materialPackID].materials[pStage->materialID].shader->GetPaddedSize(); + const uint32_t padding = ( offset % paddedSize == 0 ) ? 0 : paddedSize - ( offset % paddedSize ); + + offset += padding; + + // Make sure padding is taken into account for dynamicStagesOffset + if ( pStage->dynamic ) { if ( !dynamicDrawSurfOffsetSet ) { - dynamicDrawSurfsOffset = offset; + dynamicStagesOffset = offset; dynamicDrawSurfOffsetSet = true; } - material.dynamicMaterialsSSBOOffset = offset; - offset += paddedSize * material.totalDynamicDrawSurfCount; + const uint32_t dynamicPadding = ( dynamicOffset % paddedSize == 0 ) ? 0 : paddedSize - ( dynamicOffset % paddedSize ); + dynamicOffset += dynamicPadding; + pStage->dynamicMaterialsOffset = dynamicOffset / paddedSize; + dynamicOffset += paddedSize * pStage->variantOffset; } + + pStage->materialsSSBOOffset = offset / paddedSize; + offset += paddedSize * pStage->variantOffset; } - dynamicDrawSurfsSize = offset - dynamicDrawSurfsOffset; + dynamicStagesSize = dynamicDrawSurfOffsetSet ? offset - dynamicStagesOffset : 0; + 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 ); - memset( materialsData, 0, offset * sizeof( uint32_t ) ); + + GenerateMaterialsBuffer( materialStages, offset, materialsData ); for ( uint32_t materialPackID = 0; materialPackID < 3; materialPackID++ ) { for ( Material& material : materialPacks[materialPackID].materials ) { - for ( drawSurf_t* drawSurf : material.drawSurfs ) { - bool hasDynamicStages = false; - uint32_t stage = 0; for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - if ( drawSurf->materialIDs[stage] != material.id || drawSurf->materialPackIDs[stage] != materialPackID ) { + if ( pStage->materialID != material.id || pStage->materialPackID != materialPackID ) { stage++; continue; } - - uint32_t SSBOOffset = 0; - uint32_t drawSurfCount = 0; - if ( pStage->dynamic ) { - SSBOOffset = material.dynamicMaterialsSSBOOffset; - drawSurfCount = material.currentDynamicDrawSurfCount; - material.currentDynamicDrawSurfCount++; - } else { - SSBOOffset = material.staticMaterialsSSBOOffset; - drawSurfCount = material.currentStaticDrawSurfCount; - material.currentStaticDrawSurfCount++; - } - - drawSurf->materialsSSBOOffset[stage] = ( SSBOOffset + drawSurfCount * material.shader->GetPaddedSize() ) / - material.shader->GetPaddedSize(); - - if ( pStage->dynamic ) { - hasDynamicStages = true; - } - AddStageTextures( drawSurf, pStage, &material ); - - pStage->surfaceDataUpdater( materialsData, material, drawSurf, stage ); + // We need some of the values from the remapped stage, but material/materialPack ID has to come from pStage + shaderStage_t* remappedStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; + const uint32_t SSBOOffset = + remappedStage->materialsSSBOOffset + remappedStage->variantOffsets[drawSurf->shaderVariant[stage]]; tess.currentDrawSurf = drawSurf; - tess.currentSSBOOffset = tess.currentDrawSurf->materialsSSBOOffset[stage]; - tess.materialID = tess.currentDrawSurf->materialIDs[stage]; - tess.materialPackID = tess.currentDrawSurf->materialPackIDs[stage]; + tess.currentSSBOOffset = SSBOOffset; + tess.materialID = pStage->materialID; + tess.materialPackID = pStage->materialPackID; Tess_Begin( Tess_StageIteratorDummy, nullptr, nullptr, false, -1, 0 ); rb_surfaceTable[Util::ordinal( *drawSurf->surface )]( drawSurf->surface ); - pStage->colorRenderer( pStage ); + remappedStage->colorRenderer( remappedStage ); Tess_Clear(); drawSurf->drawCommandIDs[stage] = lastCommandID; - if ( pStage->dynamic ) { - drawSurf->materialsSSBOOffset[stage] = ( SSBOOffset - dynamicDrawSurfsOffset + drawSurfCount * - material.shader->GetPaddedSize() ) / material.shader->GetPaddedSize(); - } - stage++; } - - if ( hasDynamicStages ) { - // We need a copy here because the memory pointed to by drawSurf will change later - // We'll probably need a separate buffer for entities other than world entity + ensure we don't store a drawSurf with - // invalid pointers - dynamicDrawSurfs.emplace_back( *drawSurf ); - } } } } + for ( shaderStage_t* pStage : materialStages ) { + if ( pStage->dynamic ) { + pStage->materialsSSBOOffset = pStage->dynamicMaterialsOffset; + } + } + materialsSSBO.UnmapBuffer(); } -// This generates the buffer GLIndirect commands +void MaterialSystem::GenerateMaterialsBuffer( std::vector& stages, const uint32_t size, uint32_t* materialsData ) { + // Shader uniforms are set to 0 if they're not specified, so make sure we do that here too + memset( materialsData, 0, size * sizeof( uint32_t ) ); + for ( shaderStage_t* pStage : stages ) { + Material& material = materialPacks[pStage->materialPackID].materials[pStage->materialID]; + + /* Stage variants are essentially copies of the same stage with slightly different values that + normally come from a drawSurf_t */ + uint32_t variants = 0; + for ( int i = 0; i < Util::ordinal( ShaderStageVariant::ALL ) && variants < pStage->variantOffset; i++ ) { + if ( pStage->variantOffsets[i] != -1 ) { + pStage->mayUseVertexOverbright = i & Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ); + pStage->vertexLit = i & Util::ordinal( ShaderStageVariant::VERTEX_LIT ); + pStage->fullbright = i & Util::ordinal( ShaderStageVariant::FULLBRIGHT ); + pStage->currentOffset = pStage->variantOffsets[i]; + pStage->surfaceDataUpdater( materialsData, material, pStage ); + variants++; + } + } + } +} + +void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, TexBundle* textureBundles ) { + for ( TextureData& textureData : textures ) { + for ( int i = 0; i < MAX_TEXTURE_BUNDLES; i++ ) { + if ( textureData.texBundlesOverride[i] ) { + textureBundles->textures[i] = textureData.texBundlesOverride[i]->texture->bindlessTextureHandle; + continue; + } + + const textureBundle_t* bundle = textureData.texBundles[i]; + if ( bundle && bundle->image[0] ) { + if ( generatingWorldCommandBuffer ) { + textureBundles->textures[i] = bundle->image[0]->texture->bindlessTextureHandle; + } else { + textureBundles->textures[i] = BindAnimatedImage( 0, bundle ); + } + } + } + + // While reflection, liquid and heatHaze shaders use the matrix from TB_NORMALMAP bundle, it's never actually parsed + RB_CalcTexMatrix( textureData.texBundles[0], textureBundles->textureMatrix ); + textureBundles++; + } +} + +// This generates the buffers with indirect rendering commands etc. void MaterialSystem::GenerateWorldCommandBuffer() { Log::Debug( "Generating world command buffer" ); @@ -789,8 +632,6 @@ void MaterialSystem::GenerateWorldCommandBuffer() { Log::Debug( "Total batch count: %u", totalBatchCount ); - drawSurf_t* drawSurf; - surfaceDescriptorsSSBO.BindBuffer(); surfaceDescriptorsCount = totalDrawSurfs; descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; @@ -798,6 +639,67 @@ void MaterialSystem::GenerateWorldCommandBuffer() { nullptr, GL_STATIC_DRAW ); uint32_t* surfaceDescriptors = surfaceDescriptorsSSBO.MapBufferRange( surfaceDescriptorsCount * descriptorSize ); + texDataSSBO.BindBuffer(); + texDataSSBO.BufferStorage( ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr ); + texDataSSBO.MapAll(); + TexBundle* textureBundles = ( TexBundle* ) texDataSSBO.GetData(); + memset( textureBundles, 0, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * sizeof( uint32_t ) ); + + GenerateTexturesBuffer( texData, textureBundles ); + + textureBundles += texData.size(); + + GenerateTexturesBuffer( dynamicTexData, textureBundles ); + + dynamicTexDataOffset = texData.size() * TEX_BUNDLE_SIZE; + dynamicTexDataSize = dynamicTexData.size() * TEX_BUNDLE_SIZE; + + texDataSSBO.FlushAll(); + texDataSSBO.UnmapBuffer(); + texDataSSBO.UnBindBuffer(); + + lightmapDataUBO.BindBuffer(); + lightmapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); + lightmapDataUBO.MapAll(); + uint64_t* lightmapData = ( uint64_t* ) lightmapDataUBO.GetData(); + memset( lightmapData, 0, MAX_LIGHTMAPS * LIGHTMAP_SIZE * sizeof( uint32_t ) ); + + for ( uint32_t i = 0; i < tr.lightmaps.size(); i++ ) { + if ( !tr.lightmaps[i]->texture->hasBindlessHandle ) { + tr.lightmaps[i]->texture->GenBindlessHandle(); + } + lightmapData[i * 2] = tr.lightmaps[i]->texture->bindlessTextureHandle; + } + for ( uint32_t i = 0; i < tr.deluxemaps.size(); i++ ) { + if ( !tr.deluxemaps[i]->texture->hasBindlessHandle ) { + tr.deluxemaps[i]->texture->GenBindlessHandle(); + } + lightmapData[i * 2 + 1] = tr.deluxemaps[i]->texture->bindlessTextureHandle; + } + + ASSERT_LE( tr.lightmaps.size(), 256 ); // Engine supports up to 256 lightmaps currently, so we use 8 bits to address them + + if ( tr.lightmaps.size() == 256 ) { + /* It's very unlikely that this would actually happen, but put the warn here just in case + If needed, another bit can be added to the lightmap address in rendering commands, but that would mean + that its hex representation would no longer be easily "parsable" by just looking at it in a frame debugger */ + Log::Warn( "Material system only supports up to 255 lightmaps, got 256" ); + } else { + if ( !tr.whiteImage->texture->hasBindlessHandle ) { + tr.whiteImage->texture->GenBindlessHandle(); + } + if ( !tr.blackImage->texture->hasBindlessHandle ) { + tr.blackImage->texture->GenBindlessHandle(); + } + // Use lightmap 255 for drawSurfs that use a full white image for their lightmap + lightmapData[255 * 2] = tr.whiteImage->texture->bindlessTextureHandle; + lightmapData[255 * 2 + 1] = tr.blackImage->texture->bindlessTextureHandle; + } + + lightmapDataUBO.FlushAll(); + lightmapDataUBO.UnmapBuffer(); + lightmapDataUBO.UnBindBuffer(); + surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; surfaceCommandsSSBO.BindBuffer(); @@ -858,7 +760,8 @@ void MaterialSystem::GenerateWorldCommandBuffer() { } for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) { - drawSurf = &tr.refdef.drawSurfs[i]; + const drawSurf_t* drawSurf = &tr.refdef.drawSurfs[i]; + if ( drawSurf->entity != &tr.worldEntity ) { continue; } @@ -891,7 +794,8 @@ void MaterialSystem::GenerateWorldCommandBuffer() { if ( depthPrePass ) { const drawSurf_t* depthDrawSurf = drawSurf->depthSurface; - const Material* material = &materialPacks[depthDrawSurf->materialPackIDs[0]].materials[depthDrawSurf->materialIDs[0]]; + const Material* material = &materialPacks[depthDrawSurf->shader->stages[0].materialPackID] + .materials[depthDrawSurf->shader->stages[0].materialID]; uint cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + depthDrawSurf->drawCommandIDs[0]; // Add 1 because cmd 0 == no-command surface.surfaceCommandIDs[0] = cmdID + 1; @@ -899,12 +803,16 @@ void MaterialSystem::GenerateWorldCommandBuffer() { SurfaceCommand surfaceCommand; surfaceCommand.enabled = 0; surfaceCommand.drawCommand = material->drawCommands[depthDrawSurf->drawCommandIDs[0]].cmd; + // We still need the textures for alpha-tested depth pre-pass surface commands + surfaceCommand.drawCommand.baseInstance |= depthDrawSurf->texDataDynamic[0] + ? ( depthDrawSurf->texDataIDs[0] + texData.size() ) << TEX_BUNDLE_BITS + : depthDrawSurf->texDataIDs[0] << TEX_BUNDLE_BITS; surfaceCommands[cmdID] = surfaceCommand; } uint32_t stage = 0; for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - const Material* material = &materialPacks[drawSurf->materialPackIDs[stage]].materials[drawSurf->materialIDs[stage]]; + const Material* material = &materialPacks[pStage->materialPackID].materials[pStage->materialID]; uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + drawSurf->drawCommandIDs[stage]; // Add 1 because cmd 0 == no-command surface.surfaceCommandIDs[stage + ( depthPrePass ? 1 : 0 )] = cmdID + 1; @@ -912,6 +820,10 @@ void MaterialSystem::GenerateWorldCommandBuffer() { SurfaceCommand surfaceCommand; surfaceCommand.enabled = 0; surfaceCommand.drawCommand = material->drawCommands[drawSurf->drawCommandIDs[stage]].cmd; + surfaceCommand.drawCommand.baseInstance |= drawSurf->texDataDynamic[stage] + ? ( drawSurf->texDataIDs[stage] + texData.size() ) << TEX_BUNDLE_BITS + : drawSurf->texDataIDs[stage] << TEX_BUNDLE_BITS; + surfaceCommand.drawCommand.baseInstance |= ( HasLightMap( drawSurf ) ? GetLightMapNum( drawSurf ) : 255 ) << LIGHTMAP_BITS; surfaceCommands[cmdID] = surfaceCommand; stage++; @@ -919,7 +831,8 @@ void MaterialSystem::GenerateWorldCommandBuffer() { if ( drawSurf->fogSurface ) { const drawSurf_t* fogDrawSurf = drawSurf->fogSurface; - const Material* material = &materialPacks[fogDrawSurf->materialPackIDs[0]].materials[fogDrawSurf->materialIDs[0]]; + const Material* material = &materialPacks[fogDrawSurf->shader->stages[0].materialPackID] + .materials[fogDrawSurf->shader->stages[0].materialID]; uint cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + fogDrawSurf->drawCommandIDs[0]; // Add 1 because cmd 0 == no-command surface.surfaceCommandIDs[stage + ( depthPrePass ? 1 : 0 )] = cmdID + 1; @@ -1392,8 +1305,131 @@ void ProcessMaterialFog( Material* material, shaderStage_t* pStage, drawSurf_t* material->program = gl_fogQuake3ShaderMaterial->GetProgram( pStage->deformIndex ); } +void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage ) { + const int variant = ( pStage->mayUseVertexOverbright ? Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ) : 0 ) + | ( pStage->vertexLit ? Util::ordinal( ShaderStageVariant::VERTEX_LIT ) : 0 ) + | ( pStage->fullbright ? Util::ordinal( ShaderStageVariant::FULLBRIGHT ) : 0 ); + + if ( pStage->variantOffsets[variant] == -1 ) { + pStage->variantOffsets[variant] = pStage->variantOffset; + pStage->variantOffset++; + } + + drawSurf->shaderVariant[stage] = variant; + + // Look for a stage that will have the same data layout and data + data changes themselves + for ( shaderStage_t* pStage2 : materialStages ) { + if ( pStage == pStage2 ) { + return; + } + + if ( pStage->shaderBinder != pStage2->shaderBinder ) { + continue; + } + + if ( pStage->dynamic != pStage2->dynamic ) { + continue; + } + + if ( pStage->ifExp != pStage2->ifExp ) { + continue; + } + + if ( pStage->rgbGen != pStage2->rgbGen ) { + continue; + } + + if ( pStage->rgbGen == colorGen_t::CGEN_WAVEFORM && pStage->rgbWave != pStage2->rgbWave ) { + continue; + } + + if ( pStage->rgbGen == colorGen_t::CGEN_CUSTOM_RGB && pStage->rgbExp != pStage2->rgbExp ) { + continue; + } + + if ( pStage->rgbGen == colorGen_t::CGEN_CUSTOM_RGBs && + !( pStage->redExp == pStage2->redExp && pStage->greenExp == pStage2->greenExp && pStage->blueExp == pStage2->blueExp ) ) { + continue; + } + + if ( ( pStage->type == stageType_t::ST_STYLELIGHTMAP || pStage->type == stageType_t::ST_STYLECOLORMAP + || pStage2->type == stageType_t::ST_STYLELIGHTMAP || pStage2->type == stageType_t::ST_STYLECOLORMAP ) && pStage->type != pStage2->type ) { + continue; + } + + if ( pStage->alphaGen != pStage2->alphaGen ) { + continue; + } + + if ( pStage->alphaGen == alphaGen_t::AGEN_WAVEFORM && pStage->alphaWave != pStage2->alphaWave ) { + continue; + } + + if ( pStage->alphaGen == alphaGen_t::AGEN_CUSTOM && pStage->alphaExp != pStage2->alphaExp ) { + continue; + } + + if ( pStage->constantColor.Red() != pStage2->constantColor.Red() || pStage->constantColor.Green() != pStage2->constantColor.Green() + || pStage->constantColor.Blue() != pStage2->constantColor.Blue() || pStage->constantColor.Alpha() != pStage2->constantColor.Alpha() ) { + continue; + } + + if ( pStage->depthFadeValue != pStage2->depthFadeValue ) { + continue; + } + + // Only GLS_ATEST_BITS affect stage data, the other bits go into the material + if ( ( pStage->stateBits & GLS_ATEST_BITS ) != ( pStage2->stateBits & GLS_ATEST_BITS ) ) { + continue; + } + + if ( pStage->refractionIndexExp != pStage2->refractionIndexExp || pStage->specularExponentMin != pStage2->specularExponentMin + || pStage->specularExponentMax != pStage2->specularExponentMax || pStage->fresnelPowerExp != pStage2->fresnelPowerExp + || pStage->fresnelScaleExp != pStage2->fresnelScaleExp || pStage->fresnelBiasExp != pStage2->fresnelBiasExp + || !VectorCompare( pStage->normalScale, pStage2->normalScale ) || pStage->normalIntensityExp != pStage2->normalIntensityExp + || pStage->fogDensityExp != pStage2->fogDensityExp || pStage->depthScaleExp != pStage2->depthScaleExp ) { + continue; + } + + pStage->materialRemappedStage = pStage2; + + return; + } + + // Add at the back if we haven't found any matching ones + materialStages.emplace_back( pStage ); + + if ( pStage->dynamic ) { + dynamicStages.emplace_back( pStage ); + } +} + void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, uint32_t& previousMaterialID ) { + lightMode_t lightMode; + deluxeMode_t deluxeMode; + SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); + pStage->mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP && drawSurf->bspSurface && pStage->shaderBinder == BindShaderGeneric3D; + pStage->vertexLit = lightMode == lightMode_t::VERTEX && pStage->shaderBinder == BindShaderLightMapping; + pStage->fullbright = lightMode == lightMode_t::FULLBRIGHT && pStage->shaderBinder == BindShaderLightMapping; + + ComputeDynamics( pStage ); + + AddStage( drawSurf, pStage, stage ); + + if ( pStage->initialized ) { + Material* material = &materialPacks[pStage->materialPackID].materials[pStage->materialID]; + if ( std::find( material->drawSurfs.begin(), material->drawSurfs.end(), drawSurf ) + == material->drawSurfs.end() ) { + material->drawSurfs.emplace_back( drawSurf ); + } + + AddStageTextures( drawSurf, stage, material ); + + stage++; + return; + } + Material material; uint32_t materialPack = 0; @@ -1426,12 +1462,6 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, material.vbo = glState.currentVBO; material.ibo = glState.currentIBO; - ComputeDynamics( pStage ); - - if ( pStage->texturesDynamic ) { - drawSurf->texturesDynamic[stage] = true; - } - material.bspSurface = drawSurf->bspSurface; pStage->materialProcessor( &material, pStage, drawSurf ); @@ -1462,20 +1492,17 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, } pStage->useMaterialSystem = true; - materials[previousMaterialID].totalDrawSurfCount++; - if ( pStage->dynamic ) { - materials[previousMaterialID].totalDynamicDrawSurfCount++; - } else { - materials[previousMaterialID].totalStaticDrawSurfCount++; - } + pStage->initialized = true; + + AddStageTextures( drawSurf, stage, &materials[previousMaterialID] ); if ( std::find( materials[previousMaterialID].drawSurfs.begin(), materials[previousMaterialID].drawSurfs.end(), drawSurf ) == materials[previousMaterialID].drawSurfs.end() ) { materials[previousMaterialID].drawSurfs.emplace_back( drawSurf ); } - drawSurf->materialIDs[stage] = previousMaterialID; - drawSurf->materialPackIDs[stage] = materialPack; + pStage->materialID = previousMaterialID; + pStage->materialPackID = materialPack; packIDs[materialPack] = id; @@ -1537,7 +1564,7 @@ void MaterialSystem::GenerateWorldMaterials() { rb_surfaceTable[Util::ordinal( *( drawSurf->surface ) )]( drawSurf->surface ); Tess_Clear(); - // Only add the main surface for surfaces with depth pre-pass to the total count + // Only add the main surface for surfaces with depth pre-pass or fog to the total count if ( !drawSurf->materialSystemSkip ) { totalDrawSurfs++; } @@ -1556,14 +1583,17 @@ void MaterialSystem::GenerateWorldMaterials() { totalCount += pack.materials.size(); } Log::Notice( "Generated %u materials from %u surfaces", totalCount, tr.refdef.numDrawSurfs ); + Log::Notice( "Materials UBO: total: %.2f kb, dynamic: %.2f kb, texData: %.2f kb", + totalStageSize * 4 / 1024.0f, dynamicStagesSize * 4 / 1024.0f, + ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * 4 / 1024.0f ); + /* for ( const MaterialPack& materialPack : materialPacks ) { Log::Notice( "materialPack sort: %i %i", Util::ordinal( materialPack.fromSort ), Util::ordinal( materialPack.toSort ) ); for ( const Material& material : materialPack.materials ) { - Log::Notice( "id: %u, useSync: %b, sync: %u, program: %i, stateBits: %u, totalDrawSurfCount: %u, shader: %s, vbo: %s, ibo: %s" - ", staticDrawSurfs: %u, dynamicDrawSurfs: %u, culling: %i", - material.id, material.useSync, material.syncMaterial, material.program, material.stateBits, material.totalDrawSurfCount, - material.shader->GetName(), material.vbo->name, material.ibo->name, material.currentStaticDrawSurfCount, - material.currentDynamicDrawSurfCount, material.cullType ); + Log::Notice( "id: %u, useSync: %b, sync: %u, program: %i, stateBits: %u, total drawSurfs: %u, shader: %s, vbo: %s, ibo: %s" + ", culling: %i", + material.id, material.useSync, material.syncMaterial, material.program, material.stateBits, material.drawSurfs.size(), + material.shader->GetName(), material.vbo->name, material.ibo->name, material.cullType ); } } */ @@ -1582,7 +1612,12 @@ void MaterialSystem::AddAllWorldSurfaces() { generatingWorldCommandBuffer = false; } -void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, shaderStage_t* pStage, Material* material ) { +void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stage, Material* material ) { + TextureData textureData; + const shaderStage_t* pStage = &drawSurf->shader->stages[stage]; + + int bundleNum = 0; + bool dynamic = false; for ( const textureBundle_t& bundle : pStage->bundle ) { if ( bundle.isVideoMap ) { material->AddTexture( tr.cinematicImage[bundle.videoMapHandle]->texture ); @@ -1594,10 +1629,16 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, shaderStage_t* pSta material->AddTexture( image->texture ); } } + + if ( bundle.numImages > 1 || bundle.numTexMods > 0 ) { + dynamic = true; + } + + textureData.texBundles[bundleNum] = &bundle; + bundleNum++; } // Add lightmap and deluxemap for this surface to the material as well - lightMode_t lightMode; deluxeMode_t deluxeMode; SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); @@ -1609,6 +1650,21 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, shaderStage_t* pSta material->AddTexture( lightmap->texture ); material->AddTexture( deluxemap->texture ); + if ( pStage->type == stageType_t::ST_STYLELIGHTMAP ) { + textureData.texBundlesOverride[TB_COLORMAP] = lightmap; + } + + std::vector& textures = dynamic ? dynamicTexData : texData; + + std::vector::iterator it = std::find( textures.begin(), textures.end(), textureData ); + if ( it == textures.end() ) { + drawSurf->texDataIDs[stage] = textures.size(); + textures.emplace_back( textureData ); + } else { + drawSurf->texDataIDs[stage] = it - textures.begin(); + } + drawSurf->texDataDynamic[stage] = dynamic; + if ( glConfig2.realtimeLighting ) { if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { material->AddTexture( tr.lighttileRenderImage->texture ); @@ -1618,25 +1674,23 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, shaderStage_t* pSta // Dynamic surfaces are those whose values in the SSBO can be updated void MaterialSystem::UpdateDynamicSurfaces() { - if ( dynamicDrawSurfsSize == 0 ) { - return; + if ( dynamicStagesSize > 0 ) { + materialsSSBO.BindBuffer(); + uint32_t* materialsData = materialsSSBO.MapBufferRange( dynamicStagesOffset, dynamicStagesSize ); + + GenerateMaterialsBuffer( dynamicStages, dynamicStagesSize, materialsData ); + + materialsSSBO.UnmapBuffer(); } - materialsSSBO.BindBuffer(); - uint32_t* materialsData = materialsSSBO.MapBufferRange( dynamicDrawSurfsOffset, dynamicDrawSurfsSize ); - // Shader uniforms are set to 0 if they're not specified, so make sure we do that here too - memset( materialsData, 0, 4 * dynamicDrawSurfsSize ); - for ( drawSurf_t& drawSurf : dynamicDrawSurfs ) { - uint32_t stage = 0; - for ( shaderStage_t* pStage = drawSurf.shader->stages; pStage < drawSurf.shader->lastStage; pStage++ ) { - Material& material = materialPacks[drawSurf.materialPackIDs[stage]].materials[drawSurf.materialIDs[stage]]; + if ( dynamicTexDataSize > 0 ) { + texDataSSBO.BindBuffer(); + TexBundle* textureBundles = ( TexBundle* ) texDataSSBO.MapBufferRange( dynamicTexDataOffset, dynamicTexDataSize ); - pStage->surfaceDataUpdater( materialsData, material, &drawSurf, stage ); + GenerateTexturesBuffer( dynamicTexData, textureBundles ); - stage++; - } + texDataSSBO.UnmapBuffer(); } - materialsSSBO.UnmapBuffer(); } void MaterialSystem::UpdateFrameData() { @@ -1890,19 +1944,24 @@ void MaterialSystem::GeneratePortalBoundingSpheres() { void MaterialSystem::Free() { generatedWorldCommandBuffer = false; - dynamicDrawSurfs.clear(); + materialStages.clear(); + dynamicStages.clear(); autospriteSurfaces.clear(); portalSurfaces.clear(); portalSurfacesTmp.clear(); portalBounds.clear(); skyShaders.clear(); renderedMaterials.clear(); + texData.clear(); + dynamicTexData.clear(); R_SyncRenderThread(); surfaceCommandsSSBO.UnmapBuffer(); culledCommandsBuffer.UnmapBuffer(); atomicCommandCountersBuffer.UnmapBuffer(); + texDataSSBO.UnmapBuffer(); + lightmapDataUBO.UnmapBuffer(); if ( totalPortals > 0 ) { portalSurfacesSSBO.UnmapBuffer(); @@ -2206,6 +2265,9 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); + texDataSSBO.BindBufferBase(); + lightmapDataUBO.BindBufferBase(); + if ( r_showGlobalMaterials.Get() && material.sort != 0 && ( material.shaderBinder == BindShaderLightMapping || material.shaderBinder == BindShaderGeneric3D ) ) { vec3_t color; @@ -2320,6 +2382,9 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB ); + texDataSSBO.UnBindBufferBase(); + lightmapDataUBO.UnBindBufferBase(); + if ( material.usePolygonOffset ) { glDisable( GL_POLYGON_OFFSET_FILL ); } diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 9a41d0093c..16a22eabf9 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -70,14 +70,6 @@ struct DrawCommand { struct Material { uint32_t materialsSSBOOffset = 0; - uint32_t staticMaterialsSSBOOffset = 0; - uint32_t dynamicMaterialsSSBOOffset = 0; - uint32_t totalDrawSurfCount = 0; - uint32_t totalStaticDrawSurfCount = 0; - uint32_t totalDynamicDrawSurfCount = 0; - uint32_t currentDrawSurfCount = 0; - uint32_t currentStaticDrawSurfCount = 0; - uint32_t currentDynamicDrawSurfCount = 0; uint32_t globalID = 0; uint32_t surfaceCommandBatchOffset = 0; @@ -143,6 +135,69 @@ struct Material { } }; +struct TexBundle { + matrix_t textureMatrix; + GLuint64 textures[MAX_TEXTURE_BUNDLES]; + GLuint64 padding; +}; + +struct TextureData { + const textureBundle_t* texBundles[MAX_TEXTURE_BUNDLES] = { nullptr, nullptr, nullptr, nullptr, nullptr }; + // For ST_STYLELIGHTMAP stages + image_t* texBundlesOverride[MAX_TEXTURE_BUNDLES] = { nullptr, nullptr, nullptr, nullptr, nullptr }; + + bool operator==( const TextureData& other ) const { + for ( int i = 0; i < MAX_TEXTURE_BUNDLES; i++ ) { + if ( texBundlesOverride[i] != other.texBundlesOverride[i] ) { + return false; + } + + // Skip texBundles check for ST_STYLELIGHTMAP + if ( texBundlesOverride[i] ) { + continue; + } + + const textureBundle_t* bundle = texBundles[i]; + const textureBundle_t* otherBundle = other.texBundles[i]; + + if ( bundle->numImages != otherBundle->numImages ) { + return false; + } + + if ( ( bundle->numImages > 1 ) && ( bundle->imageAnimationSpeed != otherBundle->imageAnimationSpeed ) ) { + return false; + } + + const uint8_t numImages = bundle->numImages > 0 ? bundle->numImages : 1; + for ( int j = 0; j < numImages; j++ ) { + if ( bundle->image[j] != otherBundle->image[j] ) { + return false; + } + } + + if ( bundle->numTexMods != otherBundle->numTexMods ) { + return false; + } + + for ( size_t j = 0; j < bundle->numTexMods; j++ ) { + if ( bundle->texMods[j] != otherBundle->texMods[j] ) { + return false; + } + } + } + + return true; + } + + TextureData() { + } + + TextureData( const TextureData& other ) { + memcpy( texBundles, other.texBundles, MAX_TEXTURE_BUNDLES * sizeof( textureBundle_t* ) ); + memcpy( texBundlesOverride, other.texBundlesOverride, MAX_TEXTURE_BUNDLES * sizeof( image_t* ) ); + } +}; + enum class MaterialDebugMode { NONE, DEPTH, @@ -178,6 +233,10 @@ extern PortalView portalStack[MAX_VIEWS]; #define INDIRECT_COMMAND_SIZE 5 #define SURFACE_COMMAND_SIZE 4 #define SURFACE_COMMAND_BATCH_SIZE 2 +#define TEX_BUNDLE_SIZE 28 +#define TEX_BUNDLE_BITS 12 +#define LIGHTMAP_SIZE 4 +#define LIGHTMAP_BITS 24 #define PORTAL_SURFACE_SIZE 8 #define MAX_FRAMES 2 @@ -276,7 +335,8 @@ class MaterialSystem { void GenerateDepthImages( const int width, const int height, imageParams_t imageParms ); - void AddStageTextures( drawSurf_t* drawSurf, shaderStage_t* pStage, Material* material ); + void AddStageTextures( drawSurf_t* drawSurf, const uint32_t stage, Material* material ); + void AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage ); void ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, uint32_t& previousMaterialID ); void GenerateWorldMaterials(); @@ -284,6 +344,9 @@ class MaterialSystem { void GenerateWorldCommandBuffer(); void GeneratePortalBoundingSpheres(); + void GenerateMaterialsBuffer( std::vector& stages, const uint32_t size, uint32_t* materialsData ); + void GenerateTexturesBuffer( std::vector& textures, TexBundle* textureBundles ); + void AddAllWorldSurfaces(); void Free(); @@ -308,9 +371,17 @@ class MaterialSystem { uint32_t surfaceCommandsCount = 0; uint32_t surfaceDescriptorsCount = 0; - std::vector dynamicDrawSurfs; - uint32_t dynamicDrawSurfsOffset = 0; - uint32_t dynamicDrawSurfsSize = 0; + std::vector materialStages; + std::vector dynamicStages; + + std::vector texData; + std::vector dynamicTexData; + + uint32_t totalStageSize; + uint32_t dynamicStagesOffset = 0; + uint32_t dynamicStagesSize = 0; + uint32_t dynamicTexDataOffset = 0; + uint32_t dynamicTexDataSize = 0; Frame frames[MAX_FRAMES]; uint32_t currentFrame = 0; @@ -324,6 +395,8 @@ class MaterialSystem { }; extern GLSSBO materialsSSBO; // Global +extern GLSSBO texDataSSBO; // Global +extern GLUBO lightmapDataUBO; // Global extern GLSSBO surfaceDescriptorsSSBO; // Global extern GLSSBO surfaceCommandsSSBO; // Per viewframe, GPU updated @@ -336,16 +409,18 @@ extern GLSSBO debugSSBO; // Global extern MaterialSystem materialSystem; -void UpdateSurfaceDataNONE( uint32_t*, Material&, drawSurf_t*, const uint32_t ); -void UpdateSurfaceDataNOP( uint32_t*, Material&, drawSurf_t*, const uint32_t ); -void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); -void UpdateSurfaceDataFog( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const uint32_t stage ); +void UpdateSurfaceDataNONE( uint32_t*, Material&, shaderStage_t* ); +void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ); +void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ); + +// void UpdateSurf( uint32) void BindShaderNONE( Material* ); void BindShaderNOP( Material* ); @@ -360,7 +435,7 @@ void BindShaderFog( Material* material ); void ProcessMaterialNONE( Material*, shaderStage_t*, drawSurf_t* ); void ProcessMaterialNOP( Material*, shaderStage_t*, drawSurf_t* ); -void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ); +void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ); void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); diff --git a/src/engine/renderer/ShadeCommon.h b/src/engine/renderer/ShadeCommon.h index 79fc32abff..f83f6ecf92 100644 --- a/src/engine/renderer/ShadeCommon.h +++ b/src/engine/renderer/ShadeCommon.h @@ -32,12 +32,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =========================================================================== */ -inline size_t GetLightMapNum( shaderCommands_t* tess ) +inline size_t GetLightMapNum( const shaderCommands_t* tess ) { return tess->lightmapNum; } -inline size_t GetLightMapNum( drawSurf_t* drawSurf ) +inline size_t GetLightMapNum( const drawSurf_t* drawSurf ) { return drawSurf->lightmapNum(); } diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index d37926ffdb..5ef5fc7910 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1360,8 +1360,35 @@ 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) readonly buffer materialsSSBO {\n" - " Material materials[];\n" - "};\n\n"; + " Material materials[];\n" + "};\n\n"; + std::string texDataBlock = "struct TexData {\n" + " mat4 u_TextureMatrix;\n" + " uvec2 u_DiffuseMap;\n" + " uvec2 u_NormalMap;\n" + " uvec2 u_HeightMap;\n" + " uvec2 u_MaterialMap;\n" + " uvec2 u_GlowMap;\n" + " uvec2 padding;\n" + "};\n\n" + "layout(std430, binding = 6) readonly buffer texDataSSBO {\n" + " TexData texData[];\n" + "};\n\n" + "#define u_TextureMatrix texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix\n" + "#define u_DiffuseMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_DiffuseMap )\n" + "#define u_NormalMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_NormalMap )\n" + "#define u_HeightMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_HeightMap )\n" + "#define u_MaterialMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialMap )\n" + "#define u_GlowMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_GlowMap )\n\n" + "struct LightMapData {\n" + " uvec2 u_LightMap;\n" + " uvec2 u_DeluxeMap;\n" + "};\n\n" + "layout(std140, binding = 7) uniform lightmapDataUBO {\n" + " LightMapData lightmapData[256];\n" + "};\n\n" + "#define u_LightMap_initial lightmapData[( baseInstance >> 24 ) & 0xFF].u_LightMap\n" + "#define u_DeluxeMap_initial lightmapData[( baseInstance >> 24 ) & 0xFF].u_DeluxeMap\n\n"; std::string materialDefines; /* Generate the struct and defines in the form of: @@ -1380,24 +1407,25 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str continue; } - if ( uniform->IsTexture() ) { - materialStruct += " uvec2 "; - materialStruct += uniform->GetName(); - } else { - materialStruct += " " + uniform->GetType() + " " + uniform->GetName(); - } + if ( !uniform->IsTexture() ) { + materialStruct += " " + uniform->GetType() + " " + uniform->GetName(); - if ( uniform->GetComponentSize() ) { - materialStruct += "[ " + std::to_string( uniform->GetComponentSize() ) + " ]"; + if ( uniform->GetComponentSize() ) { + materialStruct += "[ " + std::to_string( uniform->GetComponentSize() ) + " ]"; + } + materialStruct += ";\n"; + + // vec3 is aligned to 4 components, so just pad it with int + // TODO: Try to move 1 component uniforms here to avoid wasting memory + if ( uniform->GetSTD430Size() == 3 ) { + materialStruct += " int "; + materialStruct += uniform->GetName(); + materialStruct += "_padding;\n"; + } } - materialStruct += ";\n"; - // vec3 is aligned to 4 components, so just pad it with int - // TODO: Try to move 1 component uniforms here to avoid wasting memory - if ( uniform->GetSTD430Size() == 3 ) { - materialStruct += " int "; - materialStruct += uniform->GetName(); - materialStruct += "_padding;\n"; + if ( uniform->IsTexture() ) { + continue; } materialDefines += "#define "; @@ -1407,7 +1435,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str materialDefines += "_initial uvec2("; // We'll need this to create sampler objects later } - materialDefines += " materials[baseInstance]."; + materialDefines += " materials[baseInstance & 0xFFF]."; materialDefines += uniform->GetName(); if ( uniform->IsTexture() ) { @@ -1419,7 +1447,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str // Array of structs is aligned to the largest member of the struct for ( uint i = 0; i < shader->padding; i++ ) { - materialStruct += " int material_padding" + std::to_string( i ); + materialStruct += " int material_padding" + std::to_string( i ); materialStruct += ";\n"; } @@ -1457,7 +1485,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str materialDefines += "\n"; - newShaderText = "#define USE_MATERIAL_SYSTEM\n" + materialStruct + materialBlock + materialDefines + shaderMain; + newShaderText = "#define USE_MATERIAL_SYSTEM\n" + materialStruct + materialBlock + texDataBlock + materialDefines + shaderMain; return newShaderText; } @@ -1978,7 +2006,7 @@ void GLShader::PostProcessUniforms() { std::vector globalUniforms; for ( GLUniform* uniform : _uniforms ) { - if ( uniform->IsGlobal() ) { + if ( uniform->IsGlobal() || uniform->IsTexture() ) { globalUniforms.emplace_back( uniform ); } } @@ -2178,7 +2206,7 @@ void GLShader::SetRequiredVertexPointers() void GLShader::WriteUniformsToBuffer( uint32_t* buffer ) { uint32_t* bufPtr = buffer; for ( GLUniform* uniform : _uniforms ) { - if ( !uniform->IsGlobal() ) { + if ( !uniform->IsGlobal() && !uniform->IsTexture() ) { bufPtr = uniform->WriteToBuffer( bufPtr ); } } diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 7c49f7b9d8..8020bd1bf9 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -429,7 +429,8 @@ class GLUniform size_t _locationIndex; GLUniform( GLShader *shader, const char *name, const char* type, const GLuint std430Size, const GLuint std430Alignment, - const bool global, const int components = 0, const bool isTexture = false ) : + const bool global, const int components = 0, + const bool isTexture = false ) : _shader( shader ), _name( name ), _type( type ), @@ -1531,6 +1532,10 @@ class GLUBO : public GLBuffer { GLBuffer::BindBuffer( GL_UNIFORM_BUFFER ); } + void UnBindBuffer() { + GLBuffer::UnBindBuffer( GL_UNIFORM_BUFFER ); + } + void BufferStorage( const GLsizeiptr areaSize, const GLsizeiptr areaCount, const void* data ) { GLBuffer::BufferStorage( GL_UNIFORM_BUFFER, areaSize, areaCount, data ); } @@ -2140,6 +2145,7 @@ class u_ColorMap : GLUniformSampler2D { public: u_ColorMap( GLShader* shader ) : + // While u_ColorMap is used for some screen-space shaders, it's never global in material system shaders GLUniformSampler2D( shader, "u_ColorMap" ) { } @@ -2268,7 +2274,7 @@ class u_LightMap : GLUniformSampler { public: u_LightMap( GLShader* shader ) : - GLUniformSampler( shader, "u_LightMap", "sampler2D", 1 ) { + GLUniformSampler( shader, "u_LightMap", "sampler2D", 1, true ) { } void SetUniform_LightMapBindless( GLuint64 bindlessHandle ) { @@ -2284,7 +2290,7 @@ class u_DeluxeMap : GLUniformSampler { public: u_DeluxeMap( GLShader* shader ) : - GLUniformSampler( shader, "u_DeluxeMap", "sampler2D", 1 ) { + GLUniformSampler( shader, "u_DeluxeMap", "sampler2D", 1, true ) { } void SetUniform_DeluxeMapBindless( GLuint64 bindlessHandle ) { @@ -2701,7 +2707,7 @@ class u_TextureMatrix : { public: u_TextureMatrix( GLShader *shader ) : - GLUniformMatrix4f( shader, "u_TextureMatrix" ) + GLUniformMatrix4f( shader, "u_TextureMatrix", true ) { } diff --git a/src/engine/renderer/glsl_source/generic_vp.glsl b/src/engine/renderer/glsl_source/generic_vp.glsl index 6ea263733f..8553433d39 100644 --- a/src/engine/renderer/glsl_source/generic_vp.glsl +++ b/src/engine/renderer/glsl_source/generic_vp.glsl @@ -28,7 +28,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #insert vertexAnimation_vp #insert shaderProfiler_vp -uniform mat4 u_TextureMatrix; +#if !defined(USE_MATERIAL_SYSTEM) + uniform mat4 u_TextureMatrix; +#endif + uniform vec3 u_ViewOrigin; uniform float u_Time; diff --git a/src/engine/renderer/glsl_source/heatHaze_vp.glsl b/src/engine/renderer/glsl_source/heatHaze_vp.glsl index 29fd607409..05656d4836 100644 --- a/src/engine/renderer/glsl_source/heatHaze_vp.glsl +++ b/src/engine/renderer/glsl_source/heatHaze_vp.glsl @@ -28,7 +28,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA uniform float u_Time; -uniform mat4 u_TextureMatrix; +#if !defined(USE_MATERIAL_SYSTEM) + uniform mat4 u_TextureMatrix; +#endif + uniform mat4 u_ProjectionMatrixTranspose; uniform mat4 u_ModelViewMatrixTranspose; uniform mat4 u_ModelViewProjectionMatrix; diff --git a/src/engine/renderer/glsl_source/lightMapping_vp.glsl b/src/engine/renderer/glsl_source/lightMapping_vp.glsl index 6cdae695ed..e884649a6e 100644 --- a/src/engine/renderer/glsl_source/lightMapping_vp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_vp.glsl @@ -36,7 +36,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define USE_LIGHT_MAPPING #endif -uniform mat4 u_TextureMatrix; +#if !defined(USE_MATERIAL_SYSTEM) + uniform mat4 u_TextureMatrix; +#endif #if defined(USE_MODEL_SURFACE) uniform mat4 u_ModelMatrix; diff --git a/src/engine/renderer/glsl_source/liquid_vp.glsl b/src/engine/renderer/glsl_source/liquid_vp.glsl index b65e2f44e9..290e8c86c6 100644 --- a/src/engine/renderer/glsl_source/liquid_vp.glsl +++ b/src/engine/renderer/glsl_source/liquid_vp.glsl @@ -28,7 +28,10 @@ IN vec3 attr_Tangent; IN vec3 attr_Binormal; IN vec3 attr_Normal; -uniform mat4 u_TextureMatrix; +#if !defined(USE_MATERIAL_SYSTEM) + uniform mat4 u_TextureMatrix; +#endif + uniform mat4 u_ModelMatrix; uniform mat4 u_ModelViewProjectionMatrix; diff --git a/src/engine/renderer/glsl_source/material_fp.glsl b/src/engine/renderer/glsl_source/material_fp.glsl index 5584f24fdb..9bf8caf54e 100644 --- a/src/engine/renderer/glsl_source/material_fp.glsl +++ b/src/engine/renderer/glsl_source/material_fp.glsl @@ -59,7 +59,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif // !COMPUTELIGHT_GLSL #if defined(GENERIC_GLSL) - sampler2D u_ColorMap = sampler2D( u_ColorMap_initial ); + sampler2D u_ColorMap = sampler2D( u_DiffuseMap_initial ); #endif // !GENERIC_GLSL #if defined(LIGHTMAPPING_GLSL) @@ -71,7 +71,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif // !LIGHTMAPPING_GLSL #if defined(REFLECTION_CB_GLSL) - samplerCube u_ColorMapCube = samplerCube( u_ColorMapCube_initial ); + samplerCube u_ColorMapCube = samplerCube( u_DiffuseMap_initial ); #endif // !REFLECTION_CB_GLSL #if defined(RELIEFMAPPING_GLSL) @@ -89,8 +89,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif // !RELIEFMAPPING_GLSL #if defined(SKYBOX_GLSL) - samplerCube u_ColorMapCube = samplerCube( u_ColorMapCube_initial ); - sampler2D u_CloudMap = sampler2D( u_CloudMap_initial ); + samplerCube u_ColorMapCube = samplerCube( u_DiffuseMap_initial ); + sampler2D u_CloudMap = sampler2D( u_NormalMap_initial ); #endif // !SKYBOX_GLSL #else // !HAVE_ARB_bindless_texture diff --git a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl index 240f02093d..8380de171e 100644 --- a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl +++ b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl @@ -26,7 +26,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #insert vertexSkinning_vp #insert vertexAnimation_vp -uniform mat4 u_TextureMatrix; +#if !defined(USE_MATERIAL_SYSTEM) + uniform mat4 u_TextureMatrix; +#endif + uniform mat4 u_ModelMatrix; uniform mat4 u_ModelViewProjectionMatrix; diff --git a/src/engine/renderer/glsl_source/skybox_fp.glsl b/src/engine/renderer/glsl_source/skybox_fp.glsl index 13f0fa2477..a89f1a6b89 100644 --- a/src/engine/renderer/glsl_source/skybox_fp.glsl +++ b/src/engine/renderer/glsl_source/skybox_fp.glsl @@ -33,7 +33,9 @@ uniform sampler2D u_CloudMap; uniform bool u_UseCloudMap; uniform float u_CloudHeight; -uniform mat4 u_TextureMatrix; +#if !defined(USE_MATERIAL_SYSTEM) + uniform mat4 u_TextureMatrix; +#endif uniform float u_AlphaThreshold; diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 70352f37ec..72c040ab27 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -82,7 +82,7 @@ void GL_Unbind( image_t *image ) glBindTexture( image->type, 0 ); } -GLuint64 BindAnimatedImage( int unit, textureBundle_t *bundle ) +GLuint64 BindAnimatedImage( int unit, const textureBundle_t *bundle ) { int index; diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 3bf09cf9e7..1289710ea3 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -911,6 +911,24 @@ enum class shaderProfilerRenderSubGroupsMode { { expOperation_t ops[ MAX_EXPRESSION_OPS ]; size_t numOps; + + bool operator==( const expression_t& other ) { + if ( numOps != other.numOps ) { + return false; + } + + for ( size_t i = 0; i < numOps; i++ ) { + if ( ops[i].type != other.ops[i].type || ops[i].value != other.ops[i].value ) { + return false; + } + } + + return true; + } + + bool operator!=( const expression_t& other ) { + return !( *this == other ); + } }; struct waveForm_t @@ -921,6 +939,15 @@ enum class shaderProfilerRenderSubGroupsMode { float amplitude; float phase; float frequency; + + bool operator==( const waveForm_t& other ) { + return func == other.func && base == other.base && amplitude == other.amplitude && phase == other.phase + && frequency == other.frequency; + } + + bool operator!=( const waveForm_t& other ) { + return !( *this == other ); + } }; #define TR_MAX_TEXMODS 4 @@ -988,6 +1015,17 @@ enum class shaderProfilerRenderSubGroupsMode { expression_t sExp; expression_t tExp; expression_t rExp; + + bool operator==( const texModInfo_t& other ) { + return type == other.type && wave == other.wave && MatrixCompare( matrix, other.matrix ) + && scale[0] == other.scale[0] && scale[1] == other.scale[1] && scroll[0] == other.scroll[0] && scroll[1] == other.scroll[1] + && rotateSpeed == other.rotateSpeed + && sExp == other.sExp && tExp == other.tExp && rExp == other.rExp; + } + + bool operator!=( const texModInfo_t& other ) { + return !( *this == other ); + } }; #define MAX_IMAGE_ANIMATIONS 32 @@ -1064,10 +1102,17 @@ enum class shaderProfilerRenderSubGroupsMode { struct drawSurf_t; using stageRenderer_t = void(*)(shaderStage_t *); - using stageSurfaceDataUpdater_t = void(*)(uint32_t*, Material&, drawSurf_t*, const uint32_t); + using surfaceDataUpdater_t = void(*)(uint32_t*, Material&, shaderStage_t*); using stageShaderBinder_t = void(*)(Material*); using stageMaterialProcessor_t = void(*)(Material*, shaderStage_t*, drawSurf_t*); + enum class ShaderStageVariant { + VERTEX_OVERBRIGHT = 1, + VERTEX_LIT = BIT( 1 ), + FULLBRIGHT = BIT( 2 ), + ALL = BIT( 3 ) + }; + struct shaderStage_t { stageType_t type; @@ -1082,7 +1127,7 @@ enum class shaderProfilerRenderSubGroupsMode { stageRenderer_t colorRenderer; // Material renderer (code path for advanced OpenGL techniques like bindless textures). - stageSurfaceDataUpdater_t surfaceDataUpdater; + surfaceDataUpdater_t surfaceDataUpdater; stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; @@ -1164,12 +1209,28 @@ enum class shaderProfilerRenderSubGroupsMode { bool noFog; // used only for shaders that have fog disabled, so we can enable it for individual stages bool useMaterialSystem = false; + shader_t* shader; + shaderStage_t* materialRemappedStage = nullptr; + + uint32_t materialsSSBOOffset = 0; + uint32_t dynamicMaterialsOffset = 0; + + bool initialized = false; + bool bufferInitialized = false; + uint materialPackID = 0; uint materialID = 0; + bool dynamic = false; bool colorDynamic = false; - bool texMatricesDynamic = false; - bool texturesDynamic = false; + + int variantOffsets[Util::ordinal( ShaderStageVariant::ALL )]; + uint32_t variantOffset = 0; + uint32_t currentOffset = 0; + + bool mayUseVertexOverbright = false; + bool vertexLit = false; + bool fullbright = false; }; enum cullType_t : int @@ -1606,12 +1667,10 @@ enum class shaderProfilerRenderSubGroupsMode { int fog; int portalNum = -1; - uint materialsSSBOOffset[ MAX_SHADER_STAGES ]; - bool initialized[ MAX_SHADER_STAGES ]; - uint materialIDs[ MAX_SHADER_STAGES ]; - uint materialPackIDs[ MAX_SHADER_STAGES ]; - bool texturesDynamic[ MAX_SHADER_STAGES ]; - uint drawCommandIDs[ MAX_SHADER_STAGES ]; + uint32_t drawCommandIDs[MAX_SHADER_STAGES]; + uint32_t texDataIDs[MAX_SHADER_STAGES]; + bool texDataDynamic[MAX_SHADER_STAGES]; + uint32_t shaderVariant[MAX_SHADER_STAGES]; drawSurf_t* depthSurface; drawSurf_t* fogSurface; @@ -3192,7 +3251,7 @@ inline bool checkGLErrors() void GL_Bind( image_t *image ); void GL_BindNearestCubeMap( int unit, const vec3_t xyz ); void GL_Unbind( image_t *image ); - GLuint64 BindAnimatedImage( int unit, textureBundle_t *bundle ); + GLuint64 BindAnimatedImage( int unit, const textureBundle_t *bundle ); void GL_TextureFilter( image_t *image, filterType_t filterType ); void GL_BindProgram( shaderProgram_t *program ); GLuint64 GL_BindToTMU( int unit, image_t *image ); diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 235743706a..ee8297ad59 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -2698,9 +2698,9 @@ void Tess_StageIteratorColor() Tess_ComputeTexMatrices( pStage ); if ( materialSystem.generatingWorldCommandBuffer && pStage->useMaterialSystem ) { - tess.currentSSBOOffset = tess.currentDrawSurf->materialsSSBOOffset[stage]; - tess.materialID = tess.currentDrawSurf->materialIDs[stage]; - tess.materialPackID = tess.currentDrawSurf->materialPackIDs[stage]; + tess.currentSSBOOffset = pStage->materialsSSBOOffset; + tess.materialID = pStage->materialID; + tess.materialPackID = pStage->materialPackID; } pStage->colorRenderer( pStage ); diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index 77b52a80ce..81a45342c6 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -5239,6 +5239,8 @@ static void FinishStages() default: break; } + + memset( stage->variantOffsets, -1, Util::ordinal( ShaderStageVariant::ALL ) * sizeof( int ) ); } GroupActiveStages(); @@ -5372,7 +5374,7 @@ static void SetStagesRenderers() stageRenderer_t colorRenderer; // Material renderer (code path for advanced OpenGL techniques like bindless textures). - stageSurfaceDataUpdater_t surfaceDataUpdater; + surfaceDataUpdater_t surfaceDataUpdater; stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; @@ -5591,6 +5593,8 @@ static shader_t *MakeShaderPermanent() std::copy_n( stages[ s ].bundle[ b ].texMods, newShader->stages[ s ].bundle[ b ].numTexMods, newShader->stages[ s ].bundle[ b ].texMods ); } + + newShader->stages[ s ].shader = newShader; } newShader->lastStage = newShader->stages + numStages; diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index 37c95d6285..5e6ab9b246 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -730,6 +730,8 @@ static void R_InitLightUBO() static void R_InitMaterialBuffers() { if( glConfig2.usingMaterialSystem ) { materialsSSBO.GenBuffer(); + texDataSSBO.GenBuffer(); + lightmapDataUBO.GenBuffer(); surfaceDescriptorsSSBO.GenBuffer(); surfaceCommandsSSBO.GenBuffer(); @@ -860,6 +862,8 @@ void R_ShutdownVBOs() if ( glConfig2.usingMaterialSystem ) { materialsSSBO.DelBuffer(); + texDataSSBO.DelBuffer(); + lightmapDataUBO.DelBuffer(); surfaceDescriptorsSSBO.DelBuffer(); surfaceCommandsSSBO.DelBuffer(); From d7f1fe2fc9525fcd638449216e2e36392e6c2b4d Mon Sep 17 00:00:00 2001 From: VReaperV Date: Wed, 25 Dec 2024 11:37:11 +0300 Subject: [PATCH 02/16] Change u_TextureMatrix to mat3x2 Only these 6 components (0, 1, 4, 5, 12, 13) actually have an effect. This largely reduces the amount of data being transferred for texture matrices, as well as some useless computations. . --- src/engine/renderer/Material.cpp | 10 +++- src/engine/renderer/Material.h | 33 +++++------ src/engine/renderer/gl_shader.cpp | 3 +- src/engine/renderer/gl_shader.h | 57 ++++++++++++++++++- .../glsl_source/forwardLighting_vp.glsl | 4 +- .../renderer/glsl_source/generic_vp.glsl | 6 +- .../renderer/glsl_source/heatHaze_vp.glsl | 4 +- .../renderer/glsl_source/lightMapping_vp.glsl | 4 +- .../renderer/glsl_source/liquid_vp.glsl | 4 +- .../glsl_source/reflection_CB_vp.glsl | 4 +- .../renderer/glsl_source/shadowFill_vp.glsl | 4 +- .../renderer/glsl_source/skybox_fp.glsl | 4 +- 12 files changed, 96 insertions(+), 41 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 62b0572b22..2483e625ef 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -598,7 +598,15 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, } // While reflection, liquid and heatHaze shaders use the matrix from TB_NORMALMAP bundle, it's never actually parsed - RB_CalcTexMatrix( textureData.texBundles[0], textureBundles->textureMatrix ); + RB_CalcTexMatrix( textureData.texBundles[0], tess.svars.texMatrices[TB_COLORMAP] ); + /* We only actually need these 6 components to get the correct texture transformation, + the other ones are unused */ + textureBundles->textureMatrix[0] = tess.svars.texMatrices[TB_COLORMAP][0]; + textureBundles->textureMatrix[1] = tess.svars.texMatrices[TB_COLORMAP][1]; + textureBundles->textureMatrix[2] = tess.svars.texMatrices[TB_COLORMAP][4]; + textureBundles->textureMatrix[3] = tess.svars.texMatrices[TB_COLORMAP][5]; + textureBundles->textureMatrix[4] = tess.svars.texMatrices[TB_COLORMAP][12]; + textureBundles->textureMatrix[5] = tess.svars.texMatrices[TB_COLORMAP][13]; textureBundles++; } } diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 16a22eabf9..05fa55aa02 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -136,9 +136,8 @@ struct Material { }; struct TexBundle { - matrix_t textureMatrix; + vec_t textureMatrix[6]; GLuint64 textures[MAX_TEXTURE_BUNDLES]; - GLuint64 padding; }; struct TextureData { @@ -152,27 +151,25 @@ struct TextureData { return false; } - // Skip texBundles check for ST_STYLELIGHTMAP - if ( texBundlesOverride[i] ) { - continue; - } - const textureBundle_t* bundle = texBundles[i]; const textureBundle_t* otherBundle = other.texBundles[i]; - if ( bundle->numImages != otherBundle->numImages ) { - return false; - } - - if ( ( bundle->numImages > 1 ) && ( bundle->imageAnimationSpeed != otherBundle->imageAnimationSpeed ) ) { - return false; - } + // Skip texBundles image check for ST_STYLELIGHTMAP + if ( !texBundlesOverride[i] ) { + if ( bundle->numImages != otherBundle->numImages ) { + return false; + } - const uint8_t numImages = bundle->numImages > 0 ? bundle->numImages : 1; - for ( int j = 0; j < numImages; j++ ) { - if ( bundle->image[j] != otherBundle->image[j] ) { + if ( ( bundle->numImages > 1 ) && ( bundle->imageAnimationSpeed != otherBundle->imageAnimationSpeed ) ) { return false; } + + const uint8_t numImages = bundle->numImages > 0 ? bundle->numImages : 1; + for ( int j = 0; j < numImages; j++ ) { + if ( bundle->image[j] != otherBundle->image[j] ) { + return false; + } + } } if ( bundle->numTexMods != otherBundle->numTexMods ) { @@ -233,7 +230,7 @@ extern PortalView portalStack[MAX_VIEWS]; #define INDIRECT_COMMAND_SIZE 5 #define SURFACE_COMMAND_SIZE 4 #define SURFACE_COMMAND_BATCH_SIZE 2 -#define TEX_BUNDLE_SIZE 28 +#define TEX_BUNDLE_SIZE 16 #define TEX_BUNDLE_BITS 12 #define LIGHTMAP_SIZE 4 #define LIGHTMAP_BITS 24 diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 5ef5fc7910..1d0e9b6954 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1363,13 +1363,12 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str " Material materials[];\n" "};\n\n"; std::string texDataBlock = "struct TexData {\n" - " mat4 u_TextureMatrix;\n" + " mat3x2 u_TextureMatrix;\n" " uvec2 u_DiffuseMap;\n" " uvec2 u_NormalMap;\n" " uvec2 u_HeightMap;\n" " uvec2 u_MaterialMap;\n" " uvec2 u_GlowMap;\n" - " uvec2 padding;\n" "};\n\n" "layout(std430, binding = 6) readonly buffer texDataSSBO {\n" " TexData texData[];\n" diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 8020bd1bf9..41177b198e 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -1198,6 +1198,48 @@ class GLUniformMatrix4f : protected GLUniform matrix_t currentValue; }; +class GLUniformMatrix32f : protected GLUniform { + protected: + GLUniformMatrix32f( GLShader* shader, const char* name, const bool global = false ) : + GLUniform( shader, name, "mat3x2", 6, 2, global ) { + } + + inline void SetValue( GLboolean transpose, const vec_t* m ) { + shaderProgram_t* p = _shader->GetProgram(); + + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + +#if defined( LOG_GLSL_UNIFORMS ) + if ( r_logFile->integer ) { + GLimp_LogComment( va( "GLSL_SetUniformMatrix32f( %s, shader: %s, transpose: %d, [ %f, %f, %f, %f, %f, %f ] ) ---\n", + this->GetName(), _shader->GetName().c_str(), transpose, + m[0], m[1], m[2], m[3], m[4], m[5] ) ); + } +#endif + + if ( _shader->UseMaterialSystem() && !_global ) { + memcpy( currentValue, m, 6 * sizeof( float ) ); + return; + } + + glUniformMatrix3x2fv( p->uniformLocations[_locationIndex], 1, transpose, m ); + } + public: + size_t GetSize() override { + return 6 * sizeof( float ); + } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, currentValue, 6 * sizeof( float ) ); + return buffer + 6 * _components; + } + + private: + vec_t currentValue[6] {}; +}; + class GLUniformMatrix4fv : protected GLUniform { protected: @@ -2703,17 +2745,26 @@ class u_ShadowClipMap4 : }; class u_TextureMatrix : - GLUniformMatrix4f + GLUniformMatrix32f { public: u_TextureMatrix( GLShader *shader ) : - GLUniformMatrix4f( shader, "u_TextureMatrix", true ) + GLUniformMatrix32f( shader, "u_TextureMatrix", true ) { } void SetUniform_TextureMatrix( const matrix_t m ) { - this->SetValue( GL_FALSE, m ); + /* We only actually need these 6 components to get the correct texture transformation, + the other ones are unused */ + static vec_t m2[6]; + m2[0] = m[0]; + m2[1] = m[1]; + m2[2] = m[4]; + m2[3] = m[5]; + m2[4] = m[12]; + m2[5] = m[13]; + this->SetValue( GL_FALSE, m2 ); } }; diff --git a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl b/src/engine/renderer/glsl_source/forwardLighting_vp.glsl index 2263d926f3..06f9039df2 100644 --- a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl +++ b/src/engine/renderer/glsl_source/forwardLighting_vp.glsl @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #insert vertexSkinning_vp #insert vertexAnimation_vp -uniform mat4 u_TextureMatrix; +uniform mat3x2 u_TextureMatrix; uniform mat4 u_LightAttenuationMatrix; uniform mat4 u_ModelMatrix; uniform mat4 u_ModelViewProjectionMatrix; @@ -86,7 +86,7 @@ void main() var_TexAttenuation = u_LightAttenuationMatrix * position; // transform diffusemap texcoords - var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; + var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; var_Color = color; } diff --git a/src/engine/renderer/glsl_source/generic_vp.glsl b/src/engine/renderer/glsl_source/generic_vp.glsl index 8553433d39..09042277f4 100644 --- a/src/engine/renderer/glsl_source/generic_vp.glsl +++ b/src/engine/renderer/glsl_source/generic_vp.glsl @@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #insert shaderProfiler_vp #if !defined(USE_MATERIAL_SYSTEM) - uniform mat4 u_TextureMatrix; + uniform mat3x2 u_TextureMatrix; #endif uniform vec3 u_ViewOrigin; @@ -95,9 +95,9 @@ void main() var_TexCoords = 0.5 + vec2(0.5, -0.5) * reflected.yz; } #elif defined(USE_TCGEN_LIGHTMAP) - var_TexCoords = (u_TextureMatrix * vec4(lmCoord, 0.0, 1.0)).xy; + var_TexCoords = (u_TextureMatrix * vec3(lmCoord, 1.0)).xy; #else - var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).xy; + var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).xy; #endif #if defined(USE_DEPTH_FADE) diff --git a/src/engine/renderer/glsl_source/heatHaze_vp.glsl b/src/engine/renderer/glsl_source/heatHaze_vp.glsl index 05656d4836..54b7b97206 100644 --- a/src/engine/renderer/glsl_source/heatHaze_vp.glsl +++ b/src/engine/renderer/glsl_source/heatHaze_vp.glsl @@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA uniform float u_Time; #if !defined(USE_MATERIAL_SYSTEM) - uniform mat4 u_TextureMatrix; + uniform mat3x2 u_TextureMatrix; #endif uniform mat4 u_ProjectionMatrixTranspose; @@ -75,7 +75,7 @@ void main() deformVec.z = dot(u_ModelViewMatrixTranspose[2], position); // transform normalmap texcoords - var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; + var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; d1 = dot(u_ProjectionMatrixTranspose[0], deformVec); d2 = dot(u_ProjectionMatrixTranspose[3], deformVec); diff --git a/src/engine/renderer/glsl_source/lightMapping_vp.glsl b/src/engine/renderer/glsl_source/lightMapping_vp.glsl index e884649a6e..49bee16a28 100644 --- a/src/engine/renderer/glsl_source/lightMapping_vp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_vp.glsl @@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif #if !defined(USE_MATERIAL_SYSTEM) - uniform mat4 u_TextureMatrix; + uniform mat3x2 u_TextureMatrix; #endif #if defined(USE_MODEL_SURFACE) @@ -106,7 +106,7 @@ void main() SHADER_PROFILER_SET // transform diffusemap texcoords - var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; + var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; // assign color var_Color = color; diff --git a/src/engine/renderer/glsl_source/liquid_vp.glsl b/src/engine/renderer/glsl_source/liquid_vp.glsl index 290e8c86c6..08f3ee2626 100644 --- a/src/engine/renderer/glsl_source/liquid_vp.glsl +++ b/src/engine/renderer/glsl_source/liquid_vp.glsl @@ -29,7 +29,7 @@ IN vec3 attr_Binormal; IN vec3 attr_Normal; #if !defined(USE_MATERIAL_SYSTEM) - uniform mat4 u_TextureMatrix; + uniform mat3x2 u_TextureMatrix; #endif uniform mat4 u_ModelMatrix; @@ -52,7 +52,7 @@ void main() var_Position = (u_ModelMatrix * vec4(attr_Position, 1.0)).xyz; // transform normalmap texcoords - var_TexCoords = (u_TextureMatrix * vec4(attr_TexCoord0, 0.0, 1.0)).st; + var_TexCoords = (u_TextureMatrix * vec3(attr_TexCoord0, 1.0)).st; var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz; var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz; diff --git a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl index 8380de171e..b87dc20fe5 100644 --- a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl +++ b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #insert vertexAnimation_vp #if !defined(USE_MATERIAL_SYSTEM) - uniform mat4 u_TextureMatrix; + uniform mat3x2 u_TextureMatrix; #endif uniform mat4 u_ModelMatrix; @@ -85,6 +85,6 @@ void main() var_Normal.xyz = (u_ModelMatrix * vec4(LB.normal, 0.0)).xyz; // transform normalmap texcoords - var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; + var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; } diff --git a/src/engine/renderer/glsl_source/shadowFill_vp.glsl b/src/engine/renderer/glsl_source/shadowFill_vp.glsl index 5becd198ff..3ac13c691e 100644 --- a/src/engine/renderer/glsl_source/shadowFill_vp.glsl +++ b/src/engine/renderer/glsl_source/shadowFill_vp.glsl @@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA uniform uint u_Color; -uniform mat4 u_TextureMatrix; +uniform mat3x2 u_TextureMatrix; uniform mat4 u_ModelMatrix; uniform mat4 u_ModelViewProjectionMatrix; @@ -70,7 +70,7 @@ void main() #endif // transform texcoords - var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; + var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; // assign color var_Color = unpackUnorm4x8( u_Color ); diff --git a/src/engine/renderer/glsl_source/skybox_fp.glsl b/src/engine/renderer/glsl_source/skybox_fp.glsl index a89f1a6b89..4a4bd38250 100644 --- a/src/engine/renderer/glsl_source/skybox_fp.glsl +++ b/src/engine/renderer/glsl_source/skybox_fp.glsl @@ -34,7 +34,7 @@ uniform bool u_UseCloudMap; uniform float u_CloudHeight; #if !defined(USE_MATERIAL_SYSTEM) - uniform mat4 u_TextureMatrix; + uniform mat3x2 u_TextureMatrix; #endif uniform float u_AlphaThreshold; @@ -68,7 +68,7 @@ void main() incidentRay.z += radiusWorld; incidentRay = normalize( incidentRay ); vec2 st = vec2( acos(incidentRay.x), acos(incidentRay.y) ); - st = (u_TextureMatrix * vec4(st, 0.0, 1.0)).xy; + st = (u_TextureMatrix * vec3(st, 1.0)).xy; color = texture2D( u_CloudMap, st ).rgba; } From 6a3e23f33dab4ff3f2be16eda5bb19a67130461e Mon Sep 17 00:00:00 2001 From: VReaperV Date: Wed, 25 Dec 2024 19:34:01 +0300 Subject: [PATCH 03/16] Fix material system dynamic stages --- src/engine/renderer/Material.cpp | 37 +++++++++++++------------------ src/engine/renderer/gl_shader.cpp | 4 ++-- src/engine/renderer/tr_local.h | 5 +++-- src/engine/renderer/tr_shade.cpp | 2 +- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 2483e625ef..2967adc110 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -142,7 +142,7 @@ void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ) { void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -178,7 +178,7 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shader void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -241,7 +241,7 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, sha void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -289,7 +289,7 @@ void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shade void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -309,7 +309,7 @@ void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderSta void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -331,7 +331,7 @@ void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderSta void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -357,7 +357,7 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderS void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; @@ -416,7 +416,7 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderSta void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = ( pStage->materialsSSBOOffset + pStage->currentOffset ) * material.shader->GetPaddedSize(); + const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; bool updated = !pStage->bufferInitialized || pStage->dynamic; @@ -477,9 +477,8 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { } ); uint32_t offset = 0; - uint32_t dynamicOffset = 0; dynamicStagesOffset = 0; - bool dynamicDrawSurfOffsetSet = false; + bool dynamicStagesOffsetSet = false; // Compute data size for stages for ( shaderStage_t* pStage : materialStages ) { @@ -490,22 +489,18 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { // Make sure padding is taken into account for dynamicStagesOffset if ( pStage->dynamic ) { - if ( !dynamicDrawSurfOffsetSet ) { + if ( !dynamicStagesOffsetSet ) { dynamicStagesOffset = offset; - dynamicDrawSurfOffsetSet = true; + dynamicStagesOffsetSet = true; } - - const uint32_t dynamicPadding = ( dynamicOffset % paddedSize == 0 ) ? 0 : paddedSize - ( dynamicOffset % paddedSize ); - dynamicOffset += dynamicPadding; - pStage->dynamicMaterialsOffset = dynamicOffset / paddedSize; - dynamicOffset += paddedSize * pStage->variantOffset; } - pStage->materialsSSBOOffset = offset / paddedSize; + pStage->materialOffset = offset / paddedSize; + pStage->bufferOffset = offset; offset += paddedSize * pStage->variantOffset; } - dynamicStagesSize = dynamicDrawSurfOffsetSet ? offset - dynamicStagesOffset : 0; + dynamicStagesSize = dynamicStagesOffsetSet ? offset - dynamicStagesOffset : 0; totalStageSize = offset; // 4 bytes per component @@ -527,7 +522,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { // We need some of the values from the remapped stage, but material/materialPack ID has to come from pStage shaderStage_t* remappedStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; const uint32_t SSBOOffset = - remappedStage->materialsSSBOOffset + remappedStage->variantOffsets[drawSurf->shaderVariant[stage]]; + remappedStage->materialOffset + remappedStage->variantOffsets[drawSurf->shaderVariant[stage]]; tess.currentDrawSurf = drawSurf; @@ -550,7 +545,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { for ( shaderStage_t* pStage : materialStages ) { if ( pStage->dynamic ) { - pStage->materialsSSBOOffset = pStage->dynamicMaterialsOffset; + pStage->bufferOffset -= dynamicStagesOffset; } } diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 1d0e9b6954..8dd02dc66c 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1359,7 +1359,7 @@ 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) readonly buffer materialsSSBO {\n" + std::string materialBlock = "layout(std430, binding = 0) restrict readonly buffer materialsSSBO {\n" " Material materials[];\n" "};\n\n"; std::string texDataBlock = "struct TexData {\n" @@ -1370,7 +1370,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str " uvec2 u_MaterialMap;\n" " uvec2 u_GlowMap;\n" "};\n\n" - "layout(std430, binding = 6) readonly buffer texDataSSBO {\n" + "layout(std430, binding = 6) restrict readonly buffer texDataSSBO {\n" " TexData texData[];\n" "};\n\n" "#define u_TextureMatrix texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix\n" diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 1289710ea3..a2688c6d97 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1212,8 +1212,9 @@ enum class shaderProfilerRenderSubGroupsMode { shader_t* shader; shaderStage_t* materialRemappedStage = nullptr; - uint32_t materialsSSBOOffset = 0; - uint32_t dynamicMaterialsOffset = 0; + uint32_t materialOffset = 0; + uint32_t bufferOffset = 0; + uint32_t dynamicBufferOffset = 0; bool initialized = false; bool bufferInitialized = false; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index ee8297ad59..ebc618b1d6 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -2698,7 +2698,7 @@ void Tess_StageIteratorColor() Tess_ComputeTexMatrices( pStage ); if ( materialSystem.generatingWorldCommandBuffer && pStage->useMaterialSystem ) { - tess.currentSSBOOffset = pStage->materialsSSBOOffset; + tess.currentSSBOOffset = pStage->materialOffset; tess.materialID = pStage->materialID; tess.materialPackID = pStage->materialPackID; } From fe55951446632226e62488f865c92ac4bddfdc1c Mon Sep 17 00:00:00 2001 From: VReaperV Date: Wed, 25 Dec 2024 21:31:17 +0300 Subject: [PATCH 04/16] Use UBOs for texData when possible --- src/engine/renderer/Material.cpp | 30 ++++++++++++++++----------- src/engine/renderer/Material.h | 13 ++++++++++-- src/engine/renderer/gl_shader.cpp | 34 +++++++++++++++++-------------- src/engine/renderer/tr_public.h | 1 + src/engine/sys/sdl_glimp.cpp | 1 + 5 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 2967adc110..352115c83a 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ShadeCommon.h" GLSSBO materialsSSBO( "materials", 0, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLSSBO texDataSSBO( "texData", 6, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLBuffer texDataSSBO( "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 ); @@ -600,8 +600,9 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, textureBundles->textureMatrix[1] = tess.svars.texMatrices[TB_COLORMAP][1]; textureBundles->textureMatrix[2] = tess.svars.texMatrices[TB_COLORMAP][4]; textureBundles->textureMatrix[3] = tess.svars.texMatrices[TB_COLORMAP][5]; - textureBundles->textureMatrix[4] = tess.svars.texMatrices[TB_COLORMAP][12]; - textureBundles->textureMatrix[5] = tess.svars.texMatrices[TB_COLORMAP][13]; + // These are stored as part of a vec4 in a UBO, so we need to convert them here as well + textureBundles->textureMatrix2[0] = tess.svars.texMatrices[TB_COLORMAP][12] * 32768.0f; + textureBundles->textureMatrix2[1] = tess.svars.texMatrices[TB_COLORMAP][13] * 32768.0f; textureBundles++; } } @@ -642,9 +643,11 @@ void MaterialSystem::GenerateWorldCommandBuffer() { nullptr, GL_STATIC_DRAW ); uint32_t* surfaceDescriptors = surfaceDescriptorsSSBO.MapBufferRange( surfaceDescriptorsCount * descriptorSize ); - texDataSSBO.BindBuffer(); - texDataSSBO.BufferStorage( ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr ); - texDataSSBO.MapAll(); + 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(); memset( textureBundles, 0, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * sizeof( uint32_t ) ); @@ -657,9 +660,9 @@ void MaterialSystem::GenerateWorldCommandBuffer() { dynamicTexDataOffset = texData.size() * TEX_BUNDLE_SIZE; dynamicTexDataSize = dynamicTexData.size() * TEX_BUNDLE_SIZE; - texDataSSBO.FlushAll(); + texDataSSBO.FlushAll( texDataBufferType ); texDataSSBO.UnmapBuffer(); - texDataSSBO.UnBindBuffer(); + texDataSSBO.UnBindBuffer( texDataBufferType ); lightmapDataUBO.BindBuffer(); lightmapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); @@ -1687,8 +1690,11 @@ void MaterialSystem::UpdateDynamicSurfaces() { } if ( dynamicTexDataSize > 0 ) { - texDataSSBO.BindBuffer(); - TexBundle* textureBundles = ( TexBundle* ) texDataSSBO.MapBufferRange( dynamicTexDataOffset, dynamicTexDataSize ); + texDataSSBO.BindBuffer( texDataBufferType ); + GL_CheckErrors(); + TexBundle* textureBundles = + ( TexBundle* ) texDataSSBO.MapBufferRange( texDataBufferType, dynamicTexDataOffset, dynamicTexDataSize ); + GL_CheckErrors(); GenerateTexturesBuffer( dynamicTexData, textureBundles ); @@ -2268,7 +2274,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); - texDataSSBO.BindBufferBase(); + texDataSSBO.BindBufferBase( texDataBufferType ); lightmapDataUBO.BindBufferBase(); if ( r_showGlobalMaterials.Get() && material.sort != 0 @@ -2385,7 +2391,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB ); - texDataSSBO.UnBindBufferBase(); + texDataSSBO.UnBindBufferBase( texDataBufferType ); lightmapDataUBO.UnBindBufferBase(); if ( material.usePolygonOffset ) { diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 05fa55aa02..9cba489951 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -136,7 +136,8 @@ struct Material { }; struct TexBundle { - vec_t textureMatrix[6]; + vec_t textureMatrix[4]; + uint32_t textureMatrix2[2]; GLuint64 textures[MAX_TEXTURE_BUNDLES]; }; @@ -236,6 +237,13 @@ extern PortalView portalStack[MAX_VIEWS]; #define LIGHTMAP_BITS 24 #define PORTAL_SURFACE_SIZE 8 +// 64kb min +#define MIN_MATERIAL_UBO_SIZE BIT( 16 ) + +/* 64kb UBO : 54kb texBundles, 4kb lightmaps, 2kb map shader stages, 4kb entity shader stages +Current mapss use up to ~38kb at max, without models */ +#define MAX_TEX_BUNDLES 54 * 1024 / 64 + #define MAX_FRAMES 2 #define MAX_VIEWFRAMES MAX_VIEWS * MAX_FRAMES // Buffer 2 frames for each view @@ -371,6 +379,7 @@ class MaterialSystem { std::vector materialStages; std::vector dynamicStages; + GLenum texDataBufferType; std::vector texData; std::vector dynamicTexData; @@ -392,7 +401,7 @@ class MaterialSystem { }; extern GLSSBO materialsSSBO; // Global -extern GLSSBO texDataSSBO; // Global +extern GLBuffer texDataSSBO; // Global extern GLUBO lightmapDataUBO; // Global extern GLSSBO surfaceDescriptorsSSBO; // Global diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 8dd02dc66c..63e635564b 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1362,23 +1362,27 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str std::string materialBlock = "layout(std430, binding = 0) restrict readonly buffer materialsSSBO {\n" " Material materials[];\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" + "};\n\n" + : "layout(std430, binding = 6) restrict readonly buffer texDataSSBO {\n" + " TexData texData[];\n" + "};\n\n"; + // We have to store these as a bunch of vec4/uvec4 because std140 pads everything to a vec4 std::string texDataBlock = "struct TexData {\n" - " mat3x2 u_TextureMatrix;\n" - " uvec2 u_DiffuseMap;\n" - " uvec2 u_NormalMap;\n" - " uvec2 u_HeightMap;\n" - " uvec2 u_MaterialMap;\n" - " uvec2 u_GlowMap;\n" + " vec4 u_TextureMatrix;\n" + " uvec4 u_TextureDiffuseMap;\n" + " uvec4 u_NormalHeightMap;\n" + " uvec4 u_MaterialGlowMap;\n" "};\n\n" - "layout(std430, binding = 6) restrict readonly buffer texDataSSBO {\n" - " TexData texData[];\n" - "};\n\n" - "#define u_TextureMatrix texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix\n" - "#define u_DiffuseMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_DiffuseMap )\n" - "#define u_NormalMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_NormalMap )\n" - "#define u_HeightMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_HeightMap )\n" - "#define u_MaterialMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialMap )\n" - "#define u_GlowMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_GlowMap )\n\n" + + texBuf + + "#define u_TextureMatrix mat3x2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix, vec2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureDiffuseMap.xy ) * vec2( 1.0f / 32768.0f ) )\n" + "#define u_DiffuseMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureDiffuseMap.zw )\n" + "#define u_NormalMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_NormalHeightMap.xy )\n" + "#define u_HeightMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_NormalHeightMap.zw )\n" + "#define u_MaterialMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialGlowMap.xy )\n" + "#define u_GlowMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialGlowMap.zw )\n\n" "struct LightMapData {\n" " uvec2 u_LightMap;\n" " uvec2 u_DeluxeMap;\n" diff --git a/src/engine/renderer/tr_public.h b/src/engine/renderer/tr_public.h index 038c069489..b5b320a3d9 100644 --- a/src/engine/renderer/tr_public.h +++ b/src/engine/renderer/tr_public.h @@ -77,6 +77,7 @@ struct glconfig2_t char shadingLanguageVersionString[ MAX_STRING_CHARS ]; int shadingLanguageVersion; + int maxUniformBlockSize; int maxVertexUniforms; // int maxVaryingFloats; int maxVertexAttribs; diff --git a/src/engine/sys/sdl_glimp.cpp b/src/engine/sys/sdl_glimp.cpp index 36519fccd3..a6cf29903a 100644 --- a/src/engine/sys/sdl_glimp.cpp +++ b/src/engine/sys/sdl_glimp.cpp @@ -2013,6 +2013,7 @@ static void GLimp_InitExtensions() } // Shader limits + glGetIntegerv( GL_MAX_UNIFORM_BLOCK_SIZE, &glConfig2.maxUniformBlockSize ); glGetIntegerv( GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &glConfig2.maxVertexUniforms ); glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &glConfig2.maxVertexAttribs ); From 02edbab058c9b63365c2e8b54ae01f62f5290b2e Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 26 Dec 2024 01:13:17 +0300 Subject: [PATCH 05/16] Comment out some unused args --- src/engine/renderer/Material.cpp | 20 ++++++++++---------- src/engine/renderer/Material.h | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 352115c83a..a2064ebe5f 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -140,7 +140,7 @@ void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ) { } void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ) { - shader_t* shader = pStage->shader; + // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; @@ -238,7 +238,7 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, sha gl_lightMappingShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shaderStage_t* pStage ) { +void UpdateSurfaceDataReflection( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; @@ -287,7 +287,7 @@ void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shade } void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ) { - shader_t* shader = pStage->shader; + // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; @@ -306,8 +306,8 @@ void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderSta gl_skyboxShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderStage_t* pStage ) { - shader_t* shader = pStage->shader; +void UpdateSurfaceDataScreen( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { + // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; @@ -328,8 +328,8 @@ void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderSta gl_screenShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderStage_t* pStage ) { - shader_t* shader = pStage->shader; +void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { + // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; @@ -354,8 +354,8 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderS gl_heatHazeShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderStage_t* pStage ) { - shader_t* shader = pStage->shader; +void UpdateSurfaceDataLiquid( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { + // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; @@ -414,7 +414,7 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderSta } void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ) { - shader_t* shader = pStage->shader; + // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 9cba489951..fe682bc41c 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -419,11 +419,11 @@ void UpdateSurfaceDataNONE( uint32_t*, Material&, shaderStage_t* ); void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ); void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ); void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataReflection( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataScreen( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataLiquid( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataScreen( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); +void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); +void UpdateSurfaceDataLiquid( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ); // void UpdateSurf( uint32) From 3acb7e2f6c3078167bfbd2b406c345992ae038a9 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 26 Dec 2024 11:04:08 +0300 Subject: [PATCH 06/16] Fix stage variants upload Also removed some now useless code. --- src/engine/renderer/Material.cpp | 57 +++++--------------------------- src/engine/renderer/tr_local.h | 1 - 2 files changed, 9 insertions(+), 49 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index a2064ebe5f..365b66ff96 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -145,12 +145,6 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shader const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - gl_genericShaderMaterial->BindProgram( material.deformIndex ); // u_AlphaThreshold @@ -181,12 +175,6 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, sha const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - gl_lightMappingShaderMaterial->BindProgram( material.deformIndex ); gl_lightMappingShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); @@ -244,12 +232,6 @@ void UpdateSurfaceDataReflection( uint32_t* materials, Material& /* material */, const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - // bind u_ColorMap vec3_t position; if ( backEnd.currentEntity && ( backEnd.currentEntity != &tr.worldEntity ) ) { @@ -292,12 +274,6 @@ void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderSta const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - gl_skyboxShaderMaterial->BindProgram( material.deformIndex ); // u_AlphaThreshold @@ -312,12 +288,6 @@ void UpdateSurfaceDataScreen( uint32_t* materials, Material& /* material */, sha const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - gl_screenShaderMaterial->BindProgram( pStage->deformIndex ); // bind u_CurrentMap @@ -334,12 +304,6 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& /* material */, s const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - float deformMagnitude = RB_EvalExpression( &pStage->deformMagnitudeExp, 1.0 ); gl_heatHazeShaderMaterial->SetUniform_DeformMagnitude( deformMagnitude ); @@ -360,12 +324,6 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, Material& /* material */, sha const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->colorDynamic || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - float fogDensity = RB_EvalExpression( &pStage->fogDensityExp, 0.001 ); vec4_t fogColor; Tess_ComputeColor( pStage ); @@ -419,12 +377,6 @@ void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_ const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - bool updated = !pStage->bufferInitialized || pStage->dynamic; - if ( !updated ) { - return; - } - pStage->bufferInitialized = true; - const fog_t* fog = material.fog; // u_Color @@ -567,7 +519,11 @@ void MaterialSystem::GenerateMaterialsBuffer( std::vector& stage pStage->vertexLit = i & Util::ordinal( ShaderStageVariant::VERTEX_LIT ); pStage->fullbright = i & Util::ordinal( ShaderStageVariant::FULLBRIGHT ); pStage->currentOffset = pStage->variantOffsets[i]; + + const uint32_t variantOffset = pStage->variantOffsets[i] * material.shader->GetPaddedSize(); + pStage->bufferOffset += variantOffset; pStage->surfaceDataUpdater( materialsData, material, pStage ); + pStage->bufferOffset -= variantOffset; variants++; } } @@ -1399,6 +1355,11 @@ void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint pStage->materialRemappedStage = pStage2; + if ( pStage2->variantOffsets[variant] == -1 ) { + pStage2->variantOffsets[variant] = pStage2->variantOffset; + pStage2->variantOffset++; + } + return; } diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index a2688c6d97..9a3f32a756 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1217,7 +1217,6 @@ enum class shaderProfilerRenderSubGroupsMode { uint32_t dynamicBufferOffset = 0; bool initialized = false; - bool bufferInitialized = false; uint materialPackID = 0; uint materialID = 0; From f77daa3f0401ec9550decde935dba3f51c03aa40 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 2 Jan 2025 14:25:37 +0300 Subject: [PATCH 07/16] Fix drawSurf-specific data with material system --- src/engine/renderer/Material.cpp | 83 ++++++++----------- src/engine/renderer/Material.h | 20 ++--- src/engine/renderer/gl_shader.cpp | 4 +- src/engine/renderer/gl_shader.h | 16 +++- .../renderer/glsl_source/fogQuake3_vp.glsl | 6 +- src/engine/renderer/tr_local.h | 11 ++- src/engine/renderer/tr_shade.cpp | 6 +- 7 files changed, 74 insertions(+), 72 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 365b66ff96..a468f33316 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -132,21 +132,19 @@ static void ComputeDynamics( shaderStage_t* pStage ) { // UpdateSurface*() functions will actually write the uniform values to the SSBO // Mirrors parts of the Render_*() functions in tr_shade.cpp -void UpdateSurfaceDataNONE( uint32_t*, Material&, shaderStage_t* ) { +void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t* ) { ASSERT_UNREACHABLE(); } -void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ) { +void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t* ) { } -void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ) { +void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ) { // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - gl_genericShaderMaterial->BindProgram( material.deformIndex ); - // u_AlphaThreshold gl_genericShaderMaterial->SetUniform_AlphaTest( pStage->stateBits ); @@ -154,7 +152,7 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shader colorGen_t rgbGen = SetRgbGen( pStage ); alphaGen_t alphaGen = SetAlphaGen( pStage ); - bool mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP && drawSurf->bspSurface; + bool mayUseVertexOverbright = pStage->mayUseVertexOverbright; const bool styleLightMap = pStage->type == stageType_t::ST_STYLELIGHTMAP || pStage->type == stageType_t::ST_STYLECOLORMAP; gl_genericShaderMaterial->SetUniform_ColorModulateColorGen( rgbGen, alphaGen, mayUseVertexOverbright, styleLightMap ); @@ -169,16 +167,12 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shader gl_genericShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, shaderStage_t* pStage ) { +void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - gl_lightMappingShaderMaterial->BindProgram( material.deformIndex ); - - gl_lightMappingShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - // u_ColorModulate colorGen_t rgbGen = SetRgbGen( pStage ); alphaGen_t alphaGen = SetAlphaGen( pStage ); @@ -226,7 +220,7 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, sha gl_lightMappingShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataReflection( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { +void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage) { shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; @@ -268,28 +262,24 @@ void UpdateSurfaceDataReflection( uint32_t* materials, Material& /* material */, gl_reflectionShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ) { +void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ) { // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - gl_skyboxShaderMaterial->BindProgram( material.deformIndex ); - // u_AlphaThreshold gl_skyboxShaderMaterial->SetUniform_AlphaTest( GLS_ATEST_NONE ); gl_skyboxShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataScreen( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { +void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage) { // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - gl_screenShaderMaterial->BindProgram( pStage->deformIndex ); - // bind u_CurrentMap /* FIXME: This is currently unused, but u_CurrentMap was made global for other shaders, this seems to be the only material system shader that might need it to not be global */ @@ -298,7 +288,7 @@ void UpdateSurfaceDataScreen( uint32_t* materials, Material& /* material */, sha gl_screenShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { +void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage) { // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; @@ -318,7 +308,7 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& /* material */, s gl_heatHazeShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLiquid( uint32_t* materials, Material& /* material */, shaderStage_t* pStage) { +void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage) { // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; @@ -371,17 +361,12 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, Material& /* material */, sha gl_liquidShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ) { +void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage ) { // shader_t* shader = pStage->shader; const uint32_t paddedOffset = pStage->bufferOffset; materials += paddedOffset; - const fog_t* fog = material.fog; - - // u_Color - gl_fogQuake3ShaderMaterial->SetUniform_Color( fog->color ); - gl_fogQuake3ShaderMaterial->WriteUniformsToBuffer( materials ); } @@ -424,8 +409,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { return false; } - return materialPacks[lhs->materialPackID].materials[lhs->materialID].shader->GetPaddedSize() - < materialPacks[rhs->materialPackID].materials[rhs->materialID].shader->GetPaddedSize(); + return lhs->paddedSize < rhs->paddedSize; } ); uint32_t offset = 0; @@ -434,8 +418,8 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { // Compute data size for stages for ( shaderStage_t* pStage : materialStages ) { - const uint32_t paddedSize = materialPacks[pStage->materialPackID].materials[pStage->materialID].shader->GetPaddedSize(); - const uint32_t padding = ( offset % paddedSize == 0 ) ? 0 : paddedSize - ( offset % paddedSize ); + const uint32_t paddedSize = pStage->paddedSize; + const uint32_t padding = !paddedSize || offset % paddedSize == 0 ? 0 : paddedSize - ( offset % paddedSize ); offset += padding; @@ -447,7 +431,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { } } - pStage->materialOffset = offset / paddedSize; + pStage->materialOffset = paddedSize ? offset / paddedSize : 0; pStage->bufferOffset = offset; offset += paddedSize * pStage->variantOffset; } @@ -466,7 +450,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { for ( drawSurf_t* drawSurf : material.drawSurfs ) { uint32_t stage = 0; for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - if ( pStage->materialID != material.id || pStage->materialPackID != materialPackID ) { + if ( drawSurf->materialIDs[stage] != material.id || drawSurf->materialPackIDs[stage] != materialPackID ) { stage++; continue; } @@ -479,8 +463,8 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { tess.currentDrawSurf = drawSurf; tess.currentSSBOOffset = SSBOOffset; - tess.materialID = pStage->materialID; - tess.materialPackID = pStage->materialPackID; + tess.materialID = drawSurf->materialIDs[stage]; + tess.materialPackID = drawSurf->materialPackIDs[stage]; Tess_Begin( Tess_StageIteratorDummy, nullptr, nullptr, false, -1, 0 ); rb_surfaceTable[Util::ordinal( *drawSurf->surface )]( drawSurf->surface ); @@ -508,8 +492,6 @@ void MaterialSystem::GenerateMaterialsBuffer( std::vector& stage // Shader uniforms are set to 0 if they're not specified, so make sure we do that here too memset( materialsData, 0, size * sizeof( uint32_t ) ); for ( shaderStage_t* pStage : stages ) { - Material& material = materialPacks[pStage->materialPackID].materials[pStage->materialID]; - /* Stage variants are essentially copies of the same stage with slightly different values that normally come from a drawSurf_t */ uint32_t variants = 0; @@ -520,9 +502,11 @@ void MaterialSystem::GenerateMaterialsBuffer( std::vector& stage pStage->fullbright = i & Util::ordinal( ShaderStageVariant::FULLBRIGHT ); pStage->currentOffset = pStage->variantOffsets[i]; - const uint32_t variantOffset = pStage->variantOffsets[i] * material.shader->GetPaddedSize(); + const uint32_t variantOffset = pStage->variantOffsets[i] * pStage->paddedSize; pStage->bufferOffset += variantOffset; - pStage->surfaceDataUpdater( materialsData, material, pStage ); + + pStage->surfaceDataUpdater( materialsData, pStage ); + pStage->bufferOffset -= variantOffset; variants++; } @@ -756,8 +740,8 @@ void MaterialSystem::GenerateWorldCommandBuffer() { if ( depthPrePass ) { const drawSurf_t* depthDrawSurf = drawSurf->depthSurface; - const Material* material = &materialPacks[depthDrawSurf->shader->stages[0].materialPackID] - .materials[depthDrawSurf->shader->stages[0].materialID]; + const Material* material = &materialPacks[depthDrawSurf->materialPackIDs[0]] + .materials[depthDrawSurf->materialIDs[0]]; uint cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + depthDrawSurf->drawCommandIDs[0]; // Add 1 because cmd 0 == no-command surface.surfaceCommandIDs[0] = cmdID + 1; @@ -774,7 +758,7 @@ void MaterialSystem::GenerateWorldCommandBuffer() { uint32_t stage = 0; for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - const Material* material = &materialPacks[pStage->materialPackID].materials[pStage->materialID]; + const Material* material = &materialPacks[drawSurf->materialPackIDs[stage]].materials[drawSurf->materialIDs[stage]]; uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + drawSurf->drawCommandIDs[stage]; // Add 1 because cmd 0 == no-command surface.surfaceCommandIDs[stage + ( depthPrePass ? 1 : 0 )] = cmdID + 1; @@ -793,8 +777,8 @@ void MaterialSystem::GenerateWorldCommandBuffer() { if ( drawSurf->fogSurface ) { const drawSurf_t* fogDrawSurf = drawSurf->fogSurface; - const Material* material = &materialPacks[fogDrawSurf->shader->stages[0].materialPackID] - .materials[fogDrawSurf->shader->stages[0].materialID]; + const Material* material = &materialPacks[fogDrawSurf->materialPackIDs[0]] + .materials[fogDrawSurf->materialIDs[0]]; uint cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + fogDrawSurf->drawCommandIDs[0]; // Add 1 because cmd 0 == no-command surface.surfaceCommandIDs[stage + ( depthPrePass ? 1 : 0 )] = cmdID + 1; @@ -1105,6 +1089,8 @@ void BindShaderFog( Material* material ) { gl_fogQuake3ShaderMaterial->SetUniform_FogDepthVector( fogDepthVector ); gl_fogQuake3ShaderMaterial->SetUniform_FogEyeT( eyeT ); + gl_fogQuake3ShaderMaterial->SetUniform_ColorGlobal( fog->color ); + gl_fogQuake3ShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); gl_fogQuake3ShaderMaterial->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); @@ -1384,8 +1370,8 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, AddStage( drawSurf, pStage, stage ); - if ( pStage->initialized ) { - Material* material = &materialPacks[pStage->materialPackID].materials[pStage->materialID]; + /* if ( pStage->initialized ) { + Material* material = &materialPacks[drawSurf->materialPackIDs[stage]].materials[drawSurf->materialIDs[stage]]; if ( std::find( material->drawSurfs.begin(), material->drawSurfs.end(), drawSurf ) == material->drawSurfs.end() ) { material->drawSurfs.emplace_back( drawSurf ); @@ -1395,7 +1381,7 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, stage++; return; - } + } */ Material material; @@ -1431,6 +1417,7 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, material.bspSurface = drawSurf->bspSurface; pStage->materialProcessor( &material, pStage, drawSurf ); + pStage->paddedSize = material.shader->GetPaddedSize(); std::vector& materials = materialPacks[materialPack].materials; std::vector::iterator currentSearchIt = materials.begin(); @@ -1468,8 +1455,8 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, materials[previousMaterialID].drawSurfs.emplace_back( drawSurf ); } - pStage->materialID = previousMaterialID; - pStage->materialPackID = materialPack; + drawSurf->materialIDs[stage] = previousMaterialID; + drawSurf->materialPackIDs[stage] = materialPack; packIDs[materialPack] = id; diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index fe682bc41c..ec7cf9771c 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -415,16 +415,16 @@ extern GLSSBO debugSSBO; // Global extern MaterialSystem materialSystem; -void UpdateSurfaceDataNONE( uint32_t*, Material&, shaderStage_t* ); -void UpdateSurfaceDataNOP( uint32_t*, Material&, shaderStage_t* ); -void UpdateSurfaceDataGeneric3D( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataReflection( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); -void UpdateSurfaceDataSkybox( uint32_t* materials, Material& material, shaderStage_t* pStage ); -void UpdateSurfaceDataScreen( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); -void UpdateSurfaceDataHeatHaze( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); -void UpdateSurfaceDataLiquid( uint32_t* materials, Material& /* material */, shaderStage_t* pStage); -void UpdateSurfaceDataFog( uint32_t* materials, Material& material, shaderStage_t* pStage ); +void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t* ); +void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t* ); +void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ); +void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ); +void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage); +void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ); +void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage); +void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage); +void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage); +void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage ); // void UpdateSurf( uint32) diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 63e635564b..c9770f95e3 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -2707,7 +2707,7 @@ GLShader_fogQuake3::GLShader_fogQuake3( GLShaderManager *manager ) : u_FogMap( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), - u_Color( this ), + u_ColorGlobal( this ), u_Bones( this ), u_VertexInterpolation( this ), u_FogDistanceVector( this ), @@ -2729,7 +2729,7 @@ GLShader_fogQuake3Material::GLShader_fogQuake3Material( GLShaderManager* manager u_FogMap( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), - u_Color( this ), + u_ColorGlobal( this ), u_FogDistanceVector( this ), u_FogDepthVector( this ), u_FogEyeT( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 41177b198e..72bd4b993c 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -3155,6 +3155,18 @@ class u_Color : } }; +class u_ColorGlobal : + GLUniform1ui { + public: + u_ColorGlobal( GLShader* shader ) : + GLUniform1ui( shader, "u_ColorGlobal", true ) { + } + + void SetUniform_ColorGlobal( const Color::Color& color ) { + this->SetValue( packUnorm4x8( color.ToArray() ) ); + } +}; + class u_Frame : GLUniform1ui { public: @@ -4376,7 +4388,7 @@ class GLShader_fogQuake3 : public u_FogMap, public u_ModelMatrix, public u_ModelViewProjectionMatrix, - public u_Color, + public u_ColorGlobal, public u_Bones, public u_VertexInterpolation, public u_FogDistanceVector, @@ -4396,7 +4408,7 @@ class GLShader_fogQuake3Material : public u_FogMap, public u_ModelMatrix, public u_ModelViewProjectionMatrix, - public u_Color, + public u_ColorGlobal, public u_FogDistanceVector, public u_FogDepthVector, public u_FogEyeT, diff --git a/src/engine/renderer/glsl_source/fogQuake3_vp.glsl b/src/engine/renderer/glsl_source/fogQuake3_vp.glsl index 77eba51fe1..33b216b485 100644 --- a/src/engine/renderer/glsl_source/fogQuake3_vp.glsl +++ b/src/engine/renderer/glsl_source/fogQuake3_vp.glsl @@ -28,8 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA uniform float u_Time; -uniform vec4 u_ColorModulate; -uniform uint u_Color; +uniform vec4 u_ColorModulate; +uniform uint u_ColorGlobal; uniform mat4 u_ModelMatrix; uniform mat4 u_ModelViewProjectionMatrix; @@ -58,7 +58,7 @@ void main() VertexFetch( position, LB, color, texCoord, lmCoord ); - color = /* color * u_ColorModulate + */ unpackUnorm4x8( u_Color ); + color = /* color * u_ColorModulate + */ unpackUnorm4x8( u_ColorGlobal ); DeformVertex( position, LB.normal, diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 9a3f32a756..c55836ed32 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1102,7 +1102,7 @@ enum class shaderProfilerRenderSubGroupsMode { struct drawSurf_t; using stageRenderer_t = void(*)(shaderStage_t *); - using surfaceDataUpdater_t = void(*)(uint32_t*, Material&, shaderStage_t*); + using surfaceDataUpdater_t = void(*)(uint32_t*, shaderStage_t*); using stageShaderBinder_t = void(*)(Material*); using stageMaterialProcessor_t = void(*)(Material*, shaderStage_t*, drawSurf_t*); @@ -1212,15 +1212,14 @@ enum class shaderProfilerRenderSubGroupsMode { shader_t* shader; shaderStage_t* materialRemappedStage = nullptr; + uint32_t paddedSize = 0; + uint32_t materialOffset = 0; uint32_t bufferOffset = 0; uint32_t dynamicBufferOffset = 0; bool initialized = false; - uint materialPackID = 0; - uint materialID = 0; - bool dynamic = false; bool colorDynamic = false; @@ -1667,6 +1666,10 @@ enum class shaderProfilerRenderSubGroupsMode { int fog; int portalNum = -1; + + uint32_t materialPackIDs[MAX_SHADER_STAGES]; + uint32_t materialIDs[MAX_SHADER_STAGES]; + uint32_t drawCommandIDs[MAX_SHADER_STAGES]; uint32_t texDataIDs[MAX_SHADER_STAGES]; bool texDataDynamic[MAX_SHADER_STAGES]; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index ebc618b1d6..8eb915f689 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -2317,7 +2317,7 @@ void Render_fog( shaderStage_t* pStage ) gl_fogQuake3Shader->SetUniform_FogEyeT( eyeT ); // u_Color - gl_fogQuake3Shader->SetUniform_Color( fog->color ); + gl_fogQuake3Shader->SetUniform_ColorGlobal( fog->color ); gl_fogQuake3Shader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); gl_fogQuake3Shader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); @@ -2699,8 +2699,8 @@ void Tess_StageIteratorColor() if ( materialSystem.generatingWorldCommandBuffer && pStage->useMaterialSystem ) { tess.currentSSBOOffset = pStage->materialOffset; - tess.materialID = pStage->materialID; - tess.materialPackID = pStage->materialPackID; + tess.materialID = tess.currentDrawSurf->materialIDs[stage]; + tess.materialPackID = tess.currentDrawSurf->materialPackIDs[stage]; } pStage->colorRenderer( pStage ); From 7596449032ff8c090800bfcf3c01ff1dd32aded3 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 2 Jan 2025 14:42:59 +0300 Subject: [PATCH 08/16] Some material system cleanup --- src/engine/renderer/Material.cpp | 47 ++++++++------------------------ src/engine/renderer/tr_shade.cpp | 44 ------------------------------ 2 files changed, 12 insertions(+), 79 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index a468f33316..cdc5f6e7fc 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -142,8 +142,7 @@ void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t* ) { void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ) { // shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; // u_AlphaThreshold gl_genericShaderMaterial->SetUniform_AlphaTest( pStage->stateBits ); @@ -170,8 +169,7 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ) { void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; // u_ColorModulate colorGen_t rgbGen = SetRgbGen( pStage ); @@ -223,8 +221,7 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ) void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage) { shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; // bind u_ColorMap vec3_t position; @@ -265,8 +262,7 @@ void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage) { void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ) { // shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; // u_AlphaThreshold gl_skyboxShaderMaterial->SetUniform_AlphaTest( GLS_ATEST_NONE ); @@ -277,8 +273,7 @@ void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ) { void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage) { // shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; // bind u_CurrentMap /* FIXME: This is currently unused, but u_CurrentMap was made global for other shaders, @@ -291,8 +286,7 @@ void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage) { void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage) { // shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; float deformMagnitude = RB_EvalExpression( &pStage->deformMagnitudeExp, 1.0 ); gl_heatHazeShaderMaterial->SetUniform_DeformMagnitude( deformMagnitude ); @@ -311,8 +305,7 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage) { void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage) { // shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; float fogDensity = RB_EvalExpression( &pStage->fogDensityExp, 0.001 ); vec4_t fogColor; @@ -364,8 +357,7 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage) { void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage ) { // shader_t* shader = pStage->shader; - const uint32_t paddedOffset = pStage->bufferOffset; - materials += paddedOffset; + materials += pStage->bufferOffset; gl_fogQuake3ShaderMaterial->WriteUniformsToBuffer( materials ); } @@ -468,7 +460,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { Tess_Begin( Tess_StageIteratorDummy, nullptr, nullptr, false, -1, 0 ); rb_surfaceTable[Util::ordinal( *drawSurf->surface )]( drawSurf->surface ); - remappedStage->colorRenderer( remappedStage ); + Tess_DrawElements(); Tess_Clear(); drawSurf->drawCommandIDs[stage] = lastCommandID; @@ -493,7 +485,7 @@ void MaterialSystem::GenerateMaterialsBuffer( std::vector& stage memset( materialsData, 0, size * sizeof( uint32_t ) ); for ( shaderStage_t* pStage : stages ) { /* Stage variants are essentially copies of the same stage with slightly different values that - normally come from a drawSurf_t */ + normally come from a drawSurf_t */ uint32_t variants = 0; for ( int i = 0; i < Util::ordinal( ShaderStageVariant::ALL ) && variants < pStage->variantOffset; i++ ) { if ( pStage->variantOffsets[i] != -1 ) { @@ -1368,21 +1360,6 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, ComputeDynamics( pStage ); - AddStage( drawSurf, pStage, stage ); - - /* if ( pStage->initialized ) { - Material* material = &materialPacks[drawSurf->materialPackIDs[stage]].materials[drawSurf->materialIDs[stage]]; - if ( std::find( material->drawSurfs.begin(), material->drawSurfs.end(), drawSurf ) - == material->drawSurfs.end() ) { - material->drawSurfs.emplace_back( drawSurf ); - } - - AddStageTextures( drawSurf, stage, material ); - - stage++; - return; - } */ - Material material; uint32_t materialPack = 0; @@ -1448,6 +1425,7 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, pStage->useMaterialSystem = true; pStage->initialized = true; + AddStage( drawSurf, pStage, stage ); AddStageTextures( drawSurf, stage, &materials[previousMaterialID] ); if ( std::find( materials[previousMaterialID].drawSurfs.begin(), materials[previousMaterialID].drawSurfs.end(), drawSurf ) @@ -1487,13 +1465,12 @@ void MaterialSystem::GenerateWorldMaterials() { backEnd.currentEntity = &tr.worldEntity; - drawSurf_t* drawSurf; totalDrawSurfs = 0; uint32_t packIDs[3] = { 0, 0, 0 }; for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) { - drawSurf = &tr.refdef.drawSurfs[i]; + drawSurf_t* drawSurf = &tr.refdef.drawSurfs[i]; if ( drawSurf->entity != &tr.worldEntity ) { continue; } diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 8eb915f689..88891a0757 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -818,11 +818,6 @@ void Render_generic3D( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_generic3D ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - GL_State( pStage->stateBits ); bool hasDepthFade = pStage->hasDepthFade; @@ -949,11 +944,6 @@ void Render_lightMapping( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_lightMapping ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - lightMode_t lightMode; deluxeMode_t deluxeMode; SetLightDeluxeMode( &tess, pStage->type, lightMode, deluxeMode ); @@ -1238,10 +1228,6 @@ static void Render_shadowFill( shaderStage_t *pStage ) GLimp_LogComment( "--- Render_shadowFill ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - return; - } - // remove blend modes stateBits = pStage->stateBits; stateBits &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); @@ -1872,11 +1858,6 @@ void Render_reflection_CB( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_reflection_CB ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - GL_State( pStage->stateBits ); // choose right shader program ---------------------------------- @@ -1968,11 +1949,6 @@ void Render_skybox( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_skybox ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - GL_State( pStage->stateBits ); gl_skyboxShader->BindProgram( pStage->deformIndex ); @@ -1998,11 +1974,6 @@ void Render_screen( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_screen ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - GL_State( pStage->stateBits ); gl_screenShader->BindProgram( pStage->deformIndex ); @@ -2058,11 +2029,6 @@ void Render_heatHaze( shaderStage_t *pStage ) GLimp_LogComment( "--- Render_heatHaze ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - // remove alpha test stateBits = pStage->stateBits; stateBits &= ~GLS_ATEST_BITS; @@ -2151,11 +2117,6 @@ void Render_liquid( shaderStage_t *pStage ) GLimp_LogComment( "--- Render_liquid ---\n" ); - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - // Tr3B: don't allow blend effects GL_State( pStage->stateBits & ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_DEPTHMASK_TRUE ) ); @@ -2250,11 +2211,6 @@ void Render_liquid( shaderStage_t *pStage ) void Render_fog( shaderStage_t* pStage ) { - if ( materialSystem.generatingWorldCommandBuffer ) { - Tess_DrawElements(); - return; - } - if ( r_noFog->integer || !r_wolfFog->integer || ( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) ) { return; From c33e85a3b4f6b8956189ccd4b22f329f36268b7e Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 2 Jan 2025 15:29:52 +0300 Subject: [PATCH 09/16] Use a UBO for materials instead of an SSBO --- src/engine/renderer/Material.cpp | 46 +++++++++++++++---------------- src/engine/renderer/Material.h | 4 +-- src/engine/renderer/gl_shader.cpp | 13 +++++---- src/engine/renderer/tr_vbo.cpp | 8 +++--- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index cdc5f6e7fc..45ecde2009 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -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 ); @@ -388,7 +388,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(), @@ -432,8 +432,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 ); @@ -477,7 +477,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { } } - materialsSSBO.UnmapBuffer(); + materialsUBO.UnmapBuffer(); } void MaterialSystem::GenerateMaterialsBuffer( std::vector& stages, const uint32_t size, uint32_t* materialsData ) { @@ -577,10 +577,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 ); @@ -592,9 +592,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 ); @@ -1606,24 +1606,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(); } } @@ -1894,7 +1894,7 @@ void MaterialSystem::Free() { surfaceCommandsSSBO.UnmapBuffer(); culledCommandsBuffer.UnmapBuffer(); atomicCommandCountersBuffer.UnmapBuffer(); - texDataSSBO.UnmapBuffer(); + texDataBuffer.UnmapBuffer(); lightmapDataUBO.UnmapBuffer(); if ( totalPortals > 0 ) { @@ -2057,7 +2057,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 ) { @@ -2199,7 +2199,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 @@ -2316,7 +2316,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 ) { diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index ec7cf9771c..123e4577cd 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -400,8 +400,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 diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index c9770f95e3..9fc5164fe6 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1359,9 +1359,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" @@ -2019,7 +2022,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 @@ -2030,9 +2032,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 } @@ -2051,6 +2051,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; } diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index 5e6ab9b246..daf3f504bf 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -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(); @@ -861,8 +861,8 @@ void R_ShutdownVBOs() } if ( glConfig2.usingMaterialSystem ) { - materialsSSBO.DelBuffer(); - texDataSSBO.DelBuffer(); + materialsUBO.DelBuffer(); + texDataBuffer.DelBuffer(); lightmapDataUBO.DelBuffer(); surfaceDescriptorsSSBO.DelBuffer(); From f91e241a348d7d015692ad099a0d66c692d4df55 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 2 Jan 2025 20:41:09 +0300 Subject: [PATCH 10/16] Fix material system texture matrices Also fixes an incorrect matrix constructor in shaders. --- src/engine/renderer/Material.cpp | 22 ++++++++++++---------- src/engine/renderer/Material.h | 5 +++-- src/engine/renderer/gl_shader.cpp | 23 +++++++++++++---------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 45ecde2009..ff36db3e1d 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -524,17 +524,16 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, } } - // While reflection, liquid and heatHaze shaders use the matrix from TB_NORMALMAP bundle, it's never actually parsed - RB_CalcTexMatrix( textureData.texBundles[0], tess.svars.texMatrices[TB_COLORMAP] ); + const int bundle = textureData.textureMatrixBundle; + RB_CalcTexMatrix( textureData.texBundles[bundle], tess.svars.texMatrices[bundle] ); /* We only actually need these 6 components to get the correct texture transformation, the other ones are unused */ - textureBundles->textureMatrix[0] = tess.svars.texMatrices[TB_COLORMAP][0]; - textureBundles->textureMatrix[1] = tess.svars.texMatrices[TB_COLORMAP][1]; - textureBundles->textureMatrix[2] = tess.svars.texMatrices[TB_COLORMAP][4]; - textureBundles->textureMatrix[3] = tess.svars.texMatrices[TB_COLORMAP][5]; - // These are stored as part of a vec4 in a UBO, so we need to convert them here as well - textureBundles->textureMatrix2[0] = tess.svars.texMatrices[TB_COLORMAP][12] * 32768.0f; - textureBundles->textureMatrix2[1] = tess.svars.texMatrices[TB_COLORMAP][13] * 32768.0f; + textureBundles->textureMatrix[0] = tess.svars.texMatrices[bundle][0]; + textureBundles->textureMatrix[1] = tess.svars.texMatrices[bundle][1]; + textureBundles->textureMatrix[2] = tess.svars.texMatrices[bundle][4]; + textureBundles->textureMatrix[3] = tess.svars.texMatrices[bundle][5]; + textureBundles->textureMatrix[4] = tess.svars.texMatrices[bundle][12]; + textureBundles->textureMatrix[5] = tess.svars.texMatrices[bundle][13]; textureBundles++; } } @@ -1549,7 +1548,9 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stag int bundleNum = 0; bool dynamic = false; - for ( const textureBundle_t& bundle : pStage->bundle ) { + for ( int i = 0; i < MAX_TEXTURE_BUNDLES; i++ ) { + const textureBundle_t& bundle = pStage->bundle[i]; + if ( bundle.isVideoMap ) { material->AddTexture( tr.cinematicImage[bundle.videoMapHandle]->texture ); continue; @@ -1562,6 +1563,7 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stag } if ( bundle.numImages > 1 || bundle.numTexMods > 0 ) { + textureData.textureMatrixBundle = i; dynamic = true; } diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 123e4577cd..3e03121c61 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -136,8 +136,7 @@ struct Material { }; struct TexBundle { - vec_t textureMatrix[4]; - uint32_t textureMatrix2[2]; + vec_t textureMatrix[6]; GLuint64 textures[MAX_TEXTURE_BUNDLES]; }; @@ -145,6 +144,7 @@ struct TextureData { const textureBundle_t* texBundles[MAX_TEXTURE_BUNDLES] = { nullptr, nullptr, nullptr, nullptr, nullptr }; // For ST_STYLELIGHTMAP stages image_t* texBundlesOverride[MAX_TEXTURE_BUNDLES] = { nullptr, nullptr, nullptr, nullptr, nullptr }; + int textureMatrixBundle = 0; bool operator==( const TextureData& other ) const { for ( int i = 0; i < MAX_TEXTURE_BUNDLES; i++ ) { @@ -193,6 +193,7 @@ struct TextureData { TextureData( const TextureData& other ) { memcpy( texBundles, other.texBundles, MAX_TEXTURE_BUNDLES * sizeof( textureBundle_t* ) ); memcpy( texBundlesOverride, other.texBundlesOverride, MAX_TEXTURE_BUNDLES * sizeof( image_t* ) ); + textureMatrixBundle = other.textureMatrixBundle; } }; diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 9fc5164fe6..6a1323001f 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1372,20 +1372,23 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str : "layout(std430, binding = 6) restrict readonly buffer texDataSSBO {\n" " TexData texData[];\n" "};\n\n"; - // We have to store these as a bunch of vec4/uvec4 because std140 pads everything to a vec4 + // We have to store u_TextureMatrix as vec4 + vec2 because otherwise it would be aligned to a vec4 under std140 std::string texDataBlock = "struct TexData {\n" " vec4 u_TextureMatrix;\n" - " uvec4 u_TextureDiffuseMap;\n" - " uvec4 u_NormalHeightMap;\n" - " uvec4 u_MaterialGlowMap;\n" + " vec2 u_TextureMatrix2;\n" + " uvec2 u_DiffuseMap;\n" + " uvec2 u_NormalMap;\n" + " uvec2 u_HeightMap;\n" + " uvec2 u_MaterialMap;\n" + " uvec2 u_GlowMap;\n" "};\n\n" + texBuf + - "#define u_TextureMatrix mat3x2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix, vec2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureDiffuseMap.xy ) * vec2( 1.0f / 32768.0f ) )\n" - "#define u_DiffuseMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureDiffuseMap.zw )\n" - "#define u_NormalMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_NormalHeightMap.xy )\n" - "#define u_HeightMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_NormalHeightMap.zw )\n" - "#define u_MaterialMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialGlowMap.xy )\n" - "#define u_GlowMap_initial uvec2( texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialGlowMap.zw )\n\n" + "#define u_TextureMatrix mat3x2( texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix.xy, texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix.zw, texData[( baseInstance >> 12 ) & 0xFFF].u_TextureMatrix2 )\n" + "#define u_DiffuseMap_initial texData[( baseInstance >> 12 ) & 0xFFF].u_DiffuseMap\n" + "#define u_NormalMap_initial texData[( baseInstance >> 12 ) & 0xFFF].u_NormalMap\n" + "#define u_HeightMap_initial texData[( baseInstance >> 12 ) & 0xFFF].u_HeightMap\n" + "#define u_MaterialMap_initial texData[( baseInstance >> 12 ) & 0xFFF].u_MaterialMap\n" + "#define u_GlowMap_initial texData[( baseInstance >> 12 ) & 0xFFF].u_GlowMap\n\n" "struct LightMapData {\n" " uvec2 u_LightMap;\n" " uvec2 u_DeluxeMap;\n" From 6fe7c12b60c51bc089d1547258af229864eddad9 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sat, 11 Jan 2025 15:36:49 +0300 Subject: [PATCH 11/16] Fix dynamic lights with material system The UBO bindings were conflicting with light UBO. --- src/engine/renderer/Material.cpp | 6 +++--- src/engine/renderer/gl_shader.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index ff36db3e1d..b5818560aa 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Material.h" #include "ShadeCommon.h" -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 ); +GLUBO materialsUBO( "materials", 6, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLBuffer texDataBuffer( "texData", 7, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO lightmapDataUBO( "texData", 8, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", 1, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); GLSSBO surfaceCommandsSSBO( "surfaceCommands", 2, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 6a1323001f..2591a820d1 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1361,15 +1361,15 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str std::string materialStruct = "\nstruct Material {\n"; // 6 kb for materials const uint32_t count = ( 4096 + 2048 ) / shader->GetPaddedSize(); - std::string materialBlock = "layout(std140, binding = 0) uniform materialsUBO {\n" + std::string materialBlock = "layout(std140, binding = 6) 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" + "layout(std140, binding = 7) uniform texDataUBO {\n" " TexData texData[" + std::to_string( MAX_TEX_BUNDLES ) + "]; \n" "};\n\n" - : "layout(std430, binding = 6) restrict readonly buffer texDataSSBO {\n" + : "layout(std430, binding = 7) restrict readonly buffer texDataSSBO {\n" " TexData texData[];\n" "};\n\n"; // We have to store u_TextureMatrix as vec4 + vec2 because otherwise it would be aligned to a vec4 under std140 @@ -1393,7 +1393,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str " uvec2 u_LightMap;\n" " uvec2 u_DeluxeMap;\n" "};\n\n" - "layout(std140, binding = 7) uniform lightmapDataUBO {\n" + "layout(std140, binding = 8) uniform lightmapDataUBO {\n" " LightMapData lightmapData[256];\n" "};\n\n" "#define u_LightMap_initial lightmapData[( baseInstance >> 24 ) & 0xFF].u_LightMap\n" From 10829a3f375a24a375600ddb6bad9de08a722893 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Fri, 24 Jan 2025 02:30:42 +0300 Subject: [PATCH 12/16] Remove a sneaky static --- src/engine/renderer/gl_shader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 72bd4b993c..73dad8d783 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -2757,7 +2757,7 @@ class u_TextureMatrix : { /* We only actually need these 6 components to get the correct texture transformation, the other ones are unused */ - static vec_t m2[6]; + vec_t m2[6]; m2[0] = m[0]; m2[1] = m[1]; m2[2] = m[4]; From 49da2f994430170d3afdb8a1c98f4452c6378df6 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 27 Jan 2025 03:28:54 +0300 Subject: [PATCH 13/16] Fix lightMapData naming Also make it in line with other usages of `lightMap`. --- src/engine/renderer/Material.cpp | 22 +++++++++++----------- src/engine/renderer/Material.h | 2 +- src/engine/renderer/gl_shader.cpp | 8 ++++---- src/engine/renderer/tr_vbo.cpp | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index b5818560aa..8c7c562045 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. GLUBO materialsUBO( "materials", 6, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); GLBuffer texDataBuffer( "texData", 7, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO lightmapDataUBO( "texData", 8, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO lightMapDataUBO( "lightMapData", 8, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", 1, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); GLSSBO surfaceCommandsSSBO( "surfaceCommands", 2, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); @@ -595,10 +595,10 @@ void MaterialSystem::GenerateWorldCommandBuffer() { texDataBuffer.UnmapBuffer(); texDataBuffer.UnBindBuffer( texDataBufferType ); - lightmapDataUBO.BindBuffer(); - lightmapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); - lightmapDataUBO.MapAll(); - uint64_t* lightmapData = ( uint64_t* ) lightmapDataUBO.GetData(); + lightMapDataUBO.BindBuffer(); + lightMapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); + lightMapDataUBO.MapAll(); + uint64_t* lightmapData = ( uint64_t* ) lightMapDataUBO.GetData(); memset( lightmapData, 0, MAX_LIGHTMAPS * LIGHTMAP_SIZE * sizeof( uint32_t ) ); for ( uint32_t i = 0; i < tr.lightmaps.size(); i++ ) { @@ -633,9 +633,9 @@ void MaterialSystem::GenerateWorldCommandBuffer() { lightmapData[255 * 2 + 1] = tr.blackImage->texture->bindlessTextureHandle; } - lightmapDataUBO.FlushAll(); - lightmapDataUBO.UnmapBuffer(); - lightmapDataUBO.UnBindBuffer(); + lightMapDataUBO.FlushAll(); + lightMapDataUBO.UnmapBuffer(); + lightMapDataUBO.UnBindBuffer(); surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; @@ -1897,7 +1897,7 @@ void MaterialSystem::Free() { culledCommandsBuffer.UnmapBuffer(); atomicCommandCountersBuffer.UnmapBuffer(); texDataBuffer.UnmapBuffer(); - lightmapDataUBO.UnmapBuffer(); + lightMapDataUBO.UnmapBuffer(); if ( totalPortals > 0 ) { portalSurfacesSSBO.UnmapBuffer(); @@ -2202,7 +2202,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); texDataBuffer.BindBufferBase( texDataBufferType ); - lightmapDataUBO.BindBufferBase(); + lightMapDataUBO.BindBufferBase(); if ( r_showGlobalMaterials.Get() && material.sort != 0 && ( material.shaderBinder == BindShaderLightMapping || material.shaderBinder == BindShaderGeneric3D ) ) { @@ -2319,7 +2319,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB ); texDataBuffer.UnBindBufferBase( texDataBufferType ); - lightmapDataUBO.UnBindBufferBase(); + lightMapDataUBO.UnBindBufferBase(); if ( material.usePolygonOffset ) { glDisable( GL_POLYGON_OFFSET_FILL ); diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 3e03121c61..c76f48d784 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -403,7 +403,7 @@ class MaterialSystem { extern GLUBO materialsUBO; // Global extern GLBuffer texDataBuffer; // Global -extern GLUBO lightmapDataUBO; // Global +extern GLUBO lightMapDataUBO; // Global extern GLSSBO surfaceDescriptorsSSBO; // Global extern GLSSBO surfaceCommandsSSBO; // Per viewframe, GPU updated diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 2591a820d1..785662be76 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1393,11 +1393,11 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str " uvec2 u_LightMap;\n" " uvec2 u_DeluxeMap;\n" "};\n\n" - "layout(std140, binding = 8) uniform lightmapDataUBO {\n" - " LightMapData lightmapData[256];\n" + "layout(std140, binding = 8) uniform lightMapDataUBO {\n" + " LightMapData lightMapData[256];\n" "};\n\n" - "#define u_LightMap_initial lightmapData[( baseInstance >> 24 ) & 0xFF].u_LightMap\n" - "#define u_DeluxeMap_initial lightmapData[( baseInstance >> 24 ) & 0xFF].u_DeluxeMap\n\n"; + "#define u_LightMap_initial lightMapData[( baseInstance >> 24 ) & 0xFF].u_LightMap\n" + "#define u_DeluxeMap_initial lightMapData[( baseInstance >> 24 ) & 0xFF].u_DeluxeMap\n\n"; std::string materialDefines; /* Generate the struct and defines in the form of: diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index daf3f504bf..e453a62d7e 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -731,7 +731,7 @@ static void R_InitMaterialBuffers() { if( glConfig2.usingMaterialSystem ) { materialsUBO.GenBuffer(); texDataBuffer.GenBuffer(); - lightmapDataUBO.GenBuffer(); + lightMapDataUBO.GenBuffer(); surfaceDescriptorsSSBO.GenBuffer(); surfaceCommandsSSBO.GenBuffer(); @@ -863,7 +863,7 @@ void R_ShutdownVBOs() if ( glConfig2.usingMaterialSystem ) { materialsUBO.DelBuffer(); texDataBuffer.DelBuffer(); - lightmapDataUBO.DelBuffer(); + lightMapDataUBO.DelBuffer(); surfaceDescriptorsSSBO.DelBuffer(); surfaceCommandsSSBO.DelBuffer(); From 21fce71f66f2c0d0d0e2d44e33f8d5a2186c3cfa Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 27 Jan 2025 03:31:00 +0300 Subject: [PATCH 14/16] Use default constructors/destructors for TextureData --- src/engine/renderer/Material.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index c76f48d784..30d9721927 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -186,15 +186,6 @@ struct TextureData { return true; } - - TextureData() { - } - - TextureData( const TextureData& other ) { - memcpy( texBundles, other.texBundles, MAX_TEXTURE_BUNDLES * sizeof( textureBundle_t* ) ); - memcpy( texBundlesOverride, other.texBundlesOverride, MAX_TEXTURE_BUNDLES * sizeof( image_t* ) ); - textureMatrixBundle = other.textureMatrixBundle; - } }; enum class MaterialDebugMode { From af6911e170cb4ee38a1bb573b9fa6a15f24d634a Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 27 Jan 2025 04:35:06 +0300 Subject: [PATCH 15/16] Send stage variant data through `UpdateSurfaceData*` --- src/engine/renderer/Material.cpp | 51 ++++++++++++++++---------------- src/engine/renderer/Material.h | 23 +++++++------- src/engine/renderer/tr_local.h | 7 +---- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 8c7c562045..e7d6f1de19 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -132,14 +132,14 @@ static void ComputeDynamics( shaderStage_t* pStage ) { // UpdateSurface*() functions will actually write the uniform values to the SSBO // Mirrors parts of the Render_*() functions in tr_shade.cpp -void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t* ) { +void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t*, bool, bool, bool ) { ASSERT_UNREACHABLE(); } -void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t* ) { +void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t*, bool, bool, bool ) { } -void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ) { +void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage, bool mayUseVertexOverbright, bool, bool ) { // shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -151,7 +151,6 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ) { colorGen_t rgbGen = SetRgbGen( pStage ); alphaGen_t alphaGen = SetAlphaGen( pStage ); - bool mayUseVertexOverbright = pStage->mayUseVertexOverbright; const bool styleLightMap = pStage->type == stageType_t::ST_STYLELIGHTMAP || pStage->type == stageType_t::ST_STYLECOLORMAP; gl_genericShaderMaterial->SetUniform_ColorModulateColorGen( rgbGen, alphaGen, mayUseVertexOverbright, styleLightMap ); @@ -166,7 +165,7 @@ void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ) { gl_genericShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ) { +void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage, bool, bool vertexLit, bool fullbright ) { shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -178,12 +177,12 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ) Tess_ComputeColor( pStage ); // HACK: This only has effect on vertex-lit surfaces - if ( pStage->vertexLit ) { + if ( vertexLit ) { SetVertexLightingSettings( lightMode_t::VERTEX, rgbGen ); } // u_ColorModulate - gl_lightMappingShaderMaterial->SetUniform_ColorModulateColorGen( rgbGen, alphaGen, false, !pStage->fullbright ); + gl_lightMappingShaderMaterial->SetUniform_ColorModulateColorGen( rgbGen, alphaGen, false, !fullbright ); // u_Color gl_lightMappingShaderMaterial->SetUniform_Color( tess.svars.color ); @@ -218,7 +217,7 @@ void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ) gl_lightMappingShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage) { +void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ) { shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -259,7 +258,7 @@ void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage) { gl_reflectionShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ) { +void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ) { // shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -270,7 +269,7 @@ void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ) { gl_skyboxShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage) { +void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ) { // shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -283,7 +282,7 @@ void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage) { gl_screenShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage) { +void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ) { // shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -302,7 +301,7 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage) { gl_heatHazeShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage) { +void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ) { // shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -354,7 +353,7 @@ void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage) { gl_liquidShaderMaterial->WriteUniformsToBuffer( materials ); } -void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage ) { +void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ) { // shader_t* shader = pStage->shader; materials += pStage->bufferOffset; @@ -489,15 +488,14 @@ void MaterialSystem::GenerateMaterialsBuffer( std::vector& stage uint32_t variants = 0; for ( int i = 0; i < Util::ordinal( ShaderStageVariant::ALL ) && variants < pStage->variantOffset; i++ ) { if ( pStage->variantOffsets[i] != -1 ) { - pStage->mayUseVertexOverbright = i & Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ); - pStage->vertexLit = i & Util::ordinal( ShaderStageVariant::VERTEX_LIT ); - pStage->fullbright = i & Util::ordinal( ShaderStageVariant::FULLBRIGHT ); - pStage->currentOffset = pStage->variantOffsets[i]; + const bool mayUseVertexOverbright = i & Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ); + const bool vertexLit = i & Util::ordinal( ShaderStageVariant::VERTEX_LIT ); + const bool fullbright = i & Util::ordinal( ShaderStageVariant::FULLBRIGHT ); const uint32_t variantOffset = pStage->variantOffsets[i] * pStage->paddedSize; pStage->bufferOffset += variantOffset; - pStage->surfaceDataUpdater( materialsData, pStage ); + pStage->surfaceDataUpdater( materialsData, pStage, mayUseVertexOverbright, vertexLit, fullbright ); pStage->bufferOffset -= variantOffset; variants++; @@ -1244,10 +1242,11 @@ void ProcessMaterialFog( Material* material, shaderStage_t* pStage, drawSurf_t* material->program = gl_fogQuake3ShaderMaterial->GetProgram( pStage->deformIndex ); } -void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage ) { - const int variant = ( pStage->mayUseVertexOverbright ? Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ) : 0 ) - | ( pStage->vertexLit ? Util::ordinal( ShaderStageVariant::VERTEX_LIT ) : 0 ) - | ( pStage->fullbright ? Util::ordinal( ShaderStageVariant::FULLBRIGHT ) : 0 ); +void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage, + const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright ) { + const int variant = ( mayUseVertexOverbright ? Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ) : 0 ) + | ( vertexLit ? Util::ordinal( ShaderStageVariant::VERTEX_LIT ) : 0 ) + | ( fullbright ? Util::ordinal( ShaderStageVariant::FULLBRIGHT ) : 0 ); if ( pStage->variantOffsets[variant] == -1 ) { pStage->variantOffsets[variant] = pStage->variantOffset; @@ -1353,9 +1352,9 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, lightMode_t lightMode; deluxeMode_t deluxeMode; SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); - pStage->mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP && drawSurf->bspSurface && pStage->shaderBinder == BindShaderGeneric3D; - pStage->vertexLit = lightMode == lightMode_t::VERTEX && pStage->shaderBinder == BindShaderLightMapping; - pStage->fullbright = lightMode == lightMode_t::FULLBRIGHT && pStage->shaderBinder == BindShaderLightMapping; + const bool mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP && drawSurf->bspSurface && pStage->shaderBinder == BindShaderGeneric3D; + const bool vertexLit = lightMode == lightMode_t::VERTEX && pStage->shaderBinder == BindShaderLightMapping; + const bool fullbright = lightMode == lightMode_t::FULLBRIGHT && pStage->shaderBinder == BindShaderLightMapping; ComputeDynamics( pStage ); @@ -1424,7 +1423,7 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, pStage->useMaterialSystem = true; pStage->initialized = true; - AddStage( drawSurf, pStage, stage ); + AddStage( drawSurf, pStage, stage, mayUseVertexOverbright, vertexLit, fullbright ); AddStageTextures( drawSurf, stage, &materials[previousMaterialID] ); if ( std::find( materials[previousMaterialID].drawSurfs.begin(), materials[previousMaterialID].drawSurfs.end(), drawSurf ) diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 30d9721927..1265541fb5 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -333,7 +333,8 @@ class MaterialSystem { void GenerateDepthImages( const int width, const int height, imageParams_t imageParms ); void AddStageTextures( drawSurf_t* drawSurf, const uint32_t stage, Material* material ); - void AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage ); + void AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage, + const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright ); void ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, uint32_t& previousMaterialID ); void GenerateWorldMaterials(); @@ -407,16 +408,16 @@ extern GLSSBO debugSSBO; // Global extern MaterialSystem materialSystem; -void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t* ); -void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t* ); -void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage ); -void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage ); -void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage); -void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage ); -void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage); -void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage); -void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage); -void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage ); +void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t*, bool, bool, bool ); +void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t*, bool, bool, bool ); +void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage, bool mayUseVertexOverbright, bool, bool ); +void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage, bool, bool vertexLit, bool fullbright ); +void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); +void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); +void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); +void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); +void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); +void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); // void UpdateSurf( uint32) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index c55836ed32..3e66feb2f4 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1102,7 +1102,7 @@ enum class shaderProfilerRenderSubGroupsMode { struct drawSurf_t; using stageRenderer_t = void(*)(shaderStage_t *); - using surfaceDataUpdater_t = void(*)(uint32_t*, shaderStage_t*); + using surfaceDataUpdater_t = void(*)(uint32_t*, shaderStage_t*, bool, bool, bool); using stageShaderBinder_t = void(*)(Material*); using stageMaterialProcessor_t = void(*)(Material*, shaderStage_t*, drawSurf_t*); @@ -1225,11 +1225,6 @@ enum class shaderProfilerRenderSubGroupsMode { int variantOffsets[Util::ordinal( ShaderStageVariant::ALL )]; uint32_t variantOffset = 0; - uint32_t currentOffset = 0; - - bool mayUseVertexOverbright = false; - bool vertexLit = false; - bool fullbright = false; }; enum cullType_t : int From 64315170247209d719b7fa028ef4f085a2bfc04b Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 27 Jan 2025 04:37:33 +0300 Subject: [PATCH 16/16] Change ShaderStageVariant to an enum --- src/engine/renderer/Material.cpp | 14 +++++++------- src/engine/renderer/tr_local.h | 4 ++-- src/engine/renderer/tr_shader.cpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index e7d6f1de19..c9ca0af2db 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -486,11 +486,11 @@ void MaterialSystem::GenerateMaterialsBuffer( std::vector& stage /* Stage variants are essentially copies of the same stage with slightly different values that normally come from a drawSurf_t */ uint32_t variants = 0; - for ( int i = 0; i < Util::ordinal( ShaderStageVariant::ALL ) && variants < pStage->variantOffset; i++ ) { + for ( int i = 0; i < ShaderStageVariant::ALL && variants < pStage->variantOffset; i++ ) { if ( pStage->variantOffsets[i] != -1 ) { - const bool mayUseVertexOverbright = i & Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ); - const bool vertexLit = i & Util::ordinal( ShaderStageVariant::VERTEX_LIT ); - const bool fullbright = i & Util::ordinal( ShaderStageVariant::FULLBRIGHT ); + const bool mayUseVertexOverbright = i & ShaderStageVariant::VERTEX_OVERBRIGHT; + const bool vertexLit = i & ShaderStageVariant::VERTEX_LIT; + const bool fullbright = i & ShaderStageVariant::FULLBRIGHT; const uint32_t variantOffset = pStage->variantOffsets[i] * pStage->paddedSize; pStage->bufferOffset += variantOffset; @@ -1244,9 +1244,9 @@ void ProcessMaterialFog( Material* material, shaderStage_t* pStage, drawSurf_t* void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage, const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright ) { - const int variant = ( mayUseVertexOverbright ? Util::ordinal( ShaderStageVariant::VERTEX_OVERBRIGHT ) : 0 ) - | ( vertexLit ? Util::ordinal( ShaderStageVariant::VERTEX_LIT ) : 0 ) - | ( fullbright ? Util::ordinal( ShaderStageVariant::FULLBRIGHT ) : 0 ); + const int variant = ( mayUseVertexOverbright ? ShaderStageVariant::VERTEX_OVERBRIGHT : 0 ) + | ( vertexLit ? ShaderStageVariant::VERTEX_LIT : 0 ) + | ( fullbright ? ShaderStageVariant::FULLBRIGHT : 0 ); if ( pStage->variantOffsets[variant] == -1 ) { pStage->variantOffsets[variant] = pStage->variantOffset; diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 3e66feb2f4..201f142a0a 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1106,7 +1106,7 @@ enum class shaderProfilerRenderSubGroupsMode { using stageShaderBinder_t = void(*)(Material*); using stageMaterialProcessor_t = void(*)(Material*, shaderStage_t*, drawSurf_t*); - enum class ShaderStageVariant { + enum ShaderStageVariant { VERTEX_OVERBRIGHT = 1, VERTEX_LIT = BIT( 1 ), FULLBRIGHT = BIT( 2 ), @@ -1223,7 +1223,7 @@ enum class shaderProfilerRenderSubGroupsMode { bool dynamic = false; bool colorDynamic = false; - int variantOffsets[Util::ordinal( ShaderStageVariant::ALL )]; + int variantOffsets[ShaderStageVariant::ALL]; uint32_t variantOffset = 0; }; diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index 81a45342c6..4f6ea8e370 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -5240,7 +5240,7 @@ static void FinishStages() break; } - memset( stage->variantOffsets, -1, Util::ordinal( ShaderStageVariant::ALL ) * sizeof( int ) ); + memset( stage->variantOffsets, -1, ShaderStageVariant::ALL * sizeof( int ) ); } GroupActiveStages();