diff --git a/src.cmake b/src.cmake index adcfc3c87f..d49ac61548 100644 --- a/src.cmake +++ b/src.cmake @@ -102,6 +102,8 @@ set(RENDERERLIST ${ENGINE_DIR}/renderer/tr_font.cpp ${ENGINE_DIR}/renderer/InternalImage.cpp ${ENGINE_DIR}/renderer/InternalImage.h + ${ENGINE_DIR}/renderer/Material.cpp + ${ENGINE_DIR}/renderer/Material.h ${ENGINE_DIR}/renderer/TextureManager.cpp ${ENGINE_DIR}/renderer/TextureManager.h ${ENGINE_DIR}/renderer/tr_image.cpp @@ -143,6 +145,7 @@ set(RENDERERLIST ) set(GLSLSOURCELIST + ${ENGINE_DIR}/renderer/glsl_source/commandQueue_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/skybox_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/ssao_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/ssao_vp.glsl diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp new file mode 100644 index 0000000000..12938a9b72 --- /dev/null +++ b/src/engine/renderer/Material.cpp @@ -0,0 +1,1592 @@ +#include "Material.h" + +#include "tr_local.h" + +GLSSBO materialsSSBO( "materials", 0 ); +GLIndirectBuffer commandBuffer( "drawCommands" ); +MaterialSystem materialSystem; + +static void ComputeDynamics( shaderStage_t* pStage ) { + // TODO: Move color and texMatrices stuff to a compute shader + switch ( pStage->rgbGen ) { + case colorGen_t::CGEN_IDENTITY: + case colorGen_t::CGEN_ONE_MINUS_VERTEX: + default: + case colorGen_t::CGEN_IDENTITY_LIGHTING: + /* Historically CGEN_IDENTITY_LIGHTING was done this way: + + tess.svars.color = Color::White * tr.identityLight; + + But tr.identityLight is always 1.0f in Dæmon engine + as the as the overbright bit implementation is fully + software. */ + case colorGen_t::CGEN_VERTEX: + case colorGen_t::CGEN_CONST: + case colorGen_t::CGEN_ENTITY: + case colorGen_t::CGEN_ONE_MINUS_ENTITY: + { + // TODO: Move this to some entity buffer once this is extended past BSP surfaces + if ( backEnd.currentEntity ) { + // + } else { + // + } + pStage->colorDynamic = false; + + break; + } + + case colorGen_t::CGEN_WAVEFORM: + case colorGen_t::CGEN_CUSTOM_RGB: + case colorGen_t::CGEN_CUSTOM_RGBs: + { + pStage->colorDynamic = true; + break; + } + } + + switch ( pStage->alphaGen ) { + default: + case alphaGen_t::AGEN_IDENTITY: + case alphaGen_t::AGEN_ONE_MINUS_VERTEX: + case alphaGen_t::AGEN_VERTEX: + case alphaGen_t::AGEN_CONST: { + case alphaGen_t::AGEN_ENTITY: + case alphaGen_t::AGEN_ONE_MINUS_ENTITY: + // TODO: Move this to some entity buffer once this is extended past BSP surfaces + if ( backEnd.currentEntity ) { + // + } else { + // + } + pStage->colorDynamic = false; + break; + } + + case alphaGen_t::AGEN_WAVEFORM: + case alphaGen_t::AGEN_CUSTOM: + { + pStage->colorDynamic = true; + break; + } + } + + for ( textureBundle_t& bundle : pStage->bundle ) { + for ( int j = 0; j < bundle.numTexMods; j++ ) { + switch ( bundle.texMods[j].type ) { + case texMod_t::TMOD_NONE: + 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_SCALE: + { + break; + } + + case texMod_t::TMOD_STRETCH: + { + if( bundle.texMods->wave.func != genFunc_t::GF_NONE ) { + pStage->texMatricesDynamic = true; + } + break; + } + + case texMod_t::TMOD_TRANSFORM: + { + 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[j].sExp.active || bundle.texMods[j].tExp.active ) { + pStage->texMatricesDynamic = true; + } + break; + } + + case texMod_t::TMOD_ROTATE2: + { + if( bundle.texMods[j].rExp.active ) { + 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.active; + pStage->dynamic = pStage->dynamic || pStage->alphaExp.active || pStage->alphaTestExp.active; + pStage->dynamic = pStage->dynamic || pStage->rgbExp.active || pStage->redExp.active || pStage->greenExp.active || pStage->blueExp.active; + pStage->dynamic = pStage->dynamic || pStage->deformMagnitudeExp.active; + pStage->dynamic = pStage->dynamic || pStage->depthScaleExp.active || pStage->etaExp.active || pStage->etaDeltaExp.active + || pStage->fogDensityExp.active || pStage->fresnelBiasExp.active || pStage->fresnelPowerExp.active + || pStage->fresnelScaleExp.active || pStage->normalIntensityExp.active || pStage->refractionIndexExp.active; + + pStage->dynamic = pStage->dynamic || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->texturesDynamic; +} + + +static image_t* GetLightMap() { + if ( !tr.lightmaps.currentElements ) { + return tr.whiteImage; + } else if ( tess.lightmapNum >= 0 && tess.lightmapNum < tr.lightmaps.currentElements ) { + return ( image_t* ) Com_GrowListElement( &tr.lightmaps, tess.lightmapNum ); + } else { + return tr.whiteImage; + } +} + +static image_t* GetDeluxeMap() { + if ( !tr.deluxemaps.currentElements ) { + return tr.blackImage; + } else if ( tess.lightmapNum >= 0 && tess.lightmapNum < tr.deluxemaps.currentElements ) { + return ( image_t* ) Com_GrowListElement( &tr.deluxemaps, tess.lightmapNum ); + } else { + return tr.blackImage; + } +} + +static void UpdateSurfaceDataGeneric( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const int stage ) { + shader_t* shader = drawSurf->shader; + shaderStage_t* pStage = shader->stages[stage]; + + const uint paddedOffset = drawSurf->materialsSSBOOffset[stage] * ( material.shader->GetSTD430Size() + + material.shader->GetPadding() ); + materials += paddedOffset; + + bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + if ( !updated ) { + return; + } + drawSurf->initialized[stage] = true; + + gl_genericShaderMaterial->BindProgram( material.deformIndex ); + // GL_BindProgram( material.program ); + // glUseProgram( material.program ); + + gl_genericShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + gl_genericShaderMaterial->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); + + gl_genericShaderMaterial->SetUniform_AlphaTest( pStage->stateBits ); + + // u_InverseLightFactor + // We should cancel overbrightBits if there is no light, + // and it's not using blendFunc dst_color. + bool blendFunc_dstColor = ( pStage->stateBits & GLS_SRCBLEND_BITS ) == GLS_SRCBLEND_DST_COLOR; + float inverseLightFactor = ( pStage->shaderHasNoLight && !blendFunc_dstColor ) ? tr.mapInverseLightFactor : 1.0f; + // HACK: For some reason this doesn't work properly here unless the sign is reversed + gl_genericShaderMaterial->SetUniform_InverseLightFactor( -inverseLightFactor ); + + // u_ColorModulate + colorGen_t rgbGen; + alphaGen_t alphaGen; + SetRgbaGen( pStage, &rgbGen, &alphaGen ); + gl_genericShaderMaterial->SetUniform_ColorModulate( rgbGen, alphaGen ); + + Tess_ComputeColor( pStage ); + gl_genericShaderMaterial->SetUniform_Color( tess.svars.color ); + + Tess_ComputeTexMatrices( pStage ); + gl_genericShaderMaterial->SetUniform_TextureMatrix( tess.svars.texMatrices[TB_COLORMAP] ); + + // u_DeformGen + gl_genericShaderMaterial->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); + + // bind u_ColorMap= + if ( pStage->type == stageType_t::ST_STYLELIGHTMAP ) { + gl_genericShaderMaterial->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, GetLightMap() ) + ); + } else { + /* image_t* image = GetAnimatedImage(&pStage->bundle[TB_COLORMAP], pStage->currentAnimatedImage); + if ( image != pStage->currentAnimatedImage ) { + pStage->currentAnimatedImage = image; + gl_genericShaderMaterial->SetUniform_ColorMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); + } */ + gl_genericShaderMaterial->SetUniform_ColorMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); + } + + bool needDepthMap = pStage->hasDepthFade || shader->autoSpriteMode; + if ( needDepthMap ) { + gl_genericShaderMaterial->SetUniform_DepthMapBindless( GL_BindToTMU( 1, tr.currentDepthImage ) ); + } + + bool hasDepthFade = pStage->hasDepthFade && !shader->autoSpriteMode; + if ( hasDepthFade ) { + gl_genericShaderMaterial->SetUniform_DepthScale( pStage->depthFadeValue ); + } + + gl_genericShaderMaterial->SetUniform_VertexInterpolation( false ); + + gl_genericShaderMaterial->WriteUniformsToBuffer( materials ); +} + +static void UpdateSurfaceDataLightMapping( uint32_t* materials, Material& material, drawSurf_t* drawSurf, const int stage ) { + shader_t* shader = drawSurf->shader; + shaderStage_t* pStage = shader->stages[stage]; + + const uint paddedOffset = drawSurf->materialsSSBOOffset[stage] * ( material.shader->GetSTD430Size() + + material.shader->GetPadding() ); + materials += paddedOffset; + bool updated = !drawSurf->initialized[stage] || pStage->colorDynamic || pStage->texMatricesDynamic || pStage->dynamic; + if ( !updated ) { + return; + } + drawSurf->initialized[stage] = true; + + gl_lightMappingShaderMaterial->BindProgram( material.deformIndex ); + // GL_BindProgram( material.program ); + // glUseProgram( material.program ); + + gl_lightMappingShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + + lightMode_t lightMode = lightMode_t::FULLBRIGHT; + deluxeMode_t deluxeMode = deluxeMode_t::NONE; + + /* TODO: investigate what this is. It's probably a hack to detect some + specific use case. Without knowing which use case this takes care about, + any change in the following code may break it. Or it may be a hack we + should drop if it is for a bug we don't have anymore. */ + bool hack = shader->numStages > 0 && shader->stages[0]->rgbGen == colorGen_t::CGEN_VERTEX; + + if ( ( shader->surfaceFlags & SURF_NOLIGHTMAP ) && !hack ) { + // Use fullbright on “surfaceparm nolightmap” materials. + } else if ( pStage->type == stageType_t::ST_COLLAPSE_COLORMAP ) { + /* Use fullbright for collapsed stages without lightmaps, + for example: + + { + map textures/texture_d + heightMap textures/texture_h + } + + This is doable for some complex multi-stage materials. */ + } else if ( drawSurf->bspSurface ) { + lightMode = tr.worldLight; + deluxeMode = tr.worldDeluxe; + + if ( lightMode == lightMode_t::MAP ) { + bool hasLightMap = ( drawSurf->lightmapNum() >= 0 && drawSurf->lightmapNum() <= tr.lightmaps.currentElements ); + + if ( !hasLightMap ) { + lightMode = lightMode_t::VERTEX; + deluxeMode = deluxeMode_t::NONE; + } + } + } else { + lightMode = tr.modelLight; + deluxeMode = tr.modelDeluxe; + } + + // u_Map, u_DeluxeMap + image_t* lightmap = tr.whiteImage; + image_t* deluxemap = tr.whiteImage; + + // u_ColorModulate + colorGen_t rgbGen; + alphaGen_t alphaGen; + SetRgbaGen( pStage, &rgbGen, &alphaGen ); + + switch ( lightMode ) { + case lightMode_t::VERTEX: + // Do not rewrite pStage->rgbGen. + rgbGen = colorGen_t::CGEN_VERTEX; + tess.svars.color.SetRed( 0.0f ); + tess.svars.color.SetGreen( 0.0f ); + tess.svars.color.SetBlue( 0.0f ); + break; + + case lightMode_t::GRID: + // Store lightGrid1 as lightmap, + // the GLSL code will know how to deal with it. + lightmap = tr.lightGrid1Image; + break; + + case lightMode_t::MAP: + lightmap = GetLightMap(); + + break; + + default: + break; + } + + switch ( deluxeMode ) { + case deluxeMode_t::MAP: + // Deluxe mapping for world surface. + deluxemap = GetDeluxeMap(); + break; + + case deluxeMode_t::GRID: + // Deluxe mapping emulation from grid light for game models. + // Store lightGrid2 as deluxemap, + // the GLSL code will know how to deal with it. + deluxemap = tr.lightGrid2Image; + break; + + default: + break; + } + + bool enableDeluxeMapping = ( deluxeMode == deluxeMode_t::MAP ); + bool enableGridLighting = ( lightMode == lightMode_t::GRID ); + bool enableGridDeluxeMapping = ( deluxeMode == deluxeMode_t::GRID ); + + DAEMON_ASSERT( !( enableDeluxeMapping && enableGridDeluxeMapping ) ); + + // TODO: Update this when this is extended to MDV support + gl_lightMappingShaderMaterial->SetUniform_VertexInterpolation( false ); + + if ( glConfig2.dynamicLight ) { + gl_lightMappingShaderMaterial->SetUniformBlock_Lights( tr.dlightUBO ); + + // bind u_LightTiles + if ( r_dynamicLightRenderer.Get() == Util::ordinal( dynamicLightRenderer_t::TILED ) ) { + gl_lightMappingShaderMaterial->SetUniform_LightTilesIntBindless( + GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) + ); + } + } + + // u_DeformGen + gl_lightMappingShaderMaterial->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); + + // u_InverseLightFactor + /* HACK: use sign to know if there is a light or not, and + then if it will receive overbright multiplication or not. */ + bool blendFunc_dstColor = ( pStage->stateBits & GLS_SRCBLEND_BITS ) == GLS_SRCBLEND_DST_COLOR; + bool noLight = pStage->shaderHasNoLight || lightMode == lightMode_t::FULLBRIGHT; + float inverseLightFactor = ( noLight && !blendFunc_dstColor ) ? tr.mapInverseLightFactor : -tr.mapInverseLightFactor; + // HACK: For some reason this doesn't work properly here unless the sign is reversed + gl_lightMappingShaderMaterial->SetUniform_InverseLightFactor( -inverseLightFactor ); + + // u_ColorModulate + gl_lightMappingShaderMaterial->SetUniform_ColorModulate( rgbGen, alphaGen ); + + // u_Color + Tess_ComputeColor( pStage ); + gl_lightMappingShaderMaterial->SetUniform_Color( tess.svars.color ); + + // u_AlphaTest + gl_lightMappingShaderMaterial->SetUniform_AlphaTest( pStage->stateBits ); + + // bind u_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 + if ( pStage->enableNormalMapping ) { + vec3_t normalScale; + SetNormalScale( pStage, normalScale ); + + 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 ); + + gl_lightMappingShaderMaterial->SetUniform_SpecularExponent( specExpMin, specExpMax ); + } + + // specular reflection + if ( tr.cubeHashTable != nullptr ) { + cubemapProbe_t* cubeProbeNearest; + cubemapProbe_t* cubeProbeSecondNearest; + + image_t* cubeMap0 = nullptr; + image_t* cubeMap1 = nullptr; + + float interpolation = 0.0; + + bool isWorldEntity = backEnd.currentEntity == &tr.worldEntity; + + if ( backEnd.currentEntity && !isWorldEntity ) { + R_FindTwoNearestCubeMaps( backEnd.currentEntity->e.origin, &cubeProbeNearest, &cubeProbeSecondNearest ); + } else { + // FIXME position + R_FindTwoNearestCubeMaps( backEnd.viewParms.orientation.origin, &cubeProbeNearest, &cubeProbeSecondNearest ); + } + + if ( cubeProbeNearest == nullptr && cubeProbeSecondNearest == nullptr ) { + GLimp_LogComment( "cubeProbeNearest && cubeProbeSecondNearest == NULL\n" ); + + cubeMap0 = tr.whiteCubeImage; + cubeMap1 = tr.whiteCubeImage; + } else if ( cubeProbeNearest == nullptr ) { + GLimp_LogComment( "cubeProbeNearest == NULL\n" ); + + cubeMap0 = cubeProbeSecondNearest->cubemap; + } else if ( cubeProbeSecondNearest == nullptr ) { + GLimp_LogComment( "cubeProbeSecondNearest == NULL\n" ); + + cubeMap0 = cubeProbeNearest->cubemap; + } else { + float cubeProbeNearestDistance, cubeProbeSecondNearestDistance; + + if ( backEnd.currentEntity && !isWorldEntity ) { + cubeProbeNearestDistance = Distance( backEnd.currentEntity->e.origin, cubeProbeNearest->origin ); + cubeProbeSecondNearestDistance = Distance( backEnd.currentEntity->e.origin, cubeProbeSecondNearest->origin ); + } else { + // FIXME position + cubeProbeNearestDistance = Distance( backEnd.viewParms.orientation.origin, cubeProbeNearest->origin ); + cubeProbeSecondNearestDistance = Distance( backEnd.viewParms.orientation.origin, cubeProbeSecondNearest->origin ); + } + + interpolation = cubeProbeNearestDistance / ( cubeProbeNearestDistance + cubeProbeSecondNearestDistance ); + + if ( r_logFile->integer ) { + GLimp_LogComment( va( "cubeProbeNearestDistance = %f, cubeProbeSecondNearestDistance = %f, interpolation = %f\n", + cubeProbeNearestDistance, cubeProbeSecondNearestDistance, interpolation ) ); + } + + cubeMap0 = cubeProbeNearest->cubemap; + cubeMap1 = cubeProbeSecondNearest->cubemap; + } + + /* TODO: Check why it is required to test for this, why + cubeProbeNearest->cubemap and cubeProbeSecondNearest->cubemap + can be nullptr while cubeProbeNearest and cubeProbeSecondNearest + are not. Maybe this is only required while cubemaps are building. */ + if ( cubeMap0 == nullptr ) { + cubeMap0 = tr.whiteCubeImage; + } + + if ( cubeMap1 == nullptr ) { + cubeMap1 = tr.whiteCubeImage; + } + + // bind u_EnvironmentMap0 + gl_lightMappingShaderMaterial->SetUniform_EnvironmentMap0Bindless( + GL_BindToTMU( BIND_ENVIRONMENTMAP0, cubeMap0 ) + ); + + // bind u_EnvironmentMap1 + gl_lightMappingShaderMaterial->SetUniform_EnvironmentMap1Bindless( + GL_BindToTMU( BIND_ENVIRONMENTMAP1, cubeMap1 ) + ); + + // bind u_EnvironmentInterpolation + gl_lightMappingShaderMaterial->SetUniform_EnvironmentInterpolation( interpolation ); + + updated = true; + } + + // bind u_LightMap + if ( !enableGridLighting ) { + gl_lightMappingShaderMaterial->SetUniform_LightMapBindless( + GL_BindToTMU( BIND_LIGHTMAP, lightmap ) + ); + } else { + gl_lightMappingShaderMaterial->SetUniform_LightGrid1Bindless( GL_BindToTMU( BIND_LIGHTMAP, lightmap ) ); + } + + // bind u_DeluxeMap + if ( !enableGridDeluxeMapping ) { + gl_lightMappingShaderMaterial->SetUniform_DeluxeMapBindless( + GL_BindToTMU( BIND_DELUXEMAP, deluxemap ) + ); + } else { + gl_lightMappingShaderMaterial->SetUniform_LightGrid2Bindless( 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 ); +} + +static bool UpdateSurfaceDataReflection( uint32_t* materials, drawSurf_t* drawSurf, const uint stage ) { + shader_t* shader = drawSurf->shader; + shaderStage_t* pStage = shader->stages[stage]; + + materials += drawSurf->materialsSSBOOffset[stage]; + bool updated = !drawSurf->initialized[stage]; + + if ( !drawSurf->initialized[stage] ) { + gl_reflectionShader->SetUniform_VertexInterpolation( false ); + + // bind u_NormalMap + gl_reflectionShader->SetUniform_NormalMapBindless( + GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) + ); + } + + // bind u_ColorMap + if ( backEnd.currentEntity && ( backEnd.currentEntity != &tr.worldEntity ) ) { + GL_BindNearestCubeMap( gl_reflectionShader->GetUniformLocation_ColorMap(), backEnd.currentEntity->e.origin ); + } else { + GL_BindNearestCubeMap( gl_reflectionShader->GetUniformLocation_ColorMap(), backEnd.viewParms.orientation.origin ); + } + + if ( pStage->enableNormalMapping ) { + vec3_t normalScale; + SetNormalScale( pStage, normalScale ); + + gl_reflectionShader->SetUniform_NormalScale( normalScale ); + } + + // bind u_HeightMap 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_reflectionShader->SetUniform_ReliefDepthScale( depthScale ); + gl_reflectionShader->SetUniform_ReliefOffsetBias( shader->reliefOffsetBias ); + + // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap + if ( !pStage->hasHeightMapInNormalMap ) { + gl_reflectionShader->SetUniform_HeightMapBindless( + GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) + ); + } + } + + return updated; +} + +static bool UpdateSurfaceDataSkybox( uint32_t* materials, drawSurf_t* drawSurf, const uint stage ) { + return true; +} + +static bool UpdateSurfaceDataScreen( uint32_t* materials, drawSurf_t* drawSurf, const uint stage ) { + // bind u_CurrentMap + gl_screenShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &drawSurf->shader->stages[stage]->bundle[TB_COLORMAP] ) ); + return true; +} + +static bool UpdateSurfaceDataHeatHaze( uint32_t* materials, drawSurf_t* drawSurf, const uint stage ) { + shader_t* shader = drawSurf->shader; + shaderStage_t* pStage = shader->stages[stage]; + + if ( !drawSurf->initialized[stage] ) { + // bind u_NormalMap + gl_heatHazeShader->SetUniform_NormalMapBindless( + GL_BindToTMU( 0, pStage->bundle[TB_NORMALMAP].image[0] ) + ); + } + + float deformMagnitude = RB_EvalExpression( &pStage->deformMagnitudeExp, 1.0 ); + gl_heatHazeShader->SetUniform_DeformMagnitude( deformMagnitude ); + + if ( pStage->enableNormalMapping ) { + vec3_t normalScale; + SetNormalScale( pStage, normalScale ); + + // bind u_NormalScale + gl_heatHazeShader->SetUniform_NormalScale( normalScale ); + } + + // bind u_CurrentMap + gl_heatHazeShader->SetUniform_CurrentMapBindless( + GL_BindToTMU( 1, tr.currentRenderImage[backEnd.currentMainFBO] ) + ); + + return true; +} + +static bool UpdateSurfaceDataLiquid( uint32_t* materials, drawSurf_t* drawSurf, const uint stage ) { + shader_t* shader = drawSurf->shader; + shaderStage_t* pStage = shader->stages[stage]; + + float fogDensity = RB_EvalExpression( &pStage->fogDensityExp, 0.001 ); + vec4_t fogColor; + // VectorCopy( tess.svars.color.ToArray(), fogColor ); + + gl_liquidShader->SetUniform_RefractionIndex( RB_EvalExpression( &pStage->refractionIndexExp, 1.0 ) ); + gl_liquidShader->SetUniform_FresnelPower( RB_EvalExpression( &pStage->fresnelPowerExp, 2.0 ) ); + gl_liquidShader->SetUniform_FresnelScale( RB_EvalExpression( &pStage->fresnelScaleExp, 1.0 ) ); + gl_liquidShader->SetUniform_FresnelBias( RB_EvalExpression( &pStage->fresnelBiasExp, 0.05 ) ); + gl_liquidShader->SetUniform_FogDensity( fogDensity ); + gl_liquidShader->SetUniform_FogColor( fogColor ); + + gl_liquidShader->SetUniform_UnprojectMatrix( backEnd.viewParms.unprojectionMatrix ); + gl_liquidShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + gl_liquidShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); + + // NOTE: specular component is computed by shader. + // FIXME: physical mapping is not implemented. + if ( pStage->enableSpecularMapping ) { + float specMin = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); + float specMax = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); + gl_liquidShader->SetUniform_SpecularExponent( specMin, specMax ); + } + + // bind u_CurrentMap + gl_liquidShader->SetUniform_CurrentMapBindless( GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) ); + + // bind u_PortalMap + gl_liquidShader->SetUniform_PortalMapBindless( GL_BindToTMU( 1, tr.portalRenderImage ) ); + + // depth texture + gl_liquidShader->SetUniform_DepthMapBindless( GL_BindToTMU( 2, tr.currentDepthImage ) ); + + // bind u_HeightMap u_depthScale u_reliefOffsetBias + if ( pStage->enableReliefMapping ) { + float depthScale; + float reliefDepthScale; + + depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); + reliefDepthScale = tess.surfaceShader->reliefDepthScale; + depthScale *= reliefDepthScale == 0 ? 1 : reliefDepthScale; + gl_liquidShader->SetUniform_ReliefDepthScale( depthScale ); + gl_liquidShader->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); + + // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap + if ( !pStage->hasHeightMapInNormalMap ) { + gl_liquidShader->SetUniform_HeightMapBindless( GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) ); + } + } + + // bind u_NormalMap + gl_liquidShader->SetUniform_NormalMapBindless( GL_BindToTMU( 3, pStage->bundle[TB_NORMALMAP].image[0] ) ); + + // bind u_NormalScale + if ( pStage->enableNormalMapping ) { + vec3_t normalScale; + // FIXME: NormalIntensity default was 0.5 + SetNormalScale( pStage, normalScale ); + + gl_liquidShader->SetUniform_NormalScale( normalScale ); + } + + return true; +} + +/* +* Buffer layout: +* // Static surfaces data: +* // Material0 +* // Surface/stage0_0: +* uniform0_0 +* uniform0_1 +* .. +* uniform0_x +* optional_struct_padding +* // Surface/stage0_1: +* .. +* // Surface/stage0_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 +*/ +// Buffer is separated into static and dynamic parts so we can just update the whole dynamic range at once +void MaterialSystem::GenerateMaterialsBuffer() { + uint std430Size = 0; + uint 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 uint paddedSize = material.shader->GetSTD430Size() + material.shader->GetPadding(); + const uint padding = ( offset % paddedSize == 0 ) ? 0 : paddedSize - ( offset % paddedSize ); + + offset += padding; + // material.materialsSSBOOffset = offset; + material.staticMaterialsSSBOOffset = offset; + // offset += paddedSize * material.totalDrawSurfCount; + offset += paddedSize * material.totalStaticDrawSurfCount; + } + } + + dynamicDrawSurfsOffset = offset; + + // 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 uint paddedSize = material.shader->GetSTD430Size() + material.shader->GetPadding(); + const uint padding = ( offset % paddedSize == 0 ) ? 0 : paddedSize - ( offset % paddedSize ); + + offset += padding; + // material.materialsSSBOOffset = offset; + material.dynamicMaterialsSSBOOffset = offset; + // offset += paddedSize * material.totalDrawSurfCount; + offset += paddedSize * material.totalDynamicDrawSurfCount; + } + } + + dynamicDrawSurfsSize = offset - dynamicDrawSurfsOffset; + + // 4 bytes per component + glBufferData( GL_SHADER_STORAGE_BUFFER, offset * sizeof( uint32_t ), nullptr, GL_DYNAMIC_DRAW ); + uint32_t* materialsDataInitial = materialsSSBO.MapBufferRange( offset ); + uint32_t* materialsData = materialsDataInitial; + memset( materialsData, 0, 4 * offset ); + + for ( uint materialPackID = 0; materialPackID < 3; materialPackID++ ) { + for ( Material& material : materialPacks[materialPackID].materials ) { + + for ( drawSurf_t* drawSurf : material.drawSurfs ) { + for ( int stage = 0; stage < drawSurf->shader->numStages; stage++ ) { + shaderStage_t* pStage = drawSurf->shader->stages[stage]; + + if ( drawSurf->materialIDs[stage] != material.id || drawSurf->materialPackIDs[stage] != materialPackID ) { + continue; + } + + /* pStage->materialsSSBOOffset = material.materialsSSBOOffset + material.currentDrawSurfCount * + ( material.shader->GetSTD430Size() + material.shader->GetPadding() ); + material.currentDrawSurfCount++; */ + + uint SSBOOffset = 0; + uint 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->GetSTD430Size() + material.shader->GetPadding() ) ) / + ( material.shader->GetSTD430Size() + material.shader->GetPadding() ); + // material.currentDrawSurfCount++; + + switch ( pStage->type ) { + case stageType_t::ST_COLORMAP: + // generic2D + UpdateSurfaceDataGeneric( materialsData, material, drawSurf, stage ); + break; + case stageType_t::ST_STYLELIGHTMAP: + case stageType_t::ST_STYLECOLORMAP: + UpdateSurfaceDataGeneric( materialsData, material, drawSurf, stage ); + break; + case stageType_t::ST_LIGHTMAP: + case stageType_t::ST_DIFFUSEMAP: + case stageType_t::ST_COLLAPSE_COLORMAP: + case stageType_t::ST_COLLAPSE_DIFFUSEMAP: + UpdateSurfaceDataLightMapping( materialsData, material, drawSurf, stage ); + break; + case stageType_t::ST_REFLECTIONMAP: + case stageType_t::ST_COLLAPSE_REFLECTIONMAP: + UpdateSurfaceDataReflection( materialsData, drawSurf, stage ); + break; + case stageType_t::ST_REFRACTIONMAP: + case stageType_t::ST_DISPERSIONMAP: + // Not implemented yet + break; + case stageType_t::ST_SKYBOXMAP: + UpdateSurfaceDataSkybox( materialsData, drawSurf, stage ); + break; + case stageType_t::ST_SCREENMAP: + UpdateSurfaceDataScreen( materialsData, drawSurf, stage ); + break; + case stageType_t::ST_PORTALMAP: + // This is supposedly used for alphagen portal and portal surfaces should never get here + ASSERT_UNREACHABLE(); + break; + case stageType_t::ST_HEATHAZEMAP: + UpdateSurfaceDataHeatHaze( materialsData, drawSurf, stage ); + break; + case stageType_t::ST_LIQUIDMAP: + UpdateSurfaceDataLiquid( materialsData, drawSurf, stage ); + break; + + default: + break; + } + } + } + } + } + + materialsSSBO.UnmapBuffer(); +} + +void MaterialSystem::GenerateWorldCommandBuffer() { + uint count = 0; + for ( const MaterialPack& pack : materialPacks ) { + for ( const Material& material : pack.materials ) { + count += material.drawCommands.size(); + } + } + + if ( count == 0 ) { + return; + } + + Log::Debug( "CmdBuffer size: %u", count ); + + commandBuffer.BindBuffer(); + glBufferData( GL_DRAW_INDIRECT_BUFFER, count * sizeof( GLIndirectBuffer::GLIndirectCommand ), nullptr, GL_STATIC_DRAW ); + + GLIndirectBuffer::GLIndirectCommand* commandsInitial = commandBuffer.MapBufferRange( count ); + GLIndirectBuffer::GLIndirectCommand* commands = commandsInitial; + uint offset = 0; + for ( MaterialPack& pack : materialPacks ) { + for ( Material& material : pack.materials ) { + uint drawCmdCount = 0; + material.staticCommandOffset = offset; + + for ( const DrawCommand& drawCmd : material.drawCommands ) { + memcpy( commands, &drawCmd.cmd, sizeof( GLIndirectBuffer::GLIndirectCommand ) ); + commands++; + offset++; + } + } + } + + commandBuffer.UnmapBuffer(); + GL_CheckErrors(); +} + +static void ProcessMaterialGeneric( Material* material, shaderStage_t* pStage, shader_t* shader ) { + material->shader = gl_genericShaderMaterial; + + // gl_genericShaderMaterial->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && false ); + gl_genericShaderMaterial->SetVertexAnimation( false ); + + gl_genericShaderMaterial->SetTCGenEnvironment( pStage->tcGen_Environment ); + gl_genericShaderMaterial->SetTCGenLightmap( pStage->tcGen_Lightmap ); + + bool hasDepthFade = pStage->hasDepthFade && !shader->autoSpriteMode; + gl_genericShaderMaterial->SetDepthFade( hasDepthFade ); + gl_genericShaderMaterial->SetVertexSprite( tess.vboVertexSprite ); + + uint32_t alphaTestBits = pStage->stateBits & GLS_ATEST_BITS; + gl_genericShaderMaterial->SetAlphaTesting( alphaTestBits != 0 ); + + material->program = gl_genericShaderMaterial->GetProgram( pStage->deformIndex ); +} + +static void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ) { + material->shader = gl_lightMappingShaderMaterial; + + // gl_lightMappingShaderMaterial->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && false ); + + gl_lightMappingShaderMaterial->SetVertexAnimation( false ); + gl_lightMappingShaderMaterial->SetBspSurface( drawSurf->bspSurface ); + + + lightMode_t lightMode = lightMode_t::FULLBRIGHT; + deluxeMode_t deluxeMode = deluxeMode_t::NONE; + + bool hack = tess.numSurfaceStages > 0 && tess.surfaceStages[0]->rgbGen == colorGen_t::CGEN_VERTEX; + if ( ( tess.surfaceShader->surfaceFlags & SURF_NOLIGHTMAP ) && !hack ) { + // Use fullbright on “surfaceparm nolightmap” materials. + } else if ( pStage->type == stageType_t::ST_COLLAPSE_COLORMAP ) { + /* Use fullbright for collapsed stages without lightmaps, + for example: + { + map textures/texture_d + heightMap textures/texture_h + } + + This is doable for some complex multi-stage materials. */ + } else if ( drawSurf->bspSurface ) { + lightMode = tr.worldLight; + deluxeMode = tr.worldDeluxe; + + if ( lightMode == lightMode_t::MAP ) { + bool hasLightMap = ( drawSurf->lightmapNum() >= 0 ); + + if ( !hasLightMap ) { + lightMode = lightMode_t::VERTEX; + deluxeMode = deluxeMode_t::NONE; + } + } + } else { + lightMode = tr.modelLight; + deluxeMode = tr.modelDeluxe; + } + + /* + // u_Map, u_DeluxeMap + image_t* lightmap = tr.whiteImage; + image_t* deluxemap = tr.whiteImage; + + uint32_t stateBits = pStage->stateBits; + + switch ( lightMode ) { + case lightMode_t::VERTEX: + // Do not rewrite pStage->rgbGen. + colorGen = colorGen_t::CGEN_VERTEX; + tess.svars.color.SetRed( 0.0f ); + tess.svars.color.SetGreen( 0.0f ); + tess.svars.color.SetBlue( 0.0f ); + break; + + case lightMode_t::GRID: + // Store lightGrid1 as lightmap, + // the GLSL code will know how to deal with it. + lightmap = tr.lightGrid1Image; + break; + + case lightMode_t::MAP: + lightmap = GetLightMap(); + + if ( r_showLightMaps->integer ) { + stateBits &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_ATEST_BITS ); + } + break; + + default: + break; + } + + switch ( deluxeMode ) { + case deluxeMode_t::MAP: + // Deluxe mapping for world surface. + deluxemap = GetDeluxeMap(); + break; + + case deluxeMode_t::GRID: + // Deluxe mapping emulation from grid light for game models. + // Store lightGrid2 as deluxemap, + // the GLSL code will know how to deal with it. + deluxemap = tr.lightGrid2Image; + break; + + default: + break; + } */ + + bool enableDeluxeMapping = ( deluxeMode == deluxeMode_t::MAP ); + bool enableGridLighting = ( lightMode == lightMode_t::GRID ); + bool enableGridDeluxeMapping = ( deluxeMode == deluxeMode_t::GRID ); + + gl_lightMappingShaderMaterial->SetDeluxeMapping( enableDeluxeMapping ); + + gl_lightMappingShaderMaterial->SetGridLighting( enableGridLighting ); + + gl_lightMappingShaderMaterial->SetGridDeluxeMapping( enableGridDeluxeMapping ); + + gl_lightMappingShaderMaterial->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); + + gl_lightMappingShaderMaterial->SetReliefMapping( pStage->enableReliefMapping ); + + gl_lightMappingShaderMaterial->SetReflectiveSpecular( pStage->enableNormalMapping && tr.cubeHashTable != nullptr ); + + gl_lightMappingShaderMaterial->SetPhysicalShading( pStage->enablePhysicalMapping ); + + material->program = gl_lightMappingShaderMaterial->GetProgram( pStage->deformIndex ); +} + +static void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, shader_t* shader ) { + material->shader = gl_reflectionShader; + + gl_reflectionShader->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); + + gl_reflectionShader->SetReliefMapping( pStage->enableReliefMapping ); + + gl_reflectionShader->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && false ); + gl_reflectionShader->SetVertexAnimation( glState.vertexAttribsInterpolation > 0 && false ); + + material->program = gl_reflectionShader->GetProgram( pStage->deformIndex ); +} + +static void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, shader_t* shader ) { + material->shader = gl_skyboxShader; + + material->program = gl_skyboxShader->GetProgram( 0 ); +} + +static void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, shader_t* shader ) { + material->shader = gl_screenShader; + + material->program = gl_screenShader->GetProgram( pStage->deformIndex ); +} + +static void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, shader_t* shader ) { + material->shader = gl_heatHazeShader; + + gl_heatHazeShader->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && false ); + gl_heatHazeShader->SetVertexAnimation( glState.vertexAttribsInterpolation > 0 && false ); + if ( shader->autoSpriteMode ) { + gl_heatHazeShader->SetVertexSprite( true ); + } else { + gl_heatHazeShader->SetVertexSprite( false ); + } + + material->program = gl_heatHazeShader->GetProgram( pStage->deformIndex ); +} +static void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, shader_t* shader ) { + material->shader = gl_liquidShader; + + gl_liquidShader->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); + + gl_liquidShader->SetReliefMapping( pStage->enableReliefMapping ); + + material->program = gl_liquidShader->GetProgram( pStage->deformIndex ); +} + +void MaterialSystem::GenerateMaterials() { + const int current_r_nocull = r_nocull->integer; + const int current_r_drawworld = r_drawworld->integer; + r_nocull->integer = 1; + r_drawworld->integer = 1; + tr.generatingMaterials = true; + generatingWorldCommandBuffer = true; + + R_AddWorldSurfaces(); + Log::Notice( "World bounds: min: %f %f %f max: %f %f %f", tr.viewParms.visBounds[0][0], tr.viewParms.visBounds[0][1], + tr.viewParms.visBounds[0][2], tr.viewParms.visBounds[1][0], tr.viewParms.visBounds[1][1], tr.viewParms.visBounds[1][2] ); + VectorCopy( tr.viewParms.visBounds[0], worldViewBounds[0] ); + VectorCopy( tr.viewParms.visBounds[1], worldViewBounds[1] ); + + backEnd.currentEntity = &tr.worldEntity; + + drawSurf_t* drawSurf; + + GLuint materialsSize = 0; + uint id = 0; + uint previousMaterialID = 0; + uint packIDs[3] = { 0, 0, 0 }; + + for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) { + drawSurf = &tr.refdef.drawSurfs[i]; + if ( drawSurf->entity != &tr.worldEntity ) { + continue; + } + } + + for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) { + drawSurf = &tr.refdef.drawSurfs[i]; + if ( drawSurf->entity != &tr.worldEntity ) { + continue; + } + shader_t* shader = drawSurf->shader; + if ( !shader ) { + continue; + } + shader = shader->remappedShader ? shader->remappedShader : shader; + if ( shader->isSky || shader->isPortal ) { + continue; + } + allDrawSurfs.emplace_back( drawSurf ); + + bool hasDynamicStages = false; + // Log::Warn( "shader: %s", shader->name ); + for ( int stage = 0; stage < shader->numStages; stage++ ) { + shaderStage_t* pStage = shader->stages[stage]; + + /* Log::Warn("%i: active: %s, alphaTest: %s, translucent: %s, sort: %i, depth write: %s, has depth shader: %s, depth2: %s," + "state: depthtestdisable: %s, src blend: %s, dst blend: %s", + stage, pStage->active, shader->alphaTest, shader->translucent, + shader->sort, shader->sort == 2, shader->depthShader != nullptr, + pStage->stateBits == ( pStage->stateBits & GLS_DEPTHMASK_TRUE ), pStage->stateBits == ( pStage->stateBits & GLS_DEPTHTEST_DISABLE ), + pStage->stateBits == ( pStage->stateBits & GLS_SRCBLEND_BITS ), pStage->stateBits == ( pStage->stateBits & GLS_DSTBLEND_BITS ) ); */ + + Material material; + + uint materialPack = 0; + if ( shader->sort == Util::ordinal( shaderSort_t::SS_DEPTH ) ) { + materialPack = 0; + } else if ( shader->sort >= Util::ordinal( shaderSort_t::SS_ENVIRONMENT_FOG ) + && shader->sort <= Util::ordinal( shaderSort_t::SS_OPAQUE ) ) { + materialPack = 1; + } else { + materialPack = 2; + } + id = packIDs[materialPack]; + + // Assume that in surfaces with multiple stages each consecutive stage must be drawn after the previous stage, + // except if an opaque stage follows a transparent stage etc. + if ( stage > 0 ) { + material.useSync = true; + material.syncMaterial = previousMaterialID; + } + + // uint32_t stateBits = pStage->stateBits & GLS_DEPTHFUNC_BITS & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) & + // GLS_COLORMASK_BITS & GLS_DEPTHMASK_TRUE & GLS_POLYMODE_LINE & GLS_DEPTHTEST_DISABLE; + material.stateBits = pStage->stateBits; + material.stageType = pStage->type; + material.cullType = shader->cullType; + + rb_surfaceTable[Util::ordinal( *( drawSurf->surface ) )]( drawSurf->surface ); + material.vbo = glState.currentVBO; + material.ibo = glState.currentIBO; + + ComputeDynamics( pStage ); + + switch ( pStage->type ) { + case stageType_t::ST_COLORMAP: + // generic2D also uses this, but it's for ui only, so skip that for now + ProcessMaterialGeneric( &material, pStage, drawSurf->shader ); + break; + case stageType_t::ST_STYLELIGHTMAP: + case stageType_t::ST_STYLECOLORMAP: + ProcessMaterialGeneric( &material, pStage, drawSurf->shader ); + break; + case stageType_t::ST_LIGHTMAP: + case stageType_t::ST_DIFFUSEMAP: + case stageType_t::ST_COLLAPSE_COLORMAP: + case stageType_t::ST_COLLAPSE_DIFFUSEMAP: + ProcessMaterialLightMapping( &material, pStage, drawSurf ); + break; + case stageType_t::ST_REFLECTIONMAP: + case stageType_t::ST_COLLAPSE_REFLECTIONMAP: + ProcessMaterialReflection( &material, pStage, drawSurf->shader ); + break; + case stageType_t::ST_REFRACTIONMAP: + case stageType_t::ST_DISPERSIONMAP: + // Not implemented yet + break; + case stageType_t::ST_SKYBOXMAP: + ProcessMaterialSkybox( &material, pStage, drawSurf->shader ); + break; + case stageType_t::ST_SCREENMAP: + ProcessMaterialScreen( &material, pStage, drawSurf->shader ); + break; + case stageType_t::ST_PORTALMAP: + // This is supposedly used for alphagen portal and portal surfaces should never get here + ASSERT_UNREACHABLE(); + break; + case stageType_t::ST_HEATHAZEMAP: + ProcessMaterialHeatHaze( &material, pStage, drawSurf->shader ); + break; + case stageType_t::ST_LIQUIDMAP: + ProcessMaterialLiquid( &material, pStage, drawSurf->shader ); + break; + + default: + break; + } + + std::vector& materials = materialPacks[materialPack].materials; + std::vector::iterator currentSearchIt = materials.begin(); + std::vector::iterator materialIt; + // Look for this material in the ones we already have + while( true ) { + materialIt = std::find( currentSearchIt, materials.end(), material ); + if ( materialIt == materials.end() ) { + break; + } + if ( material.useSync && materialIt->id < material.syncMaterial ) { + currentSearchIt = materialIt + 1; + } else { + break; + } + } + + // Add it at the back if not found + if ( materialIt == materials.end() ) { + material.id = id; + previousMaterialID = id; + materials.emplace_back( material ); + id++; + } else { + previousMaterialID = materialIt->id; + } + + pStage->useMaterialSystem = true; + // pStage->materialPackID = materialPack; + // pStage->materialID = previousMaterialID; + materials[previousMaterialID].totalDrawSurfCount++; + if ( pStage->dynamic ) { + materials[previousMaterialID].totalDynamicDrawSurfCount++; + hasDynamicStages = true; + } else { + materials[previousMaterialID].totalStaticDrawSurfCount++; + } + 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; + + packIDs[materialPack] = id; + } + + 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 ); + } + } + + GenerateMaterialsBuffer(); + tr.generatingMaterials = false; + + uint totalCount = 0; + for ( MaterialPack& pack : materialPacks ) { + totalCount += pack.materials.size(); + } + Log::Notice( "Generated %u materials from %u surfaces", totalCount, tr.refdef.numDrawSurfs ); + 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 ); + } + } + + r_nocull->integer = current_r_nocull; + r_drawworld->integer = current_r_drawworld; + AddAllWorldSurfaces(); +} + +/* void GenerateCommandBuffer() { + uint count = 0; + for ( const Material& material : globalMaterials ) { + count += material.drawCommands.size(); + } + + if ( count == 0 ) { + return; + } + + GL_CheckErrors(); + commandBuffer.BindBuffer(); + GL_CheckErrors(); + glBufferData( GL_DRAW_INDIRECT_BUFFER, count * sizeof( GLIndirectBuffer::GLIndirectCommand ), nullptr, GL_STATIC_DRAW ); + GL_CheckErrors(); + + GLIndirectBuffer::GLIndirectCommand* commandsInitial = commandBuffer.MapBufferRange( count ); + GLIndirectBuffer::GLIndirectCommand* commands = commandsInitial; + GL_CheckErrors(); + uint offset = 0; + for ( Material& material : globalMaterials ) { + uint drawCmdCount = 0; + material.commandBufferOffset = offset; + + for ( const DrawCommand& drawCmd : material.drawCommands ) { + memcpy( commands, &drawCmd.cmd, sizeof( GLIndirectBuffer::GLIndirectCommand ) ); + commands++; + offset++; + drawCmdCount++; + } + material.currentDrawSurfCount = drawCmdCount; + } + + commandBuffer.UnmapBuffer(); +} */ + +void MaterialSystem::AddAllWorldSurfaces() { + generatingWorldCommandBuffer = true; + for ( drawSurf_t* drawSurf : allDrawSurfs ) { + Tess_Begin( Tess_StageIteratorColor, nullptr, drawSurf->shader, nullptr, false, drawSurf->lightmapNum(), + drawSurf->fogNum(), drawSurf->bspSurface ); + tess.currentDrawSurf = drawSurf; + rb_surfaceTable[Util::ordinal( *drawSurf->surface )]( drawSurf->surface ); + Tess_End(); + } + + GenerateWorldCommandBuffer(); + generatingWorldCommandBuffer = false; + generatedWorldCommandBuffer = true; + tr.generatingMaterials = false; +} + +void MaterialSystem::UpdateDynamicSurfaces() { + if ( dynamicDrawSurfsSize == 0 ) { + return; + } + + materialsSSBO.BindBuffer(); + uint32_t* materialsDataInitial = materialsSSBO.MapBufferRange( dynamicDrawSurfsOffset, dynamicDrawSurfsSize ); + uint32_t* materialsData = materialsDataInitial; + memset( materialsData, 0, 4 * dynamicDrawSurfsSize ); + for ( drawSurf_t& drawSurf : dynamicDrawSurfs ) { + for ( int stage = 0; stage < drawSurf.shader->numStages; stage++ ) { + shaderStage_t* pStage = drawSurf.shader->stages[stage]; + + Material& material = materialPacks[drawSurf.materialPackIDs[stage]].materials[drawSurf.materialIDs[stage]]; + + switch ( pStage->type ) { + case stageType_t::ST_COLORMAP: + // generic2D + UpdateSurfaceDataGeneric( materialsData, material, &drawSurf, stage ); + break; + case stageType_t::ST_STYLELIGHTMAP: + case stageType_t::ST_STYLECOLORMAP: + UpdateSurfaceDataGeneric( materialsData, material, &drawSurf, stage ); + break; + case stageType_t::ST_LIGHTMAP: + case stageType_t::ST_DIFFUSEMAP: + case stageType_t::ST_COLLAPSE_COLORMAP: + case stageType_t::ST_COLLAPSE_DIFFUSEMAP: + UpdateSurfaceDataLightMapping( materialsData, material, &drawSurf, stage ); + break; + case stageType_t::ST_REFLECTIONMAP: + case stageType_t::ST_COLLAPSE_REFLECTIONMAP: + UpdateSurfaceDataReflection( materialsData, &drawSurf, stage ); + break; + case stageType_t::ST_REFRACTIONMAP: + case stageType_t::ST_DISPERSIONMAP: + // Not implemented yet + break; + case stageType_t::ST_SKYBOXMAP: + UpdateSurfaceDataSkybox( materialsData, &drawSurf, stage ); + break; + case stageType_t::ST_SCREENMAP: + UpdateSurfaceDataScreen( materialsData, &drawSurf, stage ); + break; + case stageType_t::ST_PORTALMAP: + // This is supposedly used for alphagen portal and portal surfaces should never get here + ASSERT_UNREACHABLE(); + break; + case stageType_t::ST_HEATHAZEMAP: + UpdateSurfaceDataHeatHaze( materialsData, &drawSurf, stage ); + break; + case stageType_t::ST_LIQUIDMAP: + UpdateSurfaceDataLiquid( materialsData, &drawSurf, stage ); + break; + + default: + break; + } + } + } + materialsSSBO.UnmapBuffer(); +} + +void MaterialSystem::Free() { + allDrawSurfs.clear(); + dynamicDrawSurfs.clear(); + for ( MaterialPack& pack : materialPacks ) { + for ( Material& material : pack.materials ) { + material.drawCommands.clear(); + material.drawSurfs.clear(); + } + pack.materials.clear(); + } +} + +void BuildCommandBuffer() { + // +} + +uint32_t* MaterialSystem::MapMaterialsSSBO( uint count ) { + if ( !materialsSSBOMapped ) { + materialsSSBOMapped = true; + materialsData = materialsSSBO.MapBufferRange( count ); + } + + return materialsData; +} + +void MaterialSystem::AddDrawCommand( const uint materialID, const uint materialPackID, const uint materialsSSBOOffset, + const GLuint count, const GLuint firstIndex ) { + cmd.cmd.count = count; + cmd.cmd.instanceCount = 1; + cmd.cmd.firstIndex = firstIndex; + cmd.cmd.baseVertex = 0; + cmd.cmd.baseInstance = materialsSSBOOffset; + cmd.materialsSSBOOffset = materialsSSBOOffset; + + materialPacks[materialPackID].materials[materialID].drawCommands.emplace_back(cmd); + cmd.textureCount = 0; +} + +void MaterialSystem::AddTexture( Texture* texture ) { + if ( cmd.textureCount > MAX_DRAWCOMMAND_TEXTURES ) { + Sys::Drop( "Exceeded max DrawCommand textures" ); + } + cmd.textures[cmd.textureCount] = texture; + cmd.textureCount++; +} + +void MaterialSystem::RenderMaterials( const shaderSort_t fromSort, const shaderSort_t toSort ) { + GL_State( GLS_DEFAULT ); + materialsSSBO.BindBufferBase(); + // TODO: Make this per-view instead + if ( materialSystem.frameStart ) { + backEnd.orientation = backEnd.viewParms.world; + GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); + for ( MaterialPack& pack : materialPacks ) { + for ( Material& material : pack.materials ) { + // GL_BindProgram( material.program ); + // glUseProgram( material.program ); + switch ( material.stageType ) { + case stageType_t::ST_COLORMAP: + case stageType_t::ST_STYLELIGHTMAP: + case stageType_t::ST_STYLECOLORMAP: + gl_genericShaderMaterial->BindProgram( material.deformIndex ); + gl_genericShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + gl_genericShaderMaterial->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); + break; + case stageType_t::ST_LIGHTMAP: + case stageType_t::ST_DIFFUSEMAP: + case stageType_t::ST_COLLAPSE_COLORMAP: + case stageType_t::ST_COLLAPSE_DIFFUSEMAP: + gl_lightMappingShaderMaterial->BindProgram( material.deformIndex ); + gl_lightMappingShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + gl_lightMappingShaderMaterial->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); + break; + default: + break; + } + // gl_lightMappingShaderMaterial->BindProgram( 0 ); + } + } + + UpdateDynamicSurfaces(); + materialSystem.frameStart = false; + } + + for ( MaterialPack& materialPack : materialPacks ) { + if ( materialPack.fromSort >= fromSort && materialPack.toSort <= toSort ) { + for ( Material& material : materialPack.materials ) { + RenderMaterial( material ); + } + } + } + glState.currentProgram = nullptr; + if ( tr.hasSkybox && ( ( fromSort <= shaderSort_t::SS_ENVIRONMENT_FOG ) && ( toSort >= shaderSort_t::SS_ENVIRONMENT_FOG ) + || ( fromSort <= shaderSort_t::SS_ENVIRONMENT_NOFOG ) && toSort >= ( shaderSort_t::SS_ENVIRONMENT_NOFOG ) ) ) { + const bool noFogPass = toSort >= shaderSort_t::SS_ENVIRONMENT_NOFOG; + for ( shader_t* skyShader : skyShaders ) { + if ( skyShader->noFog != noFogPass ) { + continue; + } + + tr.drawingSky = true; + Tess_Begin( Tess_StageIteratorSky, nullptr, skyShader, nullptr, false, -1, -1, false ); + Tess_End(); + } + } +} + +void MaterialSystem::RenderMaterial( Material& material ) { + backEnd.currentEntity = &tr.worldEntity; + uint cmdCount = 0; + uint offset = material.staticCommandOffset; + + GL_State( material.stateBits ); + GL_Cull( material.cullType ); + if ( material.cullType == cullType_t::CT_TWO_SIDED ) { + // glDisable( GL_DEPTH_TEST ); + } + if ( material.stateBits == ( material.stateBits & GLS_DEPTHMASK_TRUE ) ) { + // glDisable( GL_CULL_FACE ); + } + // glDisable( GL_CULL_FACE ); + // Log::Warn( "%i", material.cullType ); + // glUseProgram( material.program ); + material.shader->BindProgram( material.deformIndex ); + // GL_BindProgram( material.program ); + // glUseProgram( material.program ); + + R_BindVBO( material.vbo ); + R_BindIBO( material.ibo ); + material.shader->SetRequiredVertexPointers(); + + for ( const DrawCommand& cmd : material.drawCommands ) { + uint texIndex = 0; + cmdCount++; + while ( texIndex < cmd.textureCount ) { + bool makeResidentFailed = tr.textureManager.MakeTextureResident( cmd.textures[texIndex], false ); + if ( makeResidentFailed ) { + if ( cmdCount == 0 ) { + Sys::Drop( "No texture space available" ); + } + + // Send the rendering commands we already gathered if we can't make all textures resident + glMultiDrawElementsIndirect( GL_TRIANGLES, GL_UNSIGNED_INT, + BUFFER_OFFSET( offset * sizeof( GLIndirectBuffer::GLIndirectCommand ) ), cmdCount, 0 ); + offset += cmdCount; + cmdCount = 0; + texIndex = 0; + tr.textureManager.ClearTextureQueue(); + continue; + } + + texIndex++; + } + } + + if ( cmdCount > 0 ) { + glMultiDrawElementsIndirect( GL_TRIANGLES, GL_UNSIGNED_INT, + BUFFER_OFFSET( offset * sizeof( GLIndirectBuffer::GLIndirectCommand ) ), cmdCount, 0 ); + offset += cmdCount; + } +} diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h new file mode 100644 index 0000000000..757fc3fad9 --- /dev/null +++ b/src/engine/renderer/Material.h @@ -0,0 +1,120 @@ +#pragma once + +#include + +#include "gl_shader.h" +#include "tr_local.h" + +static constexpr uint MAX_DRAWCOMMAND_TEXTURES = 32; + +struct DrawCommand { + GLIndirectBuffer::GLIndirectCommand cmd; + uint materialsSSBOOffset = 0; + uint textureCount = 0; + Texture* textures[MAX_DRAWCOMMAND_TEXTURES]; + + DrawCommand() { + } + + DrawCommand( const DrawCommand& other ) { + cmd = other.cmd; + materialsSSBOOffset = other.materialsSSBOOffset; + textureCount = other.textureCount; + memcpy( textures, other.textures, textureCount * sizeof( Texture* ) ); + } +}; + +struct Material { + uint materialsSSBOOffset = 0; + uint staticMaterialsSSBOOffset = 0; + uint dynamicMaterialsSSBOOffset = 0; + uint totalDrawSurfCount = 0; + uint totalStaticDrawSurfCount = 0; + uint totalDynamicDrawSurfCount = 0; + uint currentDrawSurfCount = 0; + uint currentStaticDrawSurfCount = 0; + uint currentDynamicDrawSurfCount = 0; + + uint staticCommandOffset = 0; + + uint id = 0; + bool useSync = false; + uint syncMaterial = 0; // Must not be drawn before the material with this id + + uint32_t stateBits = 0; + stageType_t stageType; + // GLuint program = 0; + shaderProgram_t* program; + GLShader* shader; + int deformIndex = 0; + cullType_t cullType; + + VBO_t* vbo; + IBO_t* ibo; + + std::vector drawSurfs; + std::vector drawCommands; + + bool operator==( const Material& other ) { + return program == other.program && stateBits == other.stateBits && vbo == other.vbo && ibo == other.ibo + && stateBits == other.stateBits && cullType == other.cullType; + } +}; + +class MaterialSystem { + public: + bool generatedWorldCommandBuffer = false; + bool generatingWorldCommandBuffer = false; + vec3_t worldViewBounds[2] = {}; + std::vector skyShaders; + std::vector deformIndexes; + + struct MaterialPack { + const shaderSort_t fromSort; + const shaderSort_t toSort; + std::vector materials; + + MaterialPack( const shaderSort_t newFromSort, const shaderSort_t newToSort ) : + fromSort( newFromSort ), + toSort( newToSort ) { + } + }; + + MaterialPack materialPacks[3]{ + { shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH }, + { shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE }, + { shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS } + }; + + bool frameStart = true; + + uint32_t* MapMaterialsSSBO( uint count ); + void AddDrawCommand( const uint materialID, const uint materialPackID, const uint materialsSSBOOffset, const GLuint count, const GLuint firstIndex ); + void AddTexture( Texture* texture ); + void RenderMaterials( const shaderSort_t fromSort, const shaderSort_t toSort ); + void GenerateMaterials(); + void GenerateMaterialsBuffer(); + void GenerateWorldCommandBuffer(); + + void AddAllWorldSurfaces(); + void UpdateDynamicSurfaces(); + + void Free(); + + private: + DrawCommand cmd; + bool materialsSSBOMapped = false; + uint32_t* materialsData; + std::vector allDrawSurfs; + std::vector dynamicDrawSurfs; + uint dynamicDrawSurfsOffset = 0; + uint dynamicDrawSurfsSize = 0; + + void RenderMaterial( Material& material ); +}; + +void BuildCommandBuffer(); + +extern GLSSBO materialsSSBO; +extern GLIndirectBuffer commandBuffer; +extern MaterialSystem materialSystem; diff --git a/src/engine/renderer/TextureManager.cpp b/src/engine/renderer/TextureManager.cpp index b2946a5349..c33290daa1 100644 --- a/src/engine/renderer/TextureManager.cpp +++ b/src/engine/renderer/TextureManager.cpp @@ -45,14 +45,6 @@ Texture::~Texture() { } } -void Texture::UpdateAdjustedPriority( const int totalFrameTextureBinds, const int totalTextureBinds ) { - if ( totalFrameTextureBinds == 0 || totalTextureBinds == 0 ) { - return; - } - - adjustedPriority = basePriority + frameBindCounter / totalFrameTextureBinds * 0.5 + totalBindCounter / totalTextureBinds * 1.5; -} - bool Texture::IsResident() const { return bindlessTextureResident; } @@ -77,37 +69,74 @@ void Texture::GenBindlessHandle() { hasBindlessHandle = true; } -// TextureManager textureManager; - TextureManager::TextureManager() { textureUnits.reserve( glConfig2.maxTextureUnits ); } TextureManager::~TextureManager() = default; -void TextureManager::UpdateAdjustedPriorities() { - for ( Texture* texture : textures ) { - texture->UpdateAdjustedPriority( totalFrameTextureBinds, totalTextureBinds ); +GLuint64 TextureManager::RecordTexture( Texture* texture ) { + if ( std::find( textures.begin(), textures.end(), texture ) == textures.end() ) { + textures.push_back( texture ); + } + + if ( !texture->hasBindlessHandle ) { + texture->GenBindlessHandle(); } - // std::sort( textures.begin(), textures.end(), Texture::Compare() ); - totalFrameTextureBinds = 0; + return texture->bindlessTextureHandle; } -void TextureManager::BindTexture( const GLint location, Texture *texture ) { - texture->frameBindCounter++; - texture->totalBindCounter++; - - totalFrameTextureBinds++; - totalTextureBinds++; +void TextureManager::ClearTextureQueue() { + texQueue = std::queue(); +} + +bool TextureManager::MakeTextureResident( Texture* texture, const bool force ) { + if ( texture->IsResident() ) { + texQueue.push( texture ); + return false; + } + + if ( !texture->hasBindlessHandle ) { + texture->GenBindlessHandle(); + } + + texture->MakeResident(); + // Log::Warn( "Res tex: %u", texture->bindlessTextureHandle ); + + // Make lowest priority textures non-resident first + while ( !glIsTextureHandleResidentARB( texture->bindlessTextureHandle ) ) { + if ( texQueue.empty() ) { + Sys::Drop( "No texture space available" ); + } + + if ( !force ) { + return true; + } + + if ( texQueue.front()->IsResident() ) { + texQueue.front()->MakeNonResident(); + texQueue.pop(); + texture->MakeResident(); + } + } + + texQueue.push( texture ); + + GL_CheckErrors(); + + return false; +} +GLuint64 TextureManager::BindTexture( const GLint location, Texture *texture ) { if( location == -1 ) { - return; + return 0; } if ( texture->IsResident() ) { - glUniformHandleui64ARB( location, texture->bindlessTextureHandle ); - return; + // glUniformHandleui64ARB( location, texture->bindlessTextureHandle ); + GL_CheckErrors(); + return texture->bindlessTextureHandle; } if( std::find( textures.begin(), textures.end(), texture ) == textures.end() ) { @@ -122,6 +151,7 @@ void TextureManager::BindTexture( const GLint location, Texture *texture ) { } texture->MakeResident(); + GL_CheckErrors(); // Make lowest priority textures non-resident first int i = textures.size() - 1; @@ -136,61 +166,14 @@ void TextureManager::BindTexture( const GLint location, Texture *texture ) { } i--; } - - glUniformHandleui64ARB( location, texture->bindlessTextureHandle ); - GL_CheckErrors(); - return; - } + // glUniformHandleui64ARB( location, texture->bindlessTextureHandle ); - int lowestPriorityTexture = 1; - float lowestPriority = 100000.0f; - GLint handle; - - // Do a loop once so we don't have to search through it many times for each case - for ( size_t i = 0; i < textureUnits.size(); i++ ) { - // Already bound - if ( textureUnits[i] == texture ) { - glUniform1i( location, i + 1 ); - if ( textureSequenceStarted ) { - textureSequence.insert( texture ); - } - return; - } - - if ( textureSequenceStarted && textureSequence.find( textureUnits[i] ) != textureSequence.end() ) { - continue; - } - - // Take note of the texture unit with the lowest priority texture - if ( textureUnits[i] && textureUnits[i]->adjustedPriority < lowestPriority ) { - lowestPriorityTexture = i; - lowestPriority = textureUnits[i]->adjustedPriority; - } - } - - // Slot 0 is reserved for non-rendering OpenGL calls that require textures to be bound - if ( textureUnits.size() + 1 < (size_t) glConfig2.maxTextureUnits ) { - textureUnits.push_back( texture ); - glActiveTexture( GL_TEXTURE1 + textureUnits.size() - 1 ); - handle = textureUnits.size() - 1; - } - else { - // No available texture units - // Bind instead of the lowest priority texture - textureUnits[lowestPriorityTexture] = texture; - glActiveTexture( GL_TEXTURE1 + lowestPriorityTexture ); - handle = lowestPriorityTexture; - } + GL_CheckErrors(); - glBindTexture( texture->target, texture->textureHandle ); - glUniform1i( location, handle + 1 ); - if ( textureSequenceStarted ) { - textureSequence.insert( texture ); + return texture->bindlessTextureHandle; } - - GL_CheckErrors(); } void TextureManager::AllNonResident() { diff --git a/src/engine/renderer/TextureManager.h b/src/engine/renderer/TextureManager.h index 59ed59ae1a..d318927743 100644 --- a/src/engine/renderer/TextureManager.h +++ b/src/engine/renderer/TextureManager.h @@ -40,11 +40,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "GL/glew.h" -enum { - TEXTURE_PRIORITY_LOW = 0, - TEXTURE_PRIORITY_MEDIUM = 1, - TEXTURE_PRIORITY_HIGH = 2, - TEXTURE_PRIORITY_PERSISTENT = 5, +struct TextureHandles { + GLuint64 bindlessHandle; + GLuint textureUnit; }; class Texture { @@ -53,33 +51,16 @@ class Texture { GLuint64 bindlessTextureHandle = 0; bool hasBindlessHandle = false; - int frameBindCounter = 0; - int totalBindCounter = 0; - GLenum target = GL_TEXTURE_2D; - int basePriority = 0; - float adjustedPriority = 0.0f; - Texture(); ~Texture(); - void UpdateAdjustedPriority( const int totalFrameTextureBinds, const int totalTextureBinds ); - bool IsResident() const; void MakeResident(); void MakeNonResident(); - void GenBindlessHandle(); - - struct Compare { - bool operator() ( const Texture* lhs, const Texture* rhs ) { - if ( lhs->adjustedPriority != rhs->adjustedPriority ) { - return lhs->adjustedPriority > rhs->adjustedPriority; - } - return lhs->adjustedPriority < rhs->adjustedPriority; - } - }; + void GenBindlessHandle();; private: bool bindlessTextureResident = false; @@ -90,9 +71,10 @@ class TextureManager { TextureManager(); ~TextureManager(); - void UpdateAdjustedPriorities(); - - void BindTexture( const GLint location, Texture* texture ); + GLuint64 RecordTexture( Texture* texture ); + void ClearTextureQueue(); + bool MakeTextureResident( Texture* texture, const bool force ); + GLuint64 BindTexture( const GLint location, Texture* texture ); void AllNonResident(); void BindReservedTexture( const GLenum target, const GLuint handle ); void StartTextureSequence(); @@ -101,15 +83,11 @@ class TextureManager { private: std::vector textureUnits; + std::queue texQueue; std::vector textures; std::unordered_set textureSequence; bool textureSequenceStarted; - - int totalFrameTextureBinds; - int totalTextureBinds; }; -// extern TextureManager textureManager; - #endif diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index d7a74db932..b7f78ed160 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -41,7 +41,9 @@ ShaderKind shaderKind = ShaderKind::Unknown; GLShader_generic2D *gl_generic2DShader = nullptr; GLShader_generic *gl_genericShader = nullptr; +GLShader_genericMaterial *gl_genericShaderMaterial = nullptr; GLShader_lightMapping *gl_lightMappingShader = nullptr; +GLShader_lightMappingMaterial *gl_lightMappingShaderMaterial = nullptr; GLShader_forwardLighting_omniXYZ *gl_forwardLightingShader_omniXYZ = nullptr; GLShader_forwardLighting_projXYZ *gl_forwardLightingShader_projXYZ = nullptr; GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun = nullptr; @@ -67,6 +69,18 @@ GLShader_lighttile *gl_lighttileShader = nullptr; GLShader_fxaa *gl_fxaaShader = nullptr; GLShaderManager gl_shaderManager; +const GLuint GLUniform::GetSTD430Size() const { + return _std430Size; +} + +const GLuint GLUniform::GetSTD430Alignment() const { + return _std430Alignment; +} + +uint32_t* GLUniform::WriteToBuffer( uint32_t* buffer ) { + return buffer; +} + namespace // Implementation details { NORETURN inline void ThrowShaderError(Str::StringRef msg) @@ -423,6 +437,12 @@ static std::string GenVersionDeclaration() { GLEW_ARB_uniform_buffer_object, "ARB_uniform_buffer_object" ); addExtension( str, glConfig2.bindlessTexturesAvailable, -1, GLEW_ARB_bindless_texture, "ARB_bindless_texture" ); + addExtension( str, glConfig2.shaderDrawParametersAvailable, 460, + GLEW_ARB_shader_draw_parameters, "ARB_shader_draw_parameters" ); + addExtension( str, glConfig2.SSBOAvailable, 430, + GLEW_ARB_shader_storage_buffer_object, "ARB_shader_storage_buffer_object" ); + addExtension(str, glConfig2.shaderInt64Available, -1, + GLEW_ARB_gpu_shader_int64, "ARB_gpu_shader_int64" ); return str; } @@ -454,6 +474,11 @@ static std::string GenVertexHeader() { "#define OUT(mode) varying\n"; } + if ( glConfig2.shaderDrawParametersAvailable ) { + str += "OUT(flat) int in_drawID;\n"; + str += "OUT(flat) int in_baseInstance;\n"; + } + return str; } @@ -481,6 +506,11 @@ static std::string GenFragmentHeader() { str += "layout(bindless_sampler) uniform;\n"; } + if ( glConfig2.shaderDrawParametersAvailable ) { + str += "IN(flat) int in_drawID;\n"; + str += "IN(flat) int in_baseInstance;\n"; + } + return str; } @@ -737,7 +767,7 @@ std::string GLShaderManager::BuildGPUShaderText( Str::StringRef mainShaderNa // We added a lot of stuff but if we do something bad // in the GLSL shaders then we want the proper line // so we have to reset the line counting. - libs += "#line 0\n"; + // libs += "#line 0\n"; } // load main() program @@ -774,7 +804,7 @@ std::string GLShaderManager::BuildGPUShaderText( Str::StringRef mainShaderNa // We added a lot of stuff but if we do something bad // in the GLSL shaders then we want the proper line // so we have to reset the line counting. - env += "#line 0\n"; + // env += "#line 0\n"; std::string shaderText = env + libs + GetShaderText(filename); @@ -907,6 +937,8 @@ void GLShaderManager::InitShader( GLShader *shader ) { shader->_shaderPrograms = std::vector( static_cast(1) << shader->_compileMacros.size() ); + shader->PostProcessUniforms(); + shader->_uniformStorageSize = 0; for ( std::size_t i = 0; i < shader->_uniforms.size(); i++ ) { @@ -923,6 +955,9 @@ void GLShaderManager::InitShader( GLShader *shader ) } std::string vertexInlines; + if ( glConfig2.shaderDrawParametersAvailable ) { + vertexInlines = "commandQueue "; + } shader->BuildShaderVertexLibNames( vertexInlines ); std::string fragmentInlines; @@ -930,6 +965,10 @@ void GLShaderManager::InitShader( GLShader *shader ) shader->_vertexShaderText = BuildGPUShaderText( shader->GetMainShaderName(), vertexInlines, GL_VERTEX_SHADER ); shader->_fragmentShaderText = BuildGPUShaderText( shader->GetMainShaderName(), fragmentInlines, GL_FRAGMENT_SHADER ); + if ( glConfig2.shaderDrawParametersAvailable && glConfig2.SSBOAvailable ) { + shader->_vertexShaderText = ShaderPostProcess( shader, shader->_vertexShaderText, true ); + shader->_fragmentShaderText = ShaderPostProcess( shader, shader->_fragmentShaderText, false ); + } std::string combinedShaderText = GLVersionDeclaration.getText() + GLCompatHeader.getText() @@ -1145,6 +1184,120 @@ void GLShaderManager::CompileAndLinkGPUShaderProgram( GLShader *shader, shaderPr LinkProgram( program->program ); } +// This will generate all the extra code for material system shaders +std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::string& shaderText, const bool isVertexShader ) { + std::string newShaderText; + std::string drawcallStateStruct = "\nstruct DrawcallState {\n"; + std::string drawcallStateBlock = "layout(std430, binding = 0) readonly buffer drawcallStateSSBO {\n" + " DrawcallState drawcallStates[];\n" + "};\n\n"; + std::string drawcallStateDefines; + if ( isVertexShader ) { + drawcallStateDefines = "#define drawID gl_DrawIDARB\n"; + drawcallStateDefines += "#define baseInstance gl_BaseInstanceARB\n\n"; + } else { + drawcallStateDefines = "#define drawID in_drawID\n"; + drawcallStateDefines += "#define baseInstance in_baseInstance\n\n"; + } + + if ( !shader->_useMaterialSystem ) { + return drawcallStateDefines + shaderText; + } + + for( GLUniform* uniform : shader->_uniforms ) { + if ( uniform->IsGlobal() ) { + continue; + } + + if ( uniform->IsTexture() ) { + drawcallStateStruct += " uvec2 "; // Driver bug: AMD compiler crashes when using uint64_t for textures here + drawcallStateStruct += uniform->GetName(); + } else { + drawcallStateStruct += " " + uniform->GetType() + " " + uniform->GetName(); + } + + if ( uniform->GetComponentSize() ) { + drawcallStateStruct += "[ " + std::to_string( uniform->GetComponentSize() ) + " ]"; + } + drawcallStateStruct += ";\n"; + + // vec3 has weird alignment, so just pad it with int + if ( uniform->GetSTD430Size() == 3 ) { + drawcallStateStruct += " int "; + drawcallStateStruct += uniform->GetName(); + drawcallStateStruct += "_padding;\n"; + } + + drawcallStateDefines += "#define "; + drawcallStateDefines += uniform->GetName(); + if ( uniform->IsTexture() ) { + drawcallStateDefines += "_initial uvec2("; + } + drawcallStateDefines += " drawcallStates[baseInstance]."; + drawcallStateDefines += uniform->GetName(); + if ( uniform->IsTexture() ) { + drawcallStateDefines += " )"; + } + drawcallStateDefines += "\n"; + } + + // Array of structs is aligned to the largest member of the struct + for ( int i = 0; i < shader->padding; i++ ) { + drawcallStateStruct += " int drawcallState_padding" + std::to_string( i ); + drawcallStateStruct += ";\n"; + } + + drawcallStateStruct += "};\n\n"; + drawcallStateDefines += "\n"; + + std::istringstream shaderTextStream( shaderText ); + std::string shaderMain; + + std::string line; + + bool mainFound = false; + bool skip = true; + while( std::getline( shaderTextStream, line, '\n' ) ) { + // Try to avoid removing uniform/storage blocks + if( !( line.find( "uniform" ) == std::string::npos || line.find( ";" ) == std::string::npos ) ) { + continue; + } + + // Driver bug: AMD compiler crashes when using the uvec2 define directly, + // so create a local variable in the form of "sampler* textureName = sampler*(textureName_initial)" + for ( GLUniform* uniform : shader->_uniforms ) { + if ( uniform->IsTexture() && line.find( uniform->GetName() ) != std::string::npos ) { + shaderMain += uniform->GetType() + " " + uniform->GetName() + " = " + uniform->GetType() + "(" + uniform->GetName() + + "_initial);\n"; + } + } + shaderMain += line + "\n"; + + /* if ( line.find("main()") != std::string::npos ) { + mainFound = true; + } + + if ( mainFound && line.find( "{" ) != std::string::npos ) { + shaderMain += "SETUP_SHADER_PARMS"; + } */ + } + + for ( GLUniform* uniform : shader->_uniforms ) { + if ( uniform->IsGlobal() ) { + drawcallStateDefines += "uniform " + uniform->GetType() + " " + uniform->GetName(); + if ( uniform->GetComponentSize() ) { + drawcallStateDefines += "[ " + std::to_string( uniform->GetComponentSize() ) + " ]"; + } + drawcallStateDefines += ";\n"; + } + } + + drawcallStateDefines += "\n"; + + newShaderText = drawcallStateStruct + drawcallStateBlock + drawcallStateDefines + shaderMain; + return newShaderText; +} + GLuint GLShaderManager::CompileShader( Str::StringRef programName, Str::StringRef shaderText, std::initializer_list headers, @@ -1470,11 +1623,77 @@ bool GLCompileMacro_USE_BSP_SURFACE::HasConflictingMacros(size_t permutation, co return false; } +void GLShader::RegisterUniform( GLUniform* uniform ) { + _uniforms.push_back( uniform ); + textureCount += uniform->IsTexture(); +} + GLint GLShader::GetUniformLocation( const GLchar *uniformName ) const { shaderProgram_t* p = GetProgram(); return glGetUniformLocation( p->program, uniformName ); } +void GLShader::PostProcessUniforms() { + if ( !_useMaterialSystem ) { + return; + } + + std::vector tmp; + + int currentBlockSize = 0; + + std::vector globalUniforms; + for ( GLUniform* uniform : _uniforms ) { + if ( uniform->IsGlobal() ) { + globalUniforms.emplace_back( uniform ); + } + } + for ( GLUniform* uniform : globalUniforms ) { + _uniforms.erase( std::remove( _uniforms.begin(), _uniforms.end(), uniform ), _uniforms.end() ); + } + + // Sort uniforms from highest to lowest alignment so we don't need to pad uniforms (other than vec3s) + int numUniforms = _uniforms.size(); + GLuint structAlignment = 0; + GLuint structSize = 0; + while ( tmp.size() < numUniforms ) { + // Higher-alignment uniforms first to avoid wasting memory + GLuint highestAlignment = 0; + int highestUniform = 0; + for( int i = 0; i < _uniforms.size(); i++ ) { + if ( _uniforms[i]->GetSTD430Alignment() > highestAlignment ) { + highestAlignment = _uniforms[i]->GetSTD430Alignment(); + highestUniform = i; + } + if ( highestAlignment > structAlignment ) { + structAlignment = highestAlignment; + } + if ( highestAlignment == 4 ) { + break; // 4-component is the highest alignment in std430 + } + } + + const GLuint size = _uniforms[highestUniform]->GetSTD430Size(); + if ( _uniforms[highestUniform]->GetComponentSize() != 0 ) { + currentBlockSize = ( size == 3 ) ? 4 * _uniforms[highestUniform]->GetComponentSize() : + size * _uniforms[highestUniform]->GetComponentSize(); + } else { + currentBlockSize = ( size == 3 ) ? 4 : size; + } + + structSize += currentBlockSize; + tmp.emplace_back( _uniforms[highestUniform] ); + _uniforms.erase( _uniforms.begin() + highestUniform ); + } + _uniforms = tmp; + + padding = ( structAlignment - ( structSize % structAlignment ) ) % structAlignment; + std430Size = structSize; + for ( GLUniform* uniform : globalUniforms ) { + _uniforms.emplace_back( uniform ); + } +} + bool GLShader::GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut ) const { compileMacrosOut.clear(); @@ -1517,6 +1736,38 @@ int GLShader::SelectProgram() return index; } +shaderProgram_t* GLShader::GetProgram( int deformIndex ) { + int macroIndex = SelectProgram(); + size_t index = macroIndex + ( size_t( deformIndex ) << _compileMacros.size() ); + + // program may not be loaded yet because the shader manager hasn't yet gotten to it + // so try to load it now + if ( index >= _shaderPrograms.size() || !_shaderPrograms[index].program ) { + _shaderManager->buildPermutation( this, macroIndex, deformIndex ); + } + + // program is still not loaded + if ( index >= _shaderPrograms.size() || !_shaderPrograms[index].program ) { + std::string activeMacros; + size_t numMacros = _compileMacros.size(); + + for ( size_t j = 0; j < numMacros; j++ ) { + GLCompileMacro* macro = _compileMacros[j]; + + int bit = macro->GetBit(); + + if ( IsMacroSet( bit ) ) { + activeMacros += macro->GetName(); + activeMacros += " "; + } + } + + ThrowShaderError( Str::Format( "Invalid shader configuration: shader = '%s', macros = '%s'", _name, activeMacros ) ); + } + + return &_shaderPrograms[index]; +} + void GLShader::BindProgram( int deformIndex ) { int macroIndex = SelectProgram(); @@ -1576,11 +1827,19 @@ void GLShader::SetRequiredVertexPointers() GL_VertexAttribsState( ( _vertexAttribsRequired | _vertexAttribs | macroVertexAttribs ) ); // & ~_vertexAttribsUnsupported); } +void GLShader::WriteUniformsToBuffer( uint32_t* buffer ) { + uint32_t* bufPtr = buffer; + for ( GLUniform* uniform : _uniforms ) { + if ( !uniform->IsGlobal() ) { + bufPtr = uniform->WriteToBuffer( bufPtr ); + } + } +} + GLShader_generic2D::GLShader_generic2D( GLShaderManager *manager ) : GLShader( "generic2D", "generic", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager ), u_ColorMap( this ), u_DepthMap( this ), - u_EnvironmentMap1( this ), u_TextureMatrix( this ), u_AlphaThreshold( this ), u_ModelMatrix( this ), @@ -1614,13 +1873,11 @@ GLShader_generic::GLShader_generic( GLShaderManager *manager ) : GLShader( "generic", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager ), u_ColorMap( this ), u_DepthMap( this ), - u_EnvironmentMap1( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), u_ViewUp( this ), u_AlphaThreshold( this ), u_ModelMatrix( this ), - u_ProjectionMatrixTranspose( this ), u_ModelViewProjectionMatrix( this ), u_InverseLightFactor( this ), u_ColorModulate( this ), @@ -1650,6 +1907,41 @@ void GLShader_generic::SetShaderProgramUniforms( shaderProgram_t *shaderProgram glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 1 ); } +GLShader_genericMaterial::GLShader_genericMaterial( GLShaderManager* manager ) : + GLShader( "genericMaterial", "generic", true, ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager ), + u_ColorMap( this ), + u_DepthMap( this ), + u_TextureMatrix( this ), + u_ViewOrigin( this ), + u_ViewUp( this ), + u_AlphaThreshold( this ), + u_ModelMatrix( this ), + u_ModelViewProjectionMatrix( this ), + u_InverseLightFactor( this ), + u_ColorModulate( this ), + u_Color( this ), + // u_Bones( this ), + u_VertexInterpolation( this ), + u_DepthScale( this ), + GLDeformStage( this ), + // GLCompileMacro_USE_VERTEX_SKINNING( this ), + GLCompileMacro_USE_VERTEX_ANIMATION( this ), + GLCompileMacro_USE_VERTEX_SPRITE( this ), + GLCompileMacro_USE_TCGEN_ENVIRONMENT( this ), + GLCompileMacro_USE_TCGEN_LIGHTMAP( this ), + GLCompileMacro_USE_DEPTH_FADE( this ), + GLCompileMacro_USE_ALPHA_TESTING( this ) { +} + +void GLShader_genericMaterial::BuildShaderVertexLibNames( std::string& vertexInlines ) { + vertexInlines += "vertexSimple vertexSkinning vertexAnimation vertexSprite "; +} + +void GLShader_genericMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 1 ); +} + GLShader_lightMapping::GLShader_lightMapping( GLShaderManager *manager ) : GLShader( "lightMapping", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT | ATTR_COLOR, manager ), @@ -1662,7 +1954,10 @@ GLShader_lightMapping::GLShader_lightMapping( GLShaderManager *manager ) : u_GlowMap( this ), u_EnvironmentMap0( this ), u_EnvironmentMap1( this ), + u_LightGrid1( this ), + u_LightGrid2( this ), u_LightTiles( this ), + u_LightTilesInt( this ), u_LightsTexture( this ), u_TextureMatrix( this ), u_SpecularExponent( this ), @@ -1728,6 +2023,80 @@ void GLShader_lightMapping::SetShaderProgramUniforms( shaderProgram_t *shaderPro } } +GLShader_lightMappingMaterial::GLShader_lightMappingMaterial( GLShaderManager* manager ) : + GLShader( "lightMappingMaterial", "lightMapping", true, + ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT | ATTR_COLOR, manager ), + u_DiffuseMap( this ), + u_NormalMap( this ), + u_HeightMap( this ), + u_MaterialMap( this ), + u_LightMap( this ), + u_DeluxeMap( this ), + u_GlowMap( this ), + u_EnvironmentMap0( this ), + u_EnvironmentMap1( this ), + u_LightGrid1( this ), + u_LightGrid2( this ), + u_LightTilesInt( this ), + u_TextureMatrix( this ), + u_SpecularExponent( this ), + u_ColorModulate( this ), + u_Color( this ), + u_AlphaThreshold( this ), + u_ViewOrigin( this ), + u_ModelMatrix( this ), + u_ModelViewProjectionMatrix( this ), + u_InverseLightFactor( this ), + // u_Bones( this ), + u_VertexInterpolation( this ), + u_ReliefDepthScale( this ), + u_ReliefOffsetBias( this ), + u_NormalScale( this ), + u_EnvironmentInterpolation( this ), + u_LightGridOrigin( this ), + u_LightGridScale( this ), + u_numLights( this ), + u_Lights( this ), + GLDeformStage( this ), + GLCompileMacro_USE_BSP_SURFACE( this ), + // GLCompileMacro_USE_VERTEX_SKINNING( this ), + GLCompileMacro_USE_VERTEX_ANIMATION( this ), + GLCompileMacro_USE_DELUXE_MAPPING( this ), + GLCompileMacro_USE_GRID_LIGHTING( this ), + GLCompileMacro_USE_GRID_DELUXE_MAPPING( this ), + GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), + GLCompileMacro_USE_RELIEF_MAPPING( this ), + GLCompileMacro_USE_REFLECTIVE_SPECULAR( this ), + GLCompileMacro_USE_PHYSICAL_MAPPING( this ) { +} + +void GLShader_lightMappingMaterial::BuildShaderVertexLibNames( std::string& vertexInlines ) { + vertexInlines += "vertexSimple vertexSkinning vertexAnimation vertexSprite "; +} + +void GLShader_lightMappingMaterial::BuildShaderFragmentLibNames( std::string& fragmentInlines ) { + fragmentInlines += "computeLight reliefMapping"; +} + +void GLShader_lightMappingMaterial::BuildShaderCompileMacros( std::string& /*compileMacros*/ ) { +} + +void GLShader_lightMappingMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DiffuseMap" ), BIND_DIFFUSEMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), BIND_NORMALMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), BIND_HEIGHTMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_MaterialMap" ), BIND_MATERIALMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightMap" ), BIND_LIGHTMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DeluxeMap" ), BIND_DELUXEMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_GlowMap" ), BIND_GLOWMAP ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_EnvironmentMap0" ), BIND_ENVIRONMENTMAP0 ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_EnvironmentMap1" ), BIND_ENVIRONMENTMAP1 ); + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightTiles" ), BIND_LIGHTTILES ); + if ( !glConfig2.uniformBufferObjectAvailable ) { + glUniform1i( glGetUniformLocation( shaderProgram->program, "u_Lights" ), BIND_LIGHTS ); + } +} + GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ( GLShaderManager *manager ): GLShader("forwardLighting_omniXYZ", "forwardLighting", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager), u_DiffuseMap( this ), @@ -2022,7 +2391,7 @@ void GLShader_reflection::SetShaderProgramUniforms( shaderProgram_t *shaderProgr GLShader_skybox::GLShader_skybox( GLShaderManager *manager ) : GLShader( "skybox", ATTR_POSITION, manager ), - u_ColorMap( this ), + u_ColorMapCube( this ), u_CloudMap( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), @@ -2176,7 +2545,7 @@ void GLShader_contrast::SetShaderProgramUniforms( shaderProgram_t *shaderProgram GLShader_cameraEffects::GLShader_cameraEffects( GLShaderManager *manager ) : GLShader( "cameraEffects", ATTR_POSITION | ATTR_TEXCOORD, manager ), - u_ColorMap( this ), + u_ColorMap3D( this ), u_CurrentMap( this ), u_ColorModulate( this ), u_TextureMatrix( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index a3c72ffb2b..87aeffd02e 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -61,6 +61,7 @@ struct GLBinaryHeader }; class GLUniform; +class GLShader; class GLUniformBlock; class GLCompileMacro; class GLShaderManager; @@ -99,6 +100,10 @@ class GLShader std::string _name; std::string _mainShaderName; + const bool _useMaterialSystem; + GLuint std430Size = 0; + uint padding = 0; + uint textureCount = 0; protected: int _activeMacros; unsigned int _checkSum; @@ -124,6 +129,7 @@ class GLShader GLShader( const std::string &name, uint32_t vertexAttribsRequired, GLShaderManager *manager ) : _name( name ), _mainShaderName( name ), + _useMaterialSystem( false ), _activeMacros( 0 ), _checkSum( 0 ), _currentProgram( nullptr ), @@ -137,6 +143,7 @@ class GLShader GLShader( const std::string &name, const std::string &mainShaderName, uint32_t vertexAttribsRequired, GLShaderManager *manager ) : _name( name ), _mainShaderName( mainShaderName ), + _useMaterialSystem( false ), _activeMacros( 0 ), _checkSum( 0 ), _currentProgram( nullptr ), @@ -147,6 +154,19 @@ class GLShader { } + GLShader( const std::string& name, const std::string& mainShaderName, const bool useMaterialSystem, uint32_t vertexAttribsRequired, GLShaderManager* manager ) : + _name( name ), + _mainShaderName( mainShaderName ), + _useMaterialSystem( useMaterialSystem ), + _activeMacros( 0 ), + _checkSum( 0 ), + _currentProgram( nullptr ), + _vertexAttribsRequired( vertexAttribsRequired ), + _vertexAttribs( 0 ), + _shaderManager( manager ), + _uniformStorageSize( 0 ) { + } + public: virtual ~GLShader() { @@ -186,10 +206,7 @@ class GLShader } } - void RegisterUniform( GLUniform *uniform ) - { - _uniforms.push_back( uniform ); - } + void RegisterUniform( GLUniform* uniform ); void RegisterUniformBlock( GLUniformBlock *uniformBlock ) { @@ -229,6 +246,7 @@ class GLShader } protected: + void PostProcessUniforms(); bool GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut ) const; virtual void BuildShaderVertexLibNames( std::string& /*vertexInlines*/ ) { }; virtual void BuildShaderFragmentLibNames( std::string& /*vertexInlines*/ ) { }; @@ -236,6 +254,7 @@ class GLShader virtual void SetShaderProgramUniforms( shaderProgram_t* /*shaderProgram*/ ) { }; int SelectProgram(); public: + shaderProgram_t* GetProgram( int deformIndex ); void BindProgram( int deformIndex ); void SetRequiredVertexPointers(); @@ -268,6 +287,24 @@ class GLShader { _vertexAttribs &= ~bit; } + + uint GetPadding() const { + return padding; + } + + GLuint GetSTD430Size() const { + return std430Size; + } + + uint GetTextureCount() const { + return textureCount; + } + + bool UseMaterialSystem() const { + return _useMaterialSystem; + } + + void WriteUniformsToBuffer( uint32_t* buffer ); }; class GLShaderManager @@ -324,6 +361,7 @@ class GLShaderManager const std::string &compileMacros ); void CompileAndLinkGPUShaderProgram( GLShader *shader, shaderProgram_t *program, Str::StringRef compileMacros, int deformIndex ); + std::string ShaderPostProcess( GLShader *shader, const std::string& shaderText, const bool isVertexShader ); std::string BuildDeformShaderText( const std::string& steps ); std::string BuildGPUShaderText( Str::StringRef mainShader, Str::StringRef libShaders, GLenum shaderType ) const; void LinkProgram( GLuint program ) const; @@ -339,12 +377,28 @@ class GLUniform protected: GLShader *_shader; std::string _name; + const std::string _type; + const int _components; + + // In multiples of 4 bytes + const GLuint _std430Size; + const GLuint _std430Alignment; + const bool _isTexture = false; + const bool _global = false; // This uniform won't go into materials SSBO if true + size_t _firewallIndex; size_t _locationIndex; - GLUniform( GLShader *shader, const char *name ) : + 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 ) : _shader( shader ), _name( name ), + _type( type ), + _std430Size( std430Size ), + _std430Alignment( std430Alignment ), + _global( global ), + _components( components ), + _isTexture( isTexture ), _firewallIndex( 0 ), _locationIndex( 0 ) { @@ -369,11 +423,38 @@ class GLUniform return _name.c_str(); } + const std::string GetType() const { + return _type; + } + + const int GetComponentSize() const { + return _components; + } + + const GLuint GetSTD430Size() const; + + const GLuint GetSTD430Alignment() const; + + const bool IsTexture() const { + return _isTexture; + } + + const bool IsGlobal() const { + return _global; + } + + const size_t GetFireWallIndex() const { + return _firewallIndex; + } + GLint GetLocation() const { shaderProgram_t* program = _shader->GetProgram(); return program->uniformLocations[_locationIndex]; } + // This should return a pointer to the memory right after the one this uniform wrote to + virtual uint32_t* WriteToBuffer( uint32_t* buffer ); + void UpdateShaderProgramUniformLocation( shaderProgram_t *shaderProgram ) { shaderProgram->uniformLocations[ _locationIndex ] = glGetUniformLocation( shaderProgram->program, GetName() ); @@ -387,14 +468,167 @@ class GLUniform class GLUniformSampler : protected GLUniform { protected: - GLUniformSampler( GLShader* shader, const char* name ) : - GLUniform( shader, name ) { + GLUniformSampler( GLShader* shader, const char* name, const char* type, const GLuint size ) : + GLUniform( shader, name, type, glConfig2.bindlessTexturesAvailable ? size * 2 : size, + glConfig2.bindlessTexturesAvailable ? size * 2 : size, false, 0, true ) { + } + + inline GLint GetLocation() { + shaderProgram_t* p = _shader->GetProgram(); + + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + + return p->uniformLocations[_locationIndex]; + } + + inline size_t GetFirewallIndex() const { + return _firewallIndex; + } + + public: + size_t GetSize() override { + return sizeof( GLuint64 ); + } + + void SetValue( GLuint value ) { + currentValue = value; + } + + void SetValueBindless( GLint64 value ) { + currentValueBindless = value; + + if ( glConfig2.bindlessTexturesAvailable && ( !_shader->UseMaterialSystem() || _global ) ) { + glUniformHandleui64ARB( GetLocation(), currentValueBindless ); + } + } + + GLuint64 GetCurrentValueBindless() const { + return currentValueBindless; + } + + GLuint GetCurrentValue() const { + return currentValue; + } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + uint32_t* bufferNext = buffer; + if ( glConfig2.bindlessTexturesAvailable ) { + memcpy( buffer, ¤tValueBindless, sizeof( GLuint64 ) ); + bufferNext += 2; + } else { + memcpy( buffer, ¤tValue, sizeof( GLint ) ); + bufferNext += 1; + } + return bufferNext; + } + + private: + GLuint64 currentValueBindless = 0; + GLuint currentValue = 0; +}; + +class GLUniformSampler1D : protected GLUniformSampler { + protected: + GLUniformSampler1D( GLShader* shader, const char* name ) : + GLUniformSampler( shader, name, "sampler1D", 1 ) { + } + + inline GLint GetLocation() { + shaderProgram_t* p = _shader->GetProgram(); + + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + + return p->uniformLocations[_locationIndex]; + } + + public: + size_t GetSize() override { + return sizeof( GLuint64 ); + } +}; + +class GLUniformSampler2D : protected GLUniformSampler { + protected: + GLUniformSampler2D( GLShader* shader, const char* name ) : + GLUniformSampler( shader, name, "sampler2D", 1 ) { + } + + inline GLint GetLocation() { + shaderProgram_t* p = _shader->GetProgram(); + + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + + return p->uniformLocations[_locationIndex]; + } + + public: + size_t GetSize() override { + return sizeof( GLuint64 ); + } +}; + +class GLUniformSampler3D : protected GLUniformSampler { + protected: + GLUniformSampler3D( GLShader* shader, const char* name ) : + GLUniformSampler( shader, name, "sampler3D", 1 ) { } inline GLint GetLocation() { shaderProgram_t* p = _shader->GetProgram(); - ASSERT_EQ( p, glState.currentProgram ); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + + return p->uniformLocations[_locationIndex]; + } + + public: + size_t GetSize() override { + return sizeof( GLuint64 ); + } +}; + +class GLUniformUSampler3D : protected GLUniformSampler { + protected: + GLUniformUSampler3D( GLShader* shader, const char* name ) : + GLUniformSampler( shader, name, "usampler3D", 1 ) { + } + + inline GLint GetLocation() { + shaderProgram_t* p = _shader->GetProgram(); + + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + + return p->uniformLocations[_locationIndex]; + } + + public: + size_t GetSize() override { + return sizeof( GLuint64 ); + } +}; + +class GLUniformSamplerCube : protected GLUniformSampler { + protected: + GLUniformSamplerCube( GLShader* shader, const char* name ) : + GLUniformSampler( shader, name, "samplerCube", 1 ) { + } + + inline GLint GetLocation() { + shaderProgram_t* p = _shader->GetProgram(); + + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } return p->uniformLocations[_locationIndex]; } @@ -408,8 +642,8 @@ class GLUniformSampler : protected GLUniform { class GLUniform1i : protected GLUniform { protected: - GLUniform1i( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform1i( GLShader *shader, const char *name, const bool global = false ) : + GLUniform( shader, name, "int", 1, 1, global ) { } @@ -417,7 +651,9 @@ class GLUniform1i : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -426,6 +662,12 @@ class GLUniform1i : protected GLUniform this->GetName(), _shader->GetName().c_str(), value ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + currentValue = value; + return; + } + #if defined( USE_UNIFORM_FIREWALL ) int *firewall = ( int * ) &p->uniformFirewall[ _firewallIndex ]; @@ -443,13 +685,75 @@ class GLUniform1i : protected GLUniform { return sizeof( int ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, ¤tValue, sizeof( int ) ); + uint32_t* bufferNext = buffer + 1; + return bufferNext; + } + + private: + int currentValue = 0; +}; + +class GLUniform1Bool : protected GLUniform { + protected: + // GLSL std430 bool is always 4 bytes, which might not correspond to C++ bool + GLUniform1Bool( GLShader* shader, const char* name ) : + GLUniform( shader, name, "bool", 1, 1, false ) { + } + + inline void SetValue( int value ) { + 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_SetUniform1i( %s, shader: %s, value: %d ) ---\n", + this->GetName(), _shader->GetName().c_str(), value ) ); + } +#endif + + if ( _shader->UseMaterialSystem() && !_global ) { + currentValue = value; + return; + } + +#if defined( USE_UNIFORM_FIREWALL ) + int* firewall = ( int* ) &p->uniformFirewall[_firewallIndex]; + + if ( *firewall == value ) { + return; + } + + *firewall = value; +#endif + glUniform1i( p->uniformLocations[_locationIndex], value ); + } + + public: + size_t GetSize() override { + return sizeof( int ); + } + + uint32_t* WriteToBuffer( uint32_t *buffer ) override { + memcpy( buffer, ¤tValue, sizeof( bool ) ); + uint32_t* bufferNext = buffer + 1; + return bufferNext; + } + + private: + int currentValue = 0; }; class GLUniform1f : protected GLUniform { protected: GLUniform1f( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform( shader, name, "float", 1, 1, false ) { } @@ -457,7 +761,9 @@ class GLUniform1f : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -466,6 +772,12 @@ class GLUniform1f : protected GLUniform this->GetName(), _shader->GetName().c_str(), value ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + currentValue = value; + return; + } + #if defined( USE_UNIFORM_FIREWALL ) float *firewall = ( float * ) &p->uniformFirewall[ _firewallIndex ]; @@ -483,21 +795,33 @@ class GLUniform1f : protected GLUniform { return sizeof( float ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, ¤tValue, sizeof( float ) ); + uint32_t* bufferNext = buffer + 1; + return bufferNext; + } + + private: + float currentValue = 0; }; class GLUniform1fv : protected GLUniform { protected: - GLUniform1fv( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform1fv( GLShader *shader, const char *name, const int size ) : + GLUniform( shader, name, "float", 1, 1, false, size ) { + currentValue.reserve( size ); } inline void SetValue( int numFloats, float *f ) { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -506,15 +830,30 @@ class GLUniform1fv : protected GLUniform this->GetName(), _shader->GetName().c_str(), numFloats ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + memcpy( currentValue.data(), f, numFloats * sizeof( float ) ); + return; + } + glUniform1fv( p->uniformLocations[ _locationIndex ], numFloats, f ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, currentValue.data(), currentValue.size() * sizeof( float ) ); + uint32_t* bufferNext = buffer + _components; + return bufferNext; + } + + private: + std::vector currentValue; }; class GLUniform2f : protected GLUniform { protected: GLUniform2f( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform( shader, name, "vec2", 2, 2, false ) { } @@ -522,7 +861,9 @@ class GLUniform2f : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -531,6 +872,12 @@ class GLUniform2f : protected GLUniform this->GetName(), _shader->GetName().c_str(), v[ 0 ], v[ 1 ] ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + Vector2Copy( v, currentValue ); + return; + } + #if defined( USE_UNIFORM_FIREWALL ) vec2_t *firewall = ( vec2_t * ) &p->uniformFirewall[ _firewallIndex ]; @@ -549,13 +896,22 @@ class GLUniform2f : protected GLUniform { return sizeof( vec2_t ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, ¤tValue, sizeof( vec2_t ) ); + uint32_t* bufferNext = buffer + 2; + return bufferNext; + } + + private: + vec2_t currentValue; }; class GLUniform3f : protected GLUniform { protected: - GLUniform3f( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform3f( GLShader *shader, const char *name, const bool global = false ) : + GLUniform( shader, name, "vec3", 3, 4, global ) { } @@ -563,7 +919,9 @@ class GLUniform3f : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -572,6 +930,12 @@ class GLUniform3f : protected GLUniform this->GetName(), _shader->GetName().c_str(), v[ 0 ], v[ 1 ], v[ 2 ] ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + VectorCopy( v, currentValue ); + return; + } + #if defined( USE_UNIFORM_FIREWALL ) vec3_t *firewall = ( vec3_t * ) &p->uniformFirewall[ _firewallIndex ]; @@ -589,13 +953,22 @@ class GLUniform3f : protected GLUniform { return sizeof( vec3_t ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, ¤tValue, sizeof( vec3_t ) ); + uint32_t* bufferNext = buffer + 4; + return bufferNext; + } + + private: + vec3_t currentValue; }; class GLUniform4f : protected GLUniform { protected: GLUniform4f( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform( shader, name, "vec4", 4, 4, false ) { } @@ -603,7 +976,9 @@ class GLUniform4f : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -612,6 +987,12 @@ class GLUniform4f : protected GLUniform this->GetName(), _shader->GetName().c_str(), v[ 0 ], v[ 1 ], v[ 2 ], v[ 3 ] ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + Vector4Copy( v, currentValue ); + return; + } + #if defined( USE_UNIFORM_FIREWALL ) vec4_t *firewall = ( vec4_t * ) &p->uniformFirewall[ _firewallIndex ]; @@ -629,21 +1010,33 @@ class GLUniform4f : protected GLUniform { return sizeof( vec4_t ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, ¤tValue, sizeof( vec4_t ) ); + uint32_t* bufferNext = buffer + 4; + return bufferNext; + } + + private: + vec4_t currentValue; }; class GLUniform4fv : protected GLUniform { protected: - GLUniform4fv( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniform4fv( GLShader *shader, const char *name, const int size ) : + GLUniform( shader, name, "vec4", 4, 4, false, size ) { + currentValue.reserve( size ); } inline void SetValue( int numV, vec4_t *v ) { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -652,15 +1045,31 @@ class GLUniform4fv : protected GLUniform this->GetName(), _shader->GetName().c_str(), numV ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + memcpy( currentValue.data(), v, numV * sizeof( vec4_t ) ); + return; + } + glUniform4fv( p->uniformLocations[ _locationIndex ], numV, &v[ 0 ][ 0 ] ); } + + public: + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, currentValue.data(), currentValue.size() * sizeof( float ) ); + uint32_t* bufferNext = buffer + 4 * _components; + return bufferNext; + } + + private: + std::vector currentValue; }; class GLUniformMatrix4f : protected GLUniform { protected: - GLUniformMatrix4f( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniformMatrix4f( GLShader *shader, const char *name, const bool global = false ) : + GLUniform( shader, name, "mat4", 16, 4, global ) { } @@ -668,7 +1077,9 @@ class GLUniformMatrix4f : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -679,6 +1090,12 @@ class GLUniformMatrix4f : protected GLUniform m[ 13 ], m[ 14 ], m[ 15 ] ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + MatrixCopy( m, currentValue ); + return; + } + #if defined( USE_UNIFORM_FIREWALL ) matrix_t *firewall = ( matrix_t * ) &p->uniformFirewall[ _firewallIndex ]; @@ -696,21 +1113,33 @@ class GLUniformMatrix4f : protected GLUniform { return sizeof( matrix_t ); } + + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, ¤tValue, sizeof( matrix_t ) ); + uint32_t* bufferNext = buffer + 16; + return bufferNext; + } + + private: + matrix_t currentValue; }; class GLUniformMatrix4fv : protected GLUniform { protected: - GLUniformMatrix4fv( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniformMatrix4fv( GLShader *shader, const char *name, const int size ) : + GLUniform( shader, name, "mat4", 16, 4, false, size ) { + currentValue.reserve( size * 16 ); } inline void SetValue( int numMatrices, GLboolean transpose, const matrix_t *m ) { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) @@ -719,15 +1148,31 @@ class GLUniformMatrix4fv : protected GLUniform this->GetName(), _shader->GetName().c_str(), numMatrices, transpose ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + memcpy( currentValue.data(), m, numMatrices * sizeof( matrix_t ) ); + return; + } + glUniformMatrix4fv( p->uniformLocations[ _locationIndex ], numMatrices, transpose, &m[ 0 ][ 0 ] ); } + + public: + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, currentValue.data(), currentValue.size() * sizeof( float ) ); + uint32_t* bufferNext = buffer + 16 * _components; + return bufferNext; + } + + private: + std::vector currentValue; }; class GLUniformMatrix34fv : protected GLUniform { protected: - GLUniformMatrix34fv( GLShader *shader, const char *name ) : - GLUniform( shader, name ) + GLUniformMatrix34fv( GLShader *shader, const char *name, const int size ) : + GLUniform( shader, name, "mat3x4", 12, 4, false, size ) { } @@ -735,7 +1180,10 @@ class GLUniformMatrix34fv : protected GLUniform { shaderProgram_t *p = _shader->GetProgram(); - ASSERT_EQ(p, glState.currentProgram); + if ( _global || !_shader->UseMaterialSystem() ) { + ASSERT_EQ( p, glState.currentProgram ); + } + #if defined( LOG_GLSL_UNIFORMS ) if ( r_logFile->integer ) { @@ -743,8 +1191,24 @@ class GLUniformMatrix34fv : protected GLUniform this->GetName(), _shader->GetName().c_str(), numMatrices, transpose ) ); } #endif + + if ( _shader->UseMaterialSystem() && !_global ) { + memcpy( currentValue.data(), m, numMatrices * sizeof( matrix_t ) ); + return; + } + glUniformMatrix3x4fv( p->uniformLocations[ _locationIndex ], numMatrices, transpose, m ); } + + public: + uint32_t* WriteToBuffer( uint32_t* buffer ) override { + memcpy( buffer, currentValue.data(), currentValue.size() * sizeof( float ) ); + uint32_t* bufferNext = buffer + 16 * _components; + return bufferNext; + } + + private: + std::vector currentValue; }; class GLUniformBlock @@ -790,6 +1254,119 @@ class GLUniformBlock } }; +class GLSSBO { + public: + std::string _name; + const GLuint _bindingPoint; + + GLSSBO( const char* name, const GLuint bindingPoint ) : + _name( name ), + _bindingPoint( bindingPoint ) { + } + + public: + const char* GetName() { + return _name.c_str(); + } + + void BindBufferBase() { + glBindBufferBase( GL_SHADER_STORAGE_BUFFER, _bindingPoint, handle ); + } + + void BindBuffer() { + glBindBuffer( GL_SHADER_STORAGE_BUFFER, handle ); + } + + uint32_t* MapBufferRange( const GLuint count ) { + if ( !mapped ) { + mapped = true; + data = ( uint32_t* ) glMapBufferRange( GL_SHADER_STORAGE_BUFFER, + 0, count * sizeof( uint32_t ), + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ); + } + + return data; + } + + uint32_t* MapBufferRange( const GLuint offset, const GLuint count ) { + if ( !mapped ) { + mapped = true; + data = ( uint32_t* ) glMapBufferRange( GL_SHADER_STORAGE_BUFFER, + offset * sizeof( uint32_t ), count * sizeof( uint32_t ), + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT ); + } + + return data; + } + + void UnmapBuffer() { + mapped = false; + glUnmapBuffer( GL_SHADER_STORAGE_BUFFER ); + } + + void GenBuffer() { + glGenBuffers( 1, &handle ); + } + + void DelBuffer() { + glDeleteBuffers( 1, &handle ); + } + + private: + GLuint handle; + bool mapped = false; + uint32_t* data; +}; + +class GLIndirectBuffer { + public: + + struct GLIndirectCommand { + GLuint count; + GLuint instanceCount; + GLuint firstIndex; + GLint baseVertex; + GLuint baseInstance; + }; + + std::string _name; + + GLIndirectBuffer( const char* name ) : + _name( name ) { + } + + public: + + const char* GetName() { + return _name.c_str(); + } + + void BindBuffer() { + glBindBuffer( GL_DRAW_INDIRECT_BUFFER, handle ); + } + + GLIndirectCommand* MapBufferRange( const GLuint count ) { + return (GLIndirectCommand*) glMapBufferRange( GL_DRAW_INDIRECT_BUFFER, + 0, count * sizeof( GLIndirectCommand ), + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ); + } + + void UnmapBuffer() const { + glUnmapBuffer( GL_DRAW_INDIRECT_BUFFER ); + } + + void GenBuffer() { + glGenBuffers( 1, &handle ); + } + + void DelBuffer() { + glDeleteBuffers( 1, &handle ); + } + + private: + GLuint handle; +}; + class GLCompileMacro { private: @@ -1362,10 +1939,14 @@ class u_InverseLightFactor : }; class u_ColorMap : - GLUniformSampler { + GLUniformSampler2D { public: u_ColorMap( GLShader* shader ) : - GLUniformSampler( shader, "u_ColorMap" ) { + GLUniformSampler2D( shader, "u_ColorMap" ) { + } + + void SetUniform_ColorMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ColorMap() { @@ -1373,11 +1954,47 @@ class u_ColorMap : } }; +class u_ColorMap3D : + GLUniformSampler3D { + public: + u_ColorMap3D( GLShader* shader ) : + GLUniformSampler3D( shader, "u_ColorMap3D" ) { + } + + void SetUniform_ColorMap3DBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); + } + + GLint GetUniformLocation_ColorMap3D() { + return this->GetLocation(); + } +}; + +class u_ColorMapCube : + GLUniformSamplerCube { + public: + u_ColorMapCube( GLShader* shader ) : + GLUniformSamplerCube( shader, "u_ColorMapCube" ) { + } + + void SetUniform_ColorMapCubeBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); + } + + GLint GetUniformLocation_ColorMapCube() { + return this->GetLocation(); + } +}; + class u_DepthMap : - GLUniformSampler { + GLUniformSampler2D { public: u_DepthMap( GLShader* shader ) : - GLUniformSampler( shader, "u_DepthMap" ) { + GLUniformSampler2D( shader, "u_DepthMap" ) { + } + + void SetUniform_DepthMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_DepthMap() { @@ -1386,10 +2003,14 @@ class u_DepthMap : }; class u_DiffuseMap : - GLUniformSampler { + GLUniformSampler2D { public: u_DiffuseMap( GLShader* shader ) : - GLUniformSampler( shader, "u_DiffuseMap" ) { + GLUniformSampler2D( shader, "u_DiffuseMap" ) { + } + + void SetUniform_DiffuseMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_DiffuseMap() { @@ -1398,10 +2019,14 @@ class u_DiffuseMap : }; class u_HeightMap : - GLUniformSampler { + GLUniformSampler2D { public: u_HeightMap( GLShader* shader ) : - GLUniformSampler( shader, "u_HeightMap" ) { + GLUniformSampler2D( shader, "u_HeightMap" ) { + } + + void SetUniform_HeightMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_HeightMap() { @@ -1410,10 +2035,14 @@ class u_HeightMap : }; class u_NormalMap : - GLUniformSampler { + GLUniformSampler2D { public: u_NormalMap( GLShader* shader ) : - GLUniformSampler( shader, "u_NormalMap" ) { + GLUniformSampler2D( shader, "u_NormalMap" ) { + } + + void SetUniform_NormalMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_NormalMap() { @@ -1422,10 +2051,14 @@ class u_NormalMap : }; class u_MaterialMap : - GLUniformSampler { + GLUniformSampler2D { public: u_MaterialMap( GLShader* shader ) : - GLUniformSampler( shader, "u_MaterialMap" ) { + GLUniformSampler2D( shader, "u_MaterialMap" ) { + } + + void SetUniform_MaterialMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_MaterialMap() { @@ -1437,7 +2070,11 @@ class u_LightMap : GLUniformSampler { public: u_LightMap( GLShader* shader ) : - GLUniformSampler( shader, "u_LightMap" ) { + GLUniformSampler( shader, "u_LightMap", "sampler2D", 1 ) { + } + + void SetUniform_LightMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_LightMap() { @@ -1449,7 +2086,11 @@ class u_DeluxeMap : GLUniformSampler { public: u_DeluxeMap( GLShader* shader ) : - GLUniformSampler( shader, "u_DeluxeMap" ) { + GLUniformSampler( shader, "u_DeluxeMap", "sampler2D", 1 ) { + } + + void SetUniform_DeluxeMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_DeluxeMap() { @@ -1458,10 +2099,14 @@ class u_DeluxeMap : }; class u_GlowMap : - GLUniformSampler { + GLUniformSampler2D { public: u_GlowMap( GLShader* shader ) : - GLUniformSampler( shader, "u_GlowMap" ) { + GLUniformSampler2D( shader, "u_GlowMap" ) { + } + + void SetUniform_GlowMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_GlowMap() { @@ -1470,10 +2115,14 @@ class u_GlowMap : }; class u_RandomMap : - GLUniformSampler { + GLUniformSampler2D { public: u_RandomMap( GLShader* shader ) : - GLUniformSampler( shader, "u_RandomMap" ) { + GLUniformSampler2D( shader, "u_RandomMap" ) { + } + + void SetUniform_RandomMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_RandomMap() { @@ -1482,10 +2131,14 @@ class u_RandomMap : }; class u_PortalMap : - GLUniformSampler { + GLUniformSampler2D { public: u_PortalMap( GLShader* shader ) : - GLUniformSampler( shader, "u_PortalMap" ) { + GLUniformSampler2D( shader, "u_PortalMap" ) { + } + + void SetUniform_PortalMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_PortalMap() { @@ -1494,10 +2147,14 @@ class u_PortalMap : }; class u_CloudMap : - GLUniformSampler { + GLUniformSampler2D { public: u_CloudMap( GLShader* shader ) : - GLUniformSampler( shader, "u_CloudMap" ) { + GLUniformSampler2D( shader, "u_CloudMap" ) { + } + + void SetUniform_CloudMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_CloudMap() { @@ -1506,10 +2163,14 @@ class u_CloudMap : }; class u_LightsTexture : - GLUniformSampler { + GLUniformSampler2D { public: u_LightsTexture( GLShader* shader ) : - GLUniformSampler( shader, "u_Lights" ) { + GLUniformSampler2D( shader, "u_LightsTexture" ) { + } + + void SetUniform_LightsTextureBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_LightsTexture() { @@ -1518,10 +2179,14 @@ class u_LightsTexture : }; class u_LightTiles : - GLUniformSampler { + GLUniformSampler3D { public: u_LightTiles( GLShader* shader ) : - GLUniformSampler( shader, "u_LightTiles" ) { + GLUniformSampler3D( shader, "u_LightTiles" ) { + } + + void SetUniform_LightTilesBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_LightTiles() { @@ -1529,11 +2194,31 @@ class u_LightTiles : } }; +class u_LightTilesInt : + GLUniformUSampler3D { + public: + u_LightTilesInt( GLShader* shader ) : + GLUniformUSampler3D( shader, "u_LightTilesInt" ) { + } + + void SetUniform_LightTilesIntBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); + } + + GLint GetUniformLocation_LightTilesInt() { + return this->GetLocation(); + } +}; + class u_LightGrid1 : - GLUniformSampler { + GLUniformSampler3D { public: u_LightGrid1( GLShader* shader ) : - GLUniformSampler( shader, "u_LightGrid1" ) { + GLUniformSampler3D( shader, "u_LightGrid1" ) { + } + + void SetUniform_LightGrid1Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_LightGrid1() { @@ -1542,10 +2227,14 @@ class u_LightGrid1 : }; class u_LightGrid2 : - GLUniformSampler { + GLUniformSampler3D { public: u_LightGrid2( GLShader* shader ) : - GLUniformSampler( shader, "u_LightGrid2" ) { + GLUniformSampler3D( shader, "u_LightGrid2" ) { + } + + void SetUniform_LightGrid2Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_LightGrid2() { @@ -1554,10 +2243,14 @@ class u_LightGrid2 : }; class u_EnvironmentMap0 : - GLUniformSampler { + GLUniformSamplerCube { public: u_EnvironmentMap0( GLShader* shader ) : - GLUniformSampler( shader, "u_EnvironmentMap0" ) { + GLUniformSamplerCube( shader, "u_EnvironmentMap0" ) { + } + + void SetUniform_EnvironmentMap0Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_EnvironmentMap0() { @@ -1566,10 +2259,14 @@ class u_EnvironmentMap0 : }; class u_EnvironmentMap1 : - GLUniformSampler { + GLUniformSamplerCube { public: u_EnvironmentMap1( GLShader* shader ) : - GLUniformSampler( shader, "u_EnvironmentMap1" ) { + GLUniformSamplerCube( shader, "u_EnvironmentMap1" ) { + } + + void SetUniform_EnvironmentMap1Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_EnvironmentMap1() { @@ -1578,10 +2275,14 @@ class u_EnvironmentMap1 : }; class u_CurrentMap : - GLUniformSampler { + GLUniformSampler2D { public: u_CurrentMap( GLShader* shader ) : - GLUniformSampler( shader, "u_CurrentMap" ) { + GLUniformSampler2D( shader, "u_CurrentMap" ) { + } + + void SetUniform_CurrentMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_CurrentMap() { @@ -1590,10 +2291,14 @@ class u_CurrentMap : }; class u_AttenuationMapXY : - GLUniformSampler { + GLUniformSampler2D { public: u_AttenuationMapXY( GLShader* shader ) : - GLUniformSampler( shader, "u_AttenuationMapXY" ) { + GLUniformSampler2D( shader, "u_AttenuationMapXY" ) { + } + + void SetUniform_AttenuationMapXYBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_AttenuationMapXY() { @@ -1602,10 +2307,14 @@ class u_AttenuationMapXY : }; class u_AttenuationMapZ : - GLUniformSampler { + GLUniformSampler2D { public: u_AttenuationMapZ( GLShader* shader ) : - GLUniformSampler( shader, "u_AttenuationMapZ" ) { + GLUniformSampler2D( shader, "u_AttenuationMapZ" ) { + } + + void SetUniform_AttenuationMapZBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_AttenuationMapZ() { @@ -1614,10 +2323,14 @@ class u_AttenuationMapZ : }; class u_ShadowMap : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowMap( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowMap" ) { + GLUniformSampler2D( shader, "u_ShadowMap" ) { + } + + void SetUniform_ShadowMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowMap() { @@ -1626,10 +2339,14 @@ class u_ShadowMap : }; class u_ShadowMap0 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowMap0( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowMap0" ) { + GLUniformSampler2D( shader, "u_ShadowMap0" ) { + } + + void SetUniform_ShadowMap0Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowMap0() { @@ -1638,10 +2355,14 @@ class u_ShadowMap0 : }; class u_ShadowMap1 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowMap1( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowMap1" ) { + GLUniformSampler2D( shader, "u_ShadowMap1" ) { + } + + void SetUniform_ShadowMap1Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowMap1() { @@ -1650,10 +2371,14 @@ class u_ShadowMap1 : }; class u_ShadowMap2 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowMap2( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowMap2" ) { + GLUniformSampler2D( shader, "u_ShadowMap2" ) { + } + + void SetUniform_ShadowMap2Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowMap2() { @@ -1662,10 +2387,14 @@ class u_ShadowMap2 : }; class u_ShadowMap3 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowMap3( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowMap3" ) { + GLUniformSampler2D( shader, "u_ShadowMap3" ) { + } + + void SetUniform_ShadowMap3Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowMap3() { @@ -1674,10 +2403,14 @@ class u_ShadowMap3 : }; class u_ShadowMap4 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowMap4( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowMap4" ) { + GLUniformSampler2D( shader, "u_ShadowMap4" ) { + } + + void SetUniform_ShadowMap4Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowMap4() { @@ -1686,10 +2419,14 @@ class u_ShadowMap4 : }; class u_ShadowClipMap : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowClipMap( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowClipMap" ) { + GLUniformSampler2D( shader, "u_ShadowClipMap" ) { + } + + void SetUniform_ShadowClipMapBindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowClipMap() { @@ -1698,10 +2435,14 @@ class u_ShadowClipMap : }; class u_ShadowClipMap0 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowClipMap0( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowClipMap0" ) { + GLUniformSampler2D( shader, "u_ShadowClipMap0" ) { + } + + void SetUniform_ShadowClipMap0Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowClipMap0() { @@ -1710,10 +2451,14 @@ class u_ShadowClipMap0 : }; class u_ShadowClipMap1 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowClipMap1( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowClipMap1" ) { + GLUniformSampler2D( shader, "u_ShadowClipMap1" ) { + } + + void SetUniform_ShadowClipMap1Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowClipMap1() { @@ -1722,10 +2467,14 @@ class u_ShadowClipMap1 : }; class u_ShadowClipMap2 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowClipMap2( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowClipMap2" ) { + GLUniformSampler2D( shader, "u_ShadowClipMap2" ) { + } + + void SetUniform_ShadowClipMap2Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowClipMap2() { @@ -1734,10 +2483,14 @@ class u_ShadowClipMap2 : }; class u_ShadowClipMap3 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowClipMap3( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowClipMap3" ) { + GLUniformSampler2D( shader, "u_ShadowClipMap3" ) { + } + + void SetUniform_ShadowClipMap3Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowClipMap3() { @@ -1746,10 +2499,14 @@ class u_ShadowClipMap3 : }; class u_ShadowClipMap4 : - GLUniformSampler { + GLUniformSampler2D { public: u_ShadowClipMap4( GLShader* shader ) : - GLUniformSampler( shader, "u_ShadowClipMap4" ) { + GLUniformSampler2D( shader, "u_ShadowClipMap4" ) { + } + + void SetUniform_ShadowClipMap4Bindless( GLuint64 bindlessHandle ) { + this->SetValueBindless( bindlessHandle ); } GLint GetUniformLocation_ShadowClipMap4() { @@ -1835,7 +2592,7 @@ class u_ViewOrigin : { public: u_ViewOrigin( GLShader *shader ) : - GLUniform3f( shader, "u_ViewOrigin" ) + GLUniform3f( shader, "u_ViewOrigin", true ) { } @@ -1850,7 +2607,7 @@ class u_ViewUp : { public: u_ViewUp( GLShader *shader ) : - GLUniform3f( shader, "u_ViewUp" ) + GLUniform3f( shader, "u_ViewUp", true ) { } @@ -1955,7 +2712,7 @@ class u_LightFrustum : { public: u_LightFrustum( GLShader *shader ) : - GLUniform4fv( shader, "u_LightFrustum" ) + GLUniform4fv( shader, "u_LightFrustum", 6 ) { } @@ -2000,7 +2757,7 @@ class u_ShadowMatrix : { public: u_ShadowMatrix( GLShader *shader ) : - GLUniformMatrix4fv( shader, "u_ShadowMatrix" ) + GLUniformMatrix4fv( shader, "u_ShadowMatrix", MAX_SHADOWMAPS ) { } @@ -2164,7 +2921,7 @@ class u_ModelMatrix : { public: u_ModelMatrix( GLShader *shader ) : - GLUniformMatrix4f( shader, "u_ModelMatrix" ) + GLUniformMatrix4f( shader, "u_ModelMatrix", true ) { } @@ -2239,7 +2996,7 @@ class u_ModelViewProjectionMatrix : { public: u_ModelViewProjectionMatrix( GLShader *shader ) : - GLUniformMatrix4f( shader, "u_ModelViewProjectionMatrix" ) + GLUniformMatrix4f( shader, "u_ModelViewProjectionMatrix", true ) { } @@ -2265,10 +3022,10 @@ class u_UnprojectMatrix : }; class u_UseCloudMap : - GLUniform1i { + GLUniform1Bool { public: u_UseCloudMap( GLShader* shader ) : - GLUniform1i( shader, "u_UseCloudMap" ) { + GLUniform1Bool( shader, "u_UseCloudMap" ) { } void SetUniform_UseCloudMap( const bool useCloudMap ) { @@ -2281,7 +3038,7 @@ class u_Bones : { public: u_Bones( GLShader *shader ) : - GLUniform4fv( shader, "u_Bones" ) + GLUniform4fv( shader, "u_Bones", MAX_BONES * 0 + 1 ) { } @@ -2605,7 +3362,7 @@ class u_LightGridOrigin : { public: u_LightGridOrigin( GLShader *shader ) : - GLUniform3f( shader, "u_LightGridOrigin" ) + GLUniform3f( shader, "u_LightGridOrigin", true ) { } @@ -2620,7 +3377,7 @@ class u_LightGridScale : { public: u_LightGridScale( GLShader *shader ) : - GLUniform3f( shader, "u_LightGridScale" ) + GLUniform3f( shader, "u_LightGridScale", true ) { } @@ -2650,7 +3407,7 @@ class u_numLights : { public: u_numLights( GLShader *shader ) : - GLUniform1i( shader, "u_numLights" ) + GLUniform1i( shader, "u_numLights", true ) { } @@ -2698,7 +3455,6 @@ class GLShader_generic2D : public GLShader, public u_ColorMap, public u_DepthMap, - public u_EnvironmentMap1, public u_TextureMatrix, public u_AlphaThreshold, public u_ModelMatrix, @@ -2721,13 +3477,11 @@ class GLShader_generic : public GLShader, public u_ColorMap, public u_DepthMap, - public u_EnvironmentMap1, public u_TextureMatrix, public u_ViewOrigin, public u_ViewUp, public u_AlphaThreshold, public u_ModelMatrix, - public u_ProjectionMatrixTranspose, public u_ModelViewProjectionMatrix, public u_InverseLightFactor, public u_ColorModulate, @@ -2750,6 +3504,36 @@ class GLShader_generic : void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; }; +class GLShader_genericMaterial : + public GLShader, + public u_ColorMap, + public u_DepthMap, + public u_TextureMatrix, + public u_ViewOrigin, + public u_ViewUp, + public u_AlphaThreshold, + public u_ModelMatrix, + public u_ModelViewProjectionMatrix, + public u_InverseLightFactor, + public u_ColorModulate, + public u_Color, + // public u_Bones, + public u_VertexInterpolation, + public u_DepthScale, + public GLDeformStage, + // public GLCompileMacro_USE_VERTEX_SKINNING, + public GLCompileMacro_USE_VERTEX_ANIMATION, + public GLCompileMacro_USE_VERTEX_SPRITE, + public GLCompileMacro_USE_TCGEN_ENVIRONMENT, + public GLCompileMacro_USE_TCGEN_LIGHTMAP, + public GLCompileMacro_USE_DEPTH_FADE, + public GLCompileMacro_USE_ALPHA_TESTING { + public: + GLShader_genericMaterial( GLShaderManager* manager ); + void BuildShaderVertexLibNames( std::string& vertexInlines ) override; + void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; +}; + class GLShader_lightMapping : public GLShader, public u_DiffuseMap, @@ -2761,7 +3545,10 @@ class GLShader_lightMapping : public u_GlowMap, public u_EnvironmentMap0, public u_EnvironmentMap1, + public u_LightGrid1, + public u_LightGrid2, public u_LightTiles, + public u_LightTilesInt, public u_LightsTexture, public u_TextureMatrix, public u_SpecularExponent, @@ -2802,6 +3589,58 @@ class GLShader_lightMapping : void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; }; +class GLShader_lightMappingMaterial : + public GLShader, + public u_DiffuseMap, + public u_NormalMap, + public u_HeightMap, + public u_MaterialMap, + public u_LightMap, + public u_DeluxeMap, + public u_GlowMap, + public u_EnvironmentMap0, + public u_EnvironmentMap1, + public u_LightGrid1, + public u_LightGrid2, + public u_LightTilesInt, + public u_TextureMatrix, + public u_SpecularExponent, + public u_ColorModulate, + public u_Color, + public u_AlphaThreshold, + public u_ViewOrigin, + public u_ModelMatrix, + public u_ModelViewProjectionMatrix, + public u_InverseLightFactor, + // public u_Bones, + public u_VertexInterpolation, + public u_ReliefDepthScale, + public u_ReliefOffsetBias, + public u_NormalScale, + public u_EnvironmentInterpolation, + public u_LightGridOrigin, + public u_LightGridScale, + public u_numLights, + public u_Lights, + public GLDeformStage, + public GLCompileMacro_USE_BSP_SURFACE, + // public GLCompileMacro_USE_VERTEX_SKINNING, + public GLCompileMacro_USE_VERTEX_ANIMATION, + public GLCompileMacro_USE_DELUXE_MAPPING, + public GLCompileMacro_USE_GRID_LIGHTING, + public GLCompileMacro_USE_GRID_DELUXE_MAPPING, + public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, + public GLCompileMacro_USE_RELIEF_MAPPING, + public GLCompileMacro_USE_REFLECTIVE_SPECULAR, + public GLCompileMacro_USE_PHYSICAL_MAPPING { + public: + GLShader_lightMappingMaterial( GLShaderManager* manager ); + void BuildShaderVertexLibNames( std::string& vertexInlines ) override; + void BuildShaderFragmentLibNames( std::string& fragmentInlines ) override; + void BuildShaderCompileMacros( std::string& compileMacros ) override; + void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; +}; + class GLShader_forwardLighting_omniXYZ : public GLShader, public u_DiffuseMap, @@ -3003,7 +3842,7 @@ class GLShader_reflection : class GLShader_skybox : public GLShader, - public u_ColorMap, + public u_ColorMapCube, public u_CloudMap, public u_TextureMatrix, public u_ViewOrigin, @@ -3127,7 +3966,7 @@ class GLShader_contrast : class GLShader_cameraEffects : public GLShader, - public u_ColorMap, + public u_ColorMap3D, public u_CurrentMap, public u_ColorModulate, public u_TextureMatrix, @@ -3286,10 +4125,12 @@ extern ShaderKind shaderKind; extern GLShader_generic2D *gl_generic2DShader; extern GLShader_generic *gl_genericShader; +extern GLShader_genericMaterial *gl_genericShaderMaterial; extern GLShader_lightMapping *gl_lightMappingShader; +extern GLShader_lightMappingMaterial *gl_lightMappingShaderMaterial; extern GLShader_forwardLighting_omniXYZ *gl_forwardLightingShader_omniXYZ; extern GLShader_forwardLighting_projXYZ *gl_forwardLightingShader_projXYZ; -extern GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun; +extern GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun; extern GLShader_shadowFill *gl_shadowFillShader; extern GLShader_reflection *gl_reflectionShader; extern GLShader_skybox *gl_skyboxShader; diff --git a/src/engine/renderer/glsl_source/blurX_vp.glsl b/src/engine/renderer/glsl_source/blurX_vp.glsl index c36656fd4f..f6e8b8fbcf 100644 --- a/src/engine/renderer/glsl_source/blurX_vp.glsl +++ b/src/engine/renderer/glsl_source/blurX_vp.glsl @@ -30,4 +30,6 @@ void main() { // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/blurY_vp.glsl b/src/engine/renderer/glsl_source/blurY_vp.glsl index 939b4859e5..428c40273b 100644 --- a/src/engine/renderer/glsl_source/blurY_vp.glsl +++ b/src/engine/renderer/glsl_source/blurY_vp.glsl @@ -30,4 +30,6 @@ void main() { // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/cameraEffects_fp.glsl b/src/engine/renderer/glsl_source/cameraEffects_fp.glsl index 1659bc2b1b..74cfa0789c 100644 --- a/src/engine/renderer/glsl_source/cameraEffects_fp.glsl +++ b/src/engine/renderer/glsl_source/cameraEffects_fp.glsl @@ -23,9 +23,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* cameraEffects_fp.glsl */ uniform sampler2D u_CurrentMap; -uniform sampler3D u_ColorMap; +uniform sampler3D u_ColorMap3D; uniform float u_LightFactor; + uniform vec4 u_ColorModulate; uniform float u_InverseGamma; @@ -47,10 +48,10 @@ void main() // apply color grading vec3 colCoord = color.rgb * 15.0 / 16.0 + 0.5 / 16.0; colCoord.z *= 0.25; - color.rgb = u_ColorModulate.x * texture3D(u_ColorMap, colCoord).rgb; - color.rgb += u_ColorModulate.y * texture3D(u_ColorMap, colCoord + vec3(0.0, 0.0, 0.25)).rgb; - color.rgb += u_ColorModulate.z * texture3D(u_ColorMap, colCoord + vec3(0.0, 0.0, 0.50)).rgb; - color.rgb += u_ColorModulate.w * texture3D(u_ColorMap, colCoord + vec3(0.0, 0.0, 0.75)).rgb; + color.rgb = u_ColorModulate.x * texture3D(u_ColorMap3D, colCoord).rgb; + color.rgb += u_ColorModulate.y * texture3D(u_ColorMap3D, colCoord + vec3(0.0, 0.0, 0.25)).rgb; + color.rgb += u_ColorModulate.z * texture3D(u_ColorMap3D, colCoord + vec3(0.0, 0.0, 0.50)).rgb; + color.rgb += u_ColorModulate.w * texture3D(u_ColorMap3D, colCoord + vec3(0.0, 0.0, 0.75)).rgb; color.xyz = pow(color.xyz, vec3(u_InverseGamma)); diff --git a/src/engine/renderer/glsl_source/cameraEffects_vp.glsl b/src/engine/renderer/glsl_source/cameraEffects_vp.glsl index 2ba54052a1..4358adfb8f 100644 --- a/src/engine/renderer/glsl_source/cameraEffects_vp.glsl +++ b/src/engine/renderer/glsl_source/cameraEffects_vp.glsl @@ -36,4 +36,6 @@ void main() gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); var_TexCoords = (u_TextureMatrix * vec4(attr_TexCoord0, 0.0, 1.0)).st; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/commandQueue_vp.glsl b/src/engine/renderer/glsl_source/commandQueue_vp.glsl new file mode 100644 index 0000000000..e77ec87bb0 --- /dev/null +++ b/src/engine/renderer/glsl_source/commandQueue_vp.glsl @@ -0,0 +1,9 @@ +#ifdef HAVE_ARB_shader_draw_parameters +#define SETUP_SHADER_PARMS SetShaderParameters(); +void SetShaderParameters() { + in_drawID = drawID; + in_baseInstance = baseInstance; +} +#else +#define SETUP_SHADER_PARMS //Unavailable +#endif diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index e103197f24..7ea6900dce 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -47,7 +47,7 @@ layout(std140) uniform u_Lights { }; #define GetLight(idx, component) lights[idx].component #else // !HAVE_ARB_uniform_buffer_object -uniform sampler2D u_Lights; +uniform sampler2D u_LightsTexture; #define idxToTC( idx, w, h ) vec2( floor( ( idx * ( 1.0 / w ) ) + 0.5 ) * ( 1.0 / h ), \ fract( ( idx + 0.5 ) * (1.0 / w ) ) ) const struct GetLightOffsets { @@ -55,7 +55,7 @@ const struct GetLightOffsets { int color_type; int direction_angle; } getLightOffsets = GetLightOffsets(0, 1, 2); -#define GetLight(idx, component) texture2D( u_Lights, idxToTC(3 * idx + getLightOffsets.component, 64.0, float( 3 * MAX_REF_LIGHTS / 64 ) ) ) +#define GetLight(idx, component) texture2D( u_LightsTexture, idxToTC(3 * idx + getLightOffsets.component, 64.0, float( 3 * MAX_REF_LIGHTS / 64 ) ) ) #endif // HAVE_ARB_uniform_buffer_object uniform int u_numLights; @@ -148,10 +148,10 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol #if defined(TEXTURE_INTEGER) const int lightsPerLayer = 16; -uniform usampler3D u_LightTiles; +uniform usampler3D u_LightTilesInt; #define idxs_t uvec4 idxs_t fetchIdxs( in vec3 coords ) { - return texture3D( u_LightTiles, coords ); + return texture3D( u_LightTilesInt, coords ); } int nextIdx( inout idxs_t idxs ) { uvec4 tmp = ( idxs & uvec4( 3 ) ) * uvec4( 0x40, 0x10, 0x04, 0x01 ); diff --git a/src/engine/renderer/glsl_source/contrast_vp.glsl b/src/engine/renderer/glsl_source/contrast_vp.glsl index 93d4c5ac8d..31d0a31149 100644 --- a/src/engine/renderer/glsl_source/contrast_vp.glsl +++ b/src/engine/renderer/glsl_source/contrast_vp.glsl @@ -30,4 +30,6 @@ void main() { // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl b/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl index 211ac3bc53..7e1fc4b9d7 100644 --- a/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl +++ b/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl @@ -35,4 +35,6 @@ void main() gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); var_TexCoord = attr_TexCoord0.st; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/depthtile1_vp.glsl b/src/engine/renderer/glsl_source/depthtile1_vp.glsl index 5368af5968..03efb6ae8a 100644 --- a/src/engine/renderer/glsl_source/depthtile1_vp.glsl +++ b/src/engine/renderer/glsl_source/depthtile1_vp.glsl @@ -47,4 +47,6 @@ void main() unprojectionParams.z = 2.0 * u_zFar.z - r_zNear; gl_Position = u_ModelViewProjectionMatrix * vec4( attr_Position, 1.0f ); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/depthtile2_vp.glsl b/src/engine/renderer/glsl_source/depthtile2_vp.glsl index a6146f4185..e758872147 100644 --- a/src/engine/renderer/glsl_source/depthtile2_vp.glsl +++ b/src/engine/renderer/glsl_source/depthtile2_vp.glsl @@ -41,4 +41,6 @@ uniform mat4 u_ModelViewProjectionMatrix; void main() { gl_Position = u_ModelViewProjectionMatrix * vec4( attr_Position, 1.0f ); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/dispersion_C_vp.glsl b/src/engine/renderer/glsl_source/dispersion_C_vp.glsl index ca3aa4afa2..5d0b72a592 100644 --- a/src/engine/renderer/glsl_source/dispersion_C_vp.glsl +++ b/src/engine/renderer/glsl_source/dispersion_C_vp.glsl @@ -76,5 +76,7 @@ void main() // transform normal into world space var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz; } + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/fogGlobal_vp.glsl b/src/engine/renderer/glsl_source/fogGlobal_vp.glsl index 8121cd4f89..7cc2ab7533 100644 --- a/src/engine/renderer/glsl_source/fogGlobal_vp.glsl +++ b/src/engine/renderer/glsl_source/fogGlobal_vp.glsl @@ -30,4 +30,6 @@ void main() { // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/fogQuake3_vp.glsl b/src/engine/renderer/glsl_source/fogQuake3_vp.glsl index 9eaae25117..0ebeea6601 100644 --- a/src/engine/renderer/glsl_source/fogQuake3_vp.glsl +++ b/src/engine/renderer/glsl_source/fogQuake3_vp.glsl @@ -99,4 +99,6 @@ void main() var_TexCoords = vec2(s, t); var_Color = color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl b/src/engine/renderer/glsl_source/forwardLighting_vp.glsl index f1a3bb21ba..1c31fe9036 100644 --- a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl +++ b/src/engine/renderer/glsl_source/forwardLighting_vp.glsl @@ -84,4 +84,6 @@ void main() var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; var_Color = color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/fxaa_vp.glsl b/src/engine/renderer/glsl_source/fxaa_vp.glsl index dce68688fa..67ebeaf0b2 100644 --- a/src/engine/renderer/glsl_source/fxaa_vp.glsl +++ b/src/engine/renderer/glsl_source/fxaa_vp.glsl @@ -39,4 +39,6 @@ IN vec3 attr_Position; void main() { gl_Position = u_ModelViewProjectionMatrix * vec4( attr_Position, 1.0f ); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/generic_vp.glsl b/src/engine/renderer/glsl_source/generic_vp.glsl index adcab067ca..788a7b4468 100644 --- a/src/engine/renderer/glsl_source/generic_vp.glsl +++ b/src/engine/renderer/glsl_source/generic_vp.glsl @@ -92,11 +92,16 @@ void main() var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).xy; #endif -#if defined(USE_DEPTH_FADE) || defined(USE_VERTEX_SPRITE) +#if defined(USE_DEPTH_FADE) // compute z of end of fading effect vec4 fadeDepth = u_ModelViewProjectionMatrix * (position - u_DepthScale * vec4(LB.normal, 0.0)); var_FadeDepth = fadeDepth.zw; +#elif defined(USE_VERTEX_SPRITE) + vec4 fadeDepth = u_ModelViewProjectionMatrix * (position - depthScale * vec4(LB.normal, 0.0)); + var_FadeDepth = fadeDepth.zw; #endif var_Color = color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/heatHaze_vp.glsl b/src/engine/renderer/glsl_source/heatHaze_vp.glsl index a7fe1f3d7f..b2d84173c6 100644 --- a/src/engine/renderer/glsl_source/heatHaze_vp.glsl +++ b/src/engine/renderer/glsl_source/heatHaze_vp.glsl @@ -73,4 +73,6 @@ void main() // clamp the distance, so the deformations don't get too wacky near the view var_Deform = min(d1 * (1.0 / max(d2, 1.0)), 0.02) * u_DeformMagnitude; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/lightMapping_fp.glsl b/src/engine/renderer/glsl_source/lightMapping_fp.glsl index 63ec85c6c6..f95ee34a4a 100644 --- a/src/engine/renderer/glsl_source/lightMapping_fp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_fp.glsl @@ -37,19 +37,23 @@ IN(smooth) vec3 var_Tangent; IN(smooth) vec3 var_Binormal; IN(smooth) vec3 var_Normal; -#if defined(USE_LIGHT_MAPPING) +/* #if defined(USE_LIGHT_MAPPING) uniform sampler2D u_LightMap; #elif defined(USE_GRID_LIGHTING) uniform sampler3D u_LightMap; #define u_LightGrid1 u_LightMap -#endif +#endif */ +uniform sampler2D u_LightMap; +uniform sampler3D u_LightGrid1; -#if defined(USE_DELUXE_MAPPING) +/* #if defined(USE_DELUXE_MAPPING) uniform sampler2D u_DeluxeMap; #elif defined(USE_GRID_DELUXE_MAPPING) uniform sampler3D u_DeluxeMap; #define u_LightGrid2 u_DeluxeMap -#endif +#endif */ +uniform sampler2D u_DeluxeMap; +uniform sampler3D u_LightGrid2; #if defined(USE_LIGHT_MAPPING) || defined(USE_DELUXE_MAPPING) IN(smooth) vec2 var_TexLight; @@ -86,8 +90,8 @@ void main() if(abs(diffuse.a + u_AlphaThreshold) <= 1.0) { - discard; - return; + // discard; + // return; } // Compute normal in world space from normalmap. diff --git a/src/engine/renderer/glsl_source/lightMapping_vp.glsl b/src/engine/renderer/glsl_source/lightMapping_vp.glsl index 5e0e1ff2f5..9a73948745 100644 --- a/src/engine/renderer/glsl_source/lightMapping_vp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_vp.glsl @@ -98,4 +98,6 @@ void main() // assign color var_Color = color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/lighttile_vp.glsl b/src/engine/renderer/glsl_source/lighttile_vp.glsl index 5929ecb7b7..8fdce1e4e9 100644 --- a/src/engine/renderer/glsl_source/lighttile_vp.glsl +++ b/src/engine/renderer/glsl_source/lighttile_vp.glsl @@ -46,4 +46,6 @@ void main() { vPosition = attr_Position; vTexCoord = attr_TexCoord0; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/liquid_vp.glsl b/src/engine/renderer/glsl_source/liquid_vp.glsl index 66d6b0de13..0895371dc8 100644 --- a/src/engine/renderer/glsl_source/liquid_vp.glsl +++ b/src/engine/renderer/glsl_source/liquid_vp.glsl @@ -54,5 +54,7 @@ void main() // transform normal into world space var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/motionblur_vp.glsl b/src/engine/renderer/glsl_source/motionblur_vp.glsl index 5f4ac69374..af023886e0 100644 --- a/src/engine/renderer/glsl_source/motionblur_vp.glsl +++ b/src/engine/renderer/glsl_source/motionblur_vp.glsl @@ -28,4 +28,6 @@ IN vec3 attr_Position; void main() { gl_Position = u_ModelViewProjectionMatrix * vec4( attr_Position, 1.0f ); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/portal_vp.glsl b/src/engine/renderer/glsl_source/portal_vp.glsl index 80c56e6929..09adeb74ed 100644 --- a/src/engine/renderer/glsl_source/portal_vp.glsl +++ b/src/engine/renderer/glsl_source/portal_vp.glsl @@ -41,4 +41,6 @@ void main() // assign color var_Color = attr_Color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl index 6a09fb574b..e5403caa5f 100644 --- a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl +++ b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl @@ -67,5 +67,7 @@ void main() // transform normalmap texcoords var_TexCoords = (u_TextureMatrix * vec4(texCoord, 0.0, 1.0)).st; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/refraction_C_vp.glsl b/src/engine/renderer/glsl_source/refraction_C_vp.glsl index 00d723a005..8f8aae99a4 100644 --- a/src/engine/renderer/glsl_source/refraction_C_vp.glsl +++ b/src/engine/renderer/glsl_source/refraction_C_vp.glsl @@ -76,5 +76,7 @@ void main() // transform normal into world space var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz; } + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/screen_vp.glsl b/src/engine/renderer/glsl_source/screen_vp.glsl index 7d0afb53e1..7c81a42ab3 100644 --- a/src/engine/renderer/glsl_source/screen_vp.glsl +++ b/src/engine/renderer/glsl_source/screen_vp.glsl @@ -36,4 +36,6 @@ void main() // assign color var_Color = attr_Color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/shadowFill_vp.glsl b/src/engine/renderer/glsl_source/shadowFill_vp.glsl index 19d5d8ac02..1ebadb23dc 100644 --- a/src/engine/renderer/glsl_source/shadowFill_vp.glsl +++ b/src/engine/renderer/glsl_source/shadowFill_vp.glsl @@ -70,4 +70,6 @@ void main() // assign color var_Color = u_Color; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/skybox_fp.glsl b/src/engine/renderer/glsl_source/skybox_fp.glsl index abc98a2e82..7a030020be 100644 --- a/src/engine/renderer/glsl_source/skybox_fp.glsl +++ b/src/engine/renderer/glsl_source/skybox_fp.glsl @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA const float radiusWorld = 4096.0; // Value used by quake 3 skybox code -uniform samplerCube u_ColorMap; +uniform samplerCube u_ColorMapCube; uniform float u_InverseLightFactor; uniform sampler2D u_CloudMap; @@ -57,7 +57,7 @@ void main() vec4 color; if( !u_UseCloudMap ) { - color = textureCube(u_ColorMap, incidentRay).rgba; + color = textureCube(u_ColorMapCube, incidentRay).rgba; } else { incidentRay *= ComputeCloudParametric( incidentRay, radiusWorld, u_CloudHeight ); incidentRay.z += radiusWorld; diff --git a/src/engine/renderer/glsl_source/skybox_vp.glsl b/src/engine/renderer/glsl_source/skybox_vp.glsl index 382f10a072..0693cf67b7 100644 --- a/src/engine/renderer/glsl_source/skybox_vp.glsl +++ b/src/engine/renderer/glsl_source/skybox_vp.glsl @@ -34,5 +34,7 @@ void main() gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); var_Position = attr_Position; + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/ssao_vp.glsl b/src/engine/renderer/glsl_source/ssao_vp.glsl index ecd8abd6f0..a506525f3a 100644 --- a/src/engine/renderer/glsl_source/ssao_vp.glsl +++ b/src/engine/renderer/glsl_source/ssao_vp.glsl @@ -35,4 +35,6 @@ void main() unprojectionParams.z = 2.0 * u_zFar.z - r_zNear; gl_Position = u_ModelViewProjectionMatrix * vec4( attr_Position, 1.0f ); + + SETUP_SHADER_PARMS } diff --git a/src/engine/renderer/glsl_source/vertexSprite_vp.glsl b/src/engine/renderer/glsl_source/vertexSprite_vp.glsl index 1a7537870d..8b914c4307 100644 --- a/src/engine/renderer/glsl_source/vertexSprite_vp.glsl +++ b/src/engine/renderer/glsl_source/vertexSprite_vp.glsl @@ -31,7 +31,7 @@ IN vec4 attr_Orientation; uniform vec3 u_ViewOrigin; uniform vec3 u_ViewUp; -float u_DepthScale; +float depthScale; void VertexFetch(out vec4 position, out localBasis normalBasis, @@ -77,6 +77,6 @@ void VertexFetch(out vec4 position, lmCoord = abs( attr_TexCoord0.zw ); color = attr_Color; - u_DepthScale = 2.0 * radius; + depthScale = 2.0 * radius; } #endif diff --git a/src/engine/renderer/shaders.cpp b/src/engine/renderer/shaders.cpp index 53f89c6636..d51fc3cc4a 100644 --- a/src/engine/renderer/shaders.cpp +++ b/src/engine/renderer/shaders.cpp @@ -58,6 +58,7 @@ #include "shadowFill_fp.glsl.h" #include "shadowFill_vp.glsl.h" #include "skybox_fp.glsl.h" +#include "commandQueue_vp.glsl.h" std::unordered_map shadermap({ { "glsl/blurX_fp.glsl", std::string(reinterpret_cast(blurX_fp_glsl), sizeof(blurX_fp_glsl)) }, @@ -66,6 +67,7 @@ std::unordered_map shadermap({ { "glsl/blurY_vp.glsl", std::string(reinterpret_cast(blurY_vp_glsl), sizeof(blurY_vp_glsl)) }, { "glsl/cameraEffects_fp.glsl", std::string(reinterpret_cast(cameraEffects_fp_glsl), sizeof(cameraEffects_fp_glsl)) }, { "glsl/cameraEffects_vp.glsl", std::string(reinterpret_cast(cameraEffects_vp_glsl), sizeof(cameraEffects_vp_glsl)) }, + { "glsl/commandQueue_vp.glsl", std::string( reinterpret_cast< const char* >( commandQueue_vp_glsl ), sizeof( commandQueue_vp_glsl ) ) }, { "glsl/computeLight_fp.glsl", std::string(reinterpret_cast(computeLight_fp_glsl), sizeof(computeLight_fp_glsl)) }, { "glsl/contrast_fp.glsl", std::string(reinterpret_cast(contrast_fp_glsl), sizeof(contrast_fp_glsl)) }, { "glsl/contrast_vp.glsl", std::string(reinterpret_cast(contrast_vp_glsl), sizeof(contrast_vp_glsl)) }, diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 0c0da72e7c..55e86e9833 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #include "gl_shader.h" #include "TextureManager.h" +#include "Material.h" #if defined( REFBONE_NAMES ) #include #endif @@ -77,7 +78,69 @@ void GL_Unbind( image_t *image ) glBindTexture( image->type, 0 ); } -void BindAnimatedImage( GLint location, textureBundle_t *bundle ) +bool AnimatedImageUpdated( textureBundle_t* bundle, image_t* currentImage ) { + int index; + + if ( bundle->isVideoMap ) { + if ( bundle->videoMapHandle >= 0 && CIN_RunCinematic( bundle->videoMapHandle ) ) { + return true; + } else { + return currentImage == tr.defaultImage; + } + } + + if ( bundle->numImages <= 1 ) { + return currentImage == bundle->image[0]; + } + + index = Q_ftol( backEnd.refdef.floatTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE ); + index >>= FUNCTABLE_SIZE2; + + if ( index < 0 ) { + index = 0; // may happen with shader time offsets + } + + index %= bundle->numImages; + + return currentImage == bundle->image[index]; +} + +image_t* GetAnimatedImage( textureBundle_t* bundle, image_t* currentImage ) { + int index; + + if ( bundle->isVideoMap ) { + if ( bundle->videoMapHandle >= 0 && CIN_RunCinematic( bundle->videoMapHandle ) ) { + return currentImage; // CIN_UploadCinematic( bundle->videoMapHandle ); + } else { + return tr.defaultImage; + } + } + + if ( bundle->image[0] == nullptr ) { + return tr.defaultImage; + } + + if ( bundle->numImages <= 1 ) { + bundle->image[0]; + } + + // it is necessary to do this messy calc to make sure animations line up + // exactly with waveforms of the same frequency + index = Q_ftol( backEnd.refdef.floatTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE ); + index >>= FUNCTABLE_SIZE2; + + if ( index < 0 ) { + index = 0; // may happen with shader time offsets + } + + if ( !bundle->numImages == 0 ) { + index %= bundle->numImages; + } + + return bundle->image[index]; +} + +GLuint64 BindAnimatedImage( int unit, textureBundle_t *bundle ) { int index; @@ -89,16 +152,15 @@ void BindAnimatedImage( GLint location, textureBundle_t *bundle ) } else { - GL_BindToTMU( location, tr.defaultImage ); + return GL_BindToTMU( unit, tr.defaultImage ); } - return; + return 0; } if ( bundle->numImages <= 1 ) { - GL_BindToTMU( location, bundle->image[ 0 ] ); - return; + return GL_BindToTMU( unit, bundle->image[ 0 ] ); } // it is necessary to do this messy calc to make sure animations line up @@ -113,7 +175,7 @@ void BindAnimatedImage( GLint location, textureBundle_t *bundle ) index %= bundle->numImages; - GL_BindToTMU( location, bundle->image[ index ] ); + return GL_BindToTMU( unit, bundle->image[ index ] ); } void GL_BindProgram( shaderProgram_t *program ) @@ -126,6 +188,9 @@ void GL_BindProgram( shaderProgram_t *program ) return; } + // globalCommandQueue.RegisterProgram( program->program ); + // glState.currentProgram = program; + if ( glState.currentProgram != program ) { glUseProgram( program->program ); @@ -174,7 +239,7 @@ void GL_SelectTexture( int unit ) glState.currenttmu = unit; } -void GL_BindToTMU( GLint unit, image_t *image ) +GLuint64 GL_BindToTMU( int unit, image_t *image ) { if ( !image ) { @@ -182,10 +247,32 @@ void GL_BindToTMU( GLint unit, image_t *image ) image = tr.defaultImage; } - tr.textureManager.BindTexture( unit, image->texture ); - return; + if ( glConfig2.bindlessTexturesAvailable ) { + if ( glConfig2.materialSystemAvailable && false ) { + // globalCommandQueue.RegisterTexture( image->texture ); + return tr.textureManager.RecordTexture( image->texture ); + } + + if ( tr.generatingMaterials ) { + // return tr.textureManager.RecordTexture( image->texture ); + if ( !image->texture->hasBindlessHandle ) { + image->texture->GenBindlessHandle(); + } + return image->texture->bindlessTextureHandle; + } - /* int texnum = image->texnum; + if ( tess.useMaterialSystem ) { + // materialSystem.AddTexture( image->texture ); + } + + return tr.textureManager.BindTexture( 0, image->texture ); + } + + if ( glConfig2.materialSystemAvailable && false ) { + return 0; + } + + int texnum = image->texnum; if ( unit < 0 || unit > 31 ) { @@ -194,11 +281,12 @@ void GL_BindToTMU( GLint unit, image_t *image ) if ( glState.currenttextures[ unit ] == texnum ) { - return; + return 0; } GL_SelectTexture( unit ); - GL_Bind( image ); */ + GL_Bind( image ); + return 0; } void GL_BlendFunc( GLenum sfactor, GLenum dfactor ) @@ -622,6 +710,8 @@ void GL_VertexAttribsState( uint32_t stateBits ) uint32_t diff; uint32_t i; + // globalCommandQueue.RegisterVertexBindingState( stateBits ); + if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) { stateBits |= ATTR_BONE_FACTORS; @@ -733,6 +823,8 @@ void GL_VertexAttribPointers( uint32_t attribBits ) } glVertexAttribPointer( i, layout->numComponents, layout->componentType, layout->normalize, layout->stride, BUFFER_OFFSET( layout->ofs + ( frame * layout->frameOffset + base ) ) ); + + // globalCommandQueue.RegisterVertexBindingState( true, i, layout->numComponents, layout->componentType, layout->normalize, layout->stride, BUFFER_OFFSET( layout->ofs + ( frame * layout->frameOffset + base ) ) ); glState.vertexAttribPointersSet |= bit; } } @@ -868,6 +960,7 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, for ( i = backEnd.viewParms.firstDrawSurf[ Util::ordinal(fromSort) ]; i < lastSurf; i++ ) { drawSurf = &backEnd.viewParms.drawSurfs[ i ]; + tess.currentDrawSurf = drawSurf; // FIXME: investigate why this happens. if( drawSurf->surface == nullptr ) @@ -1873,7 +1966,9 @@ static void RB_SetupLightForLighting( trRefLight_t *light ) gl_debugShadowMapShader->BindProgram( 0 ); - GL_BindToTMU( gl_debugShadowMapShader->GetUniformLocation_CurrentMap(), tr.sunShadowMapFBOImage[frustumIndex]); + gl_debugShadowMapShader->SetUniform_CurrentMapBindless( + GL_BindToTMU( 0, tr.sunShadowMapFBOImage[frustumIndex] ) + ); w = 200; h = 200; @@ -1916,7 +2011,9 @@ static void RB_SetupLightForLighting( trRefLight_t *light ) GL_Cull( cullType_t::CT_TWO_SIDED ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); gl_genericShader->SetUniform_ModelViewProjectionMatrix( light->shadowMatrices[ frustumIndex ] ); @@ -2067,8 +2164,10 @@ static void RB_BlurShadowMap( const trRefLight_t *light, int i ) gl_blurXShader->SetUniform_TexScale( texScale ); Tess_InstantQuad( 0, 0, fbos[ index ]->width, fbos[ index ]->height ); - - GL_BindToTMU( gl_blurXShader->GetUniformLocation_ColorMap(), images[index] ); + + gl_blurXShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, images[index] ) + ); gl_blurXShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); @@ -2088,7 +2187,9 @@ static void RB_BlurShadowMap( const trRefLight_t *light, int i ) gl_blurYShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - GL_BindToTMU( gl_blurYShader->GetUniformLocation_ColorMap(), images[index + MAX_SHADOWMAPS] ); + gl_blurYShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, images[index + MAX_SHADOWMAPS] ) + ); Tess_DrawElements(); @@ -2794,7 +2895,9 @@ void RB_RunVisTests( ) gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_COLORMASK_BITS ); @@ -2871,7 +2974,9 @@ void RB_RenderPostDepthLightTile() zParams[ 2 ] = backEnd.viewParms.zFar; gl_depthtile1Shader->SetUniform_zFar( zParams ); - GL_BindToTMU( gl_depthtile1Shader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_depthtile1Shader->SetUniform_DepthMapBindless( + GL_BindToTMU( 0, tr.currentDepthImage ) + ); matrix_t ortho; GL_PushMatrix(); @@ -2897,7 +3002,9 @@ void RB_RenderPostDepthLightTile() GL_Scissor( 0, 0, w, h ); gl_depthtile2Shader->BindProgram( 0 ); - GL_BindToTMU( gl_depthtile2Shader->GetUniformLocation_DepthMap(), tr.depthtile1RenderImage ); + gl_depthtile2Shader->SetUniform_DepthMapBindless( + GL_BindToTMU( 0, tr.depthtile1RenderImage ) + ); gl_depthtile2Shader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[glState.stackIndex] ); @@ -2923,10 +3030,14 @@ void RB_RenderPostDepthLightTile() if( glConfig2.uniformBufferObjectAvailable ) { gl_lighttileShader->SetUniformBlock_Lights( tr.dlightUBO ); } else { - GL_BindToTMU( gl_lighttileShader->GetUniformLocation_LightsTexture(), tr.dlightImage ); + gl_lighttileShader->SetUniform_LightsTextureBindless( + GL_BindToTMU( 1, tr.dlightImage ) + ); } - GL_BindToTMU( gl_lighttileShader->GetUniformLocation_DepthMap(), tr.depthtile2RenderImage ); + gl_lighttileShader->SetUniform_DepthMapBindless( + GL_BindToTMU( 1, tr.depthtile2RenderImage ) + ); R_BindVBO( tr.lighttileVBO ); @@ -3029,10 +3140,14 @@ void RB_RenderGlobalFog() gl_fogGlobalShader->SetUniform_UnprojectMatrix( backEnd.viewParms.unprojectionMatrix ); // bind u_ColorMap - GL_BindToTMU( gl_fogGlobalShader->GetUniformLocation_ColorMap(), tr.fogImage ); + gl_fogGlobalShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.fogImage ) + ); // bind u_DepthMap - GL_BindToTMU( gl_fogGlobalShader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_fogGlobalShader->SetUniform_DepthMapBindless( + GL_BindToTMU( 0, tr.currentDepthImage ) + ); // set 2D virtual screen size GL_PushMatrix(); @@ -3093,7 +3208,9 @@ void RB_RenderBloom() // u_InverseLightFactor gl_contrastShader->SetUniform_InverseLightFactor( tr.mapInverseLightFactor ); - GL_BindToTMU( gl_contrastShader->GetUniformLocation_ColorMap(), tr.currentRenderImage[backEnd.currentMainFBO] ); + gl_contrastShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) + ); GL_PopMatrix(); // special 1/4th of the screen contrastRenderFBO ortho @@ -3110,7 +3227,9 @@ void RB_RenderBloom() Tess_DrawElements(); // render bloom in multiple passes - GL_BindToTMU( gl_contrastShader->GetUniformLocation_ColorMap(), tr.contrastRenderFBOImage ); + gl_contrastShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.contrastRenderFBOImage ) + ); for ( i = 0; i < 2; i++ ) { for ( j = 0; j < r_bloomPasses->integer; j++ ) @@ -3142,7 +3261,9 @@ void RB_RenderBloom() gl_blurXShader->SetUniform_DeformMagnitude( r_bloomBlur->value ); gl_blurXShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); gl_blurXShader->SetUniform_TexScale( texScale ); - GL_BindToTMU( gl_blurXShader->GetUniformLocation_ColorMap(), tr.bloomRenderFBOImage[flip] ); + gl_blurXShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.bloomRenderFBOImage[flip] ) + ); } else { @@ -3151,7 +3272,9 @@ void RB_RenderBloom() gl_blurYShader->SetUniform_DeformMagnitude( r_bloomBlur->value ); gl_blurYShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); gl_blurYShader->SetUniform_TexScale( texScale ); - GL_BindToTMU( gl_blurYShader->GetUniformLocation_ColorMap(), tr.bloomRenderFBOImage[flip] ); + gl_blurYShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.bloomRenderFBOImage[flip] ) + ); } Tess_DrawElements(); @@ -3200,13 +3323,17 @@ void RB_RenderMotionBlur() gl_motionblurShader->BindProgram( 0 ); // Swap main FBOs - GL_BindToTMU( gl_motionblurShader->GetUniformLocation_ColorMap(), tr.currentRenderImage[backEnd.currentMainFBO] ); + gl_motionblurShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) + ); backEnd.currentMainFBO = 1 - backEnd.currentMainFBO; R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); gl_motionblurShader->SetUniform_blurVec(tr.refdef.blurVec); - GL_BindToTMU( gl_motionblurShader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_motionblurShader->SetUniform_DepthMapBindless( + GL_BindToTMU( 1, tr.currentDepthImage ) + ); matrix_t ortho; GL_PushMatrix(); @@ -3262,7 +3389,9 @@ void RB_RenderSSAO() gl_ssaoShader->SetUniform_zFar( zParams ); - GL_BindToTMU( gl_ssaoShader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_ssaoShader->SetUniform_DepthMapBindless( + GL_BindToTMU( 0, tr.currentDepthImage ) + ); matrix_t ortho; GL_PushMatrix(); @@ -3305,7 +3434,9 @@ void RB_FXAA() GL_Cull( cullType_t::CT_TWO_SIDED ); // Swap main FBOs - GL_BindToTMU( gl_fxaaShader->GetUniformLocation_ColorMap(), tr.currentRenderImage[backEnd.currentMainFBO] ); + gl_fxaaShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) + ); backEnd.currentMainFBO = 1 - backEnd.currentMainFBO; R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); @@ -3368,8 +3499,12 @@ void RB_CameraPostFX() // This shader is run last, so let it render to screen instead of // tr.mainFBO R_BindNullFBO(); - GL_BindToTMU( gl_cameraEffectsShader->GetUniformLocation_CurrentMap(), tr.currentRenderImage[backEnd.currentMainFBO] ); - GL_BindToTMU( gl_cameraEffectsShader->GetUniformLocation_ColorMap(), tr.colorGradeImage ); + gl_cameraEffectsShader->SetUniform_CurrentMapBindless( + GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) + ); + gl_cameraEffectsShader->SetUniform_ColorMap3DBindless( + GL_BindToTMU( 3, tr.colorGradeImage ) + ); // draw viewport Tess_InstantQuad( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, @@ -3417,7 +3552,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetRequiredVertexPointers(); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); ia = nullptr; @@ -3577,7 +3714,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_Color( Color::Black ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); for ( iaCount = 0, ia = &backEnd.viewParms.interactions[ 0 ]; iaCount < backEnd.viewParms.numInteractions; ia++, iaCount++ ) @@ -3702,7 +3841,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_Color( Color::Black ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); ent = backEnd.refdef.entities; @@ -3783,7 +3924,9 @@ static void RB_RenderDebugUtils() int width = r_imageHashTable [ tr.charsetImageHash ]->width; int height = r_imageHashTable [ tr.charsetImageHash ]->height; #else - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); #endif gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); @@ -4006,7 +4149,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_ColorModulate( colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); // set 2D virtual screen size @@ -4099,7 +4244,9 @@ static void RB_RenderDebugUtils() } // bind u_ColorMap - GL_BindToTMU( gl_reflectionShader->GetUniformLocation_ColorMap(), cubeProbe->cubemap ); + gl_reflectionShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, cubeProbe->cubemap ) + ); Tess_AddCubeWithNormals( cubeProbe->origin, mins, maxs, Color::White ); } @@ -4136,7 +4283,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); GL_CheckErrors(); @@ -4212,7 +4361,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); GL_CheckErrors(); @@ -4297,7 +4448,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_ColorModulate( colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); GL_CheckErrors(); @@ -4394,7 +4547,9 @@ static void RB_RenderDebugUtils() GL_Cull( cullType_t::CT_TWO_SIDED ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); @@ -4596,7 +4751,9 @@ static void RB_RenderDebugUtils() gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); GL_CheckErrors(); @@ -4688,7 +4845,9 @@ void DebugDrawBegin( debugDrawMode_t mode, float size ) { gl_genericShader->SetUniform_Color( colorClear ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); // render in world space @@ -4819,7 +4978,12 @@ static void RB_RenderView( bool depthPass ) startTime = ri.Milliseconds(); } + materialSystem.frameStart = true; + if( depthPass ) { + if ( glConfig2.materialSystemAvailable ) { + materialSystem.RenderMaterials( shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH ); + } RB_RenderDrawSurfaces( shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH, DRAWSURFACES_ALL ); RB_RunVisTests(); RB_RenderPostDepthLightTile(); @@ -4831,6 +4995,9 @@ static void RB_RenderView( bool depthPass ) tr.refdef.blurVec[2] != 0.0f ) { // draw everything that is not the gun + if ( glConfig2.materialSystemAvailable ) { + materialSystem.RenderMaterials( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE ); + } RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE, DRAWSURFACES_ALL_FAR ); RB_RenderMotionBlur(); @@ -4841,6 +5008,9 @@ static void RB_RenderView( bool depthPass ) else { // draw everything that is opaque + if ( glConfig2.materialSystemAvailable ) { + materialSystem.RenderMaterials( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE ); + } RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE, DRAWSURFACES_ALL ); } @@ -4870,6 +5040,9 @@ static void RB_RenderView( bool depthPass ) RB_RenderGlobalFog(); // draw everything that is translucent + if ( glConfig2.materialSystemAvailable ) { + materialSystem.RenderMaterials( shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS ); + } RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS, DRAWSURFACES_ALL ); GL_CheckErrors(); @@ -5513,7 +5686,9 @@ const RenderCommand *SetupLightsCommand::ExecuteSelf( ) const glUnmapBuffer( bufferTarget ); if( !glConfig2.uniformBufferObjectAvailable ) { - GL_BindToTMU( gl_lighttileShader->GetUniformLocation_LightsTexture(), tr.dlightImage ); + gl_lighttileShader->SetUniform_LightsTextureBindless( + GL_BindToTMU( 1, tr.dlightImage ) + ); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, tr.dlightImage->width, tr.dlightImage->height, GL_RGBA, GL_FLOAT, nullptr ); } glBindBuffer( bufferTarget, 0 ); @@ -5855,7 +6030,9 @@ void RB_ShowImages() } // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), image ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, image ) + ); Tess_InstantQuad( x, y, w, h ); @@ -5981,13 +6158,17 @@ void RB_ExecuteRenderCommands( const void *data ) backEnd.smpFrame = 1; } - tr.textureManager.UpdateAdjustedPriorities(); + // Log::Warn( "CMD: ====================" ); + // Log::Warn( "CMD: Start" ); while ( cmd != nullptr ) { cmd = cmd->ExecuteSelf(); } - // tr.textureManager.AllNonResident(); + + // Log::Warn( "CMD: End" ); + // Log::Warn( "CMD: ====================" ); + // stop rendering on this thread t2 = ri.Milliseconds(); backEnd.pc.msec = t2 - t1; diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index dcb8c36f84..3f8bdf6129 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_bsp.c #include "tr_local.h" #include "framework/CommandSystem.h" +#include "Material.h" /* ======================================================== @@ -7091,4 +7092,6 @@ void RE_LoadWorldMap( const char *name ) tr.mapLightFactor = pow( 2, tr.mapOverBrightBits ); tr.mapInverseLightFactor = 1.0f / tr.mapLightFactor; } + + tr.materialsGenerated = false; } diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 9722e9b20f..da232ceac9 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1037,17 +1037,6 @@ void R_UploadImage( const byte **dataArray, int numLayers, int numMips, image_t image->uploadHeight = scaledHeight; image->internalFormat = internalFormat; - const int size = scaledWidth * scaledHeight; - if ( size < 128 * 128 ) { - image->texture->basePriority = TEXTURE_PRIORITY_LOW; - } else if ( size < 512 * 512 ) { - image->texture->basePriority = TEXTURE_PRIORITY_MEDIUM; - } else if ( size < 1024 * 1024 ) { - image->texture->basePriority = TEXTURE_PRIORITY_HIGH; - } else { - image->texture->basePriority = TEXTURE_PRIORITY_PERSISTENT; - } - switch ( image->type ) { case GL_TEXTURE_3D: @@ -1091,17 +1080,6 @@ void R_UploadImage( const byte **dataArray, int numLayers, int numMips, image_t image->uploadHeight = scaledHeight; image->internalFormat = internalFormat; - const int size = scaledWidth * scaledHeight; - if ( size < 128 * 128 ) { - image->texture->basePriority = TEXTURE_PRIORITY_LOW; - } else if ( size < 512 * 512 ) { - image->texture->basePriority = TEXTURE_PRIORITY_MEDIUM; - } else if ( size < 1024 * 1024 ) { - image->texture->basePriority = TEXTURE_PRIORITY_HIGH; - } else { - image->texture->basePriority = TEXTURE_PRIORITY_PERSISTENT; - } - mipWidth = scaledWidth; mipHeight = scaledHeight; mipLayers = numLayers; @@ -1433,17 +1411,6 @@ image_t *R_CreateGlyph( const char *name, const byte *pic, int width, int height image->uploadHeight = height; image->internalFormat = GL_RGBA; - const int size = width * height; - if ( size < 128 * 128 ) { - image->texture->basePriority = TEXTURE_PRIORITY_LOW; - } else if ( size < 512 * 512 ) { - image->texture->basePriority = TEXTURE_PRIORITY_MEDIUM; - } else if ( size < 1024 * 1024 ) { - image->texture->basePriority = TEXTURE_PRIORITY_HIGH; - } else { - image->texture->basePriority = TEXTURE_PRIORITY_PERSISTENT; - } - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic ); GL_CheckErrors(); diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 78f0569234..cc65430c4e 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_init.c -- functions that are not called every frame #include "tr_local.h" #include "framework/CvarSystem.h" +#include "Material.h" glconfig_t glConfig; glconfig2_t glConfig2; @@ -102,6 +103,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_arb_texture_gather; cvar_t *r_arb_gpu_shader5; cvar_t *r_arb_bindless_texture; + cvar_t *r_arb_shader_draw_parameters; + cvar_t *r_arb_shader_storage_buffer_object; + cvar_t *r_arb_gpu_shader_int64; + cvar_t *r_arb_multi_draw_indirect; cvar_t *r_checkGLErrors; cvar_t *r_logFile; @@ -1090,6 +1095,10 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_arb_texture_gather = Cvar_Get( "r_arb_texture_gather", "1", CVAR_CHEAT | CVAR_LATCH ); r_arb_gpu_shader5 = Cvar_Get( "r_arb_gpu_shader5", "1", CVAR_CHEAT | CVAR_LATCH ); r_arb_bindless_texture = Cvar_Get( "r_arb_bindless_texture", "1", CVAR_CHEAT | CVAR_LATCH ); + r_arb_shader_draw_parameters = Cvar_Get( "r_arb_shader_draw_parameters", "1", CVAR_CHEAT | CVAR_LATCH ); + r_arb_shader_storage_buffer_object = Cvar_Get( "r_arb_shader_storage_buffer_object", "1", CVAR_CHEAT | CVAR_LATCH ); + r_arb_gpu_shader_int64 = Cvar_Get( "r_arb_gpu_shader_int64", "1", CVAR_CHEAT | CVAR_LATCH ); + r_arb_multi_draw_indirect = Cvar_Get( "r_arb_multi_draw_indirect", "1", CVAR_CHEAT | CVAR_LATCH ); r_picMip = Cvar_Get( "r_picMip", "0", CVAR_LATCH | CVAR_ARCHIVE ); r_imageMaxDimension = Cvar_Get( "r_imageMaxDimension", "0", CVAR_LATCH | CVAR_ARCHIVE ); @@ -1481,6 +1490,8 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p // print info GfxInfo_f(); + // globalCommandQueue.Init(); + Log::Debug("----- finished R_Init -----" ); return true; @@ -1525,6 +1536,8 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p R_DoneFreeType(); + materialSystem.Free(); + // shut down platform specific OpenGL stuff if ( destroyWindow ) { diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 090a6e00be..bf7642cb56 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -597,6 +597,9 @@ enum class dynamicLightRenderer_t { LEGACY, TILED }; cullResult_t cull; vec3_t localBounds[ 2 ]; vec3_t worldBounds[ 2 ]; + + bool modelMatrixUpdated = false; + uint modelMatrixID = 0; }; struct orientationr_t @@ -1296,6 +1299,18 @@ enum class dynamicLightRenderer_t { LEGACY, TILED }; expression_t deformMagnitudeExp; bool noFog; // used only for shaders that have fog disabled, so we can enable it for individual stages + + bool useMaterialSystem = false; + uint materialPackID = 0; + uint materialID = 0; + // uint materialsSSBOOffset = 0; + // bool initialized = false; + bool dynamic = false; + bool colorDynamic = false; + bool texMatricesDynamic = false; + bool texturesDynamic = false; + image_t* currentAnimatedImage; + // int dynamicMaterialOffsets[MAX_DYNAMIC_MATERIAL_OFFSETS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; }; enum cullType_t : int @@ -1753,6 +1768,13 @@ enum class dynamicLightRenderer_t { LEGACY, TILED }; uint64_t sort; bool bspSurface; + uint materialsSSBOOffset[ MAX_SHADER_STAGES ]; + bool initialized[ MAX_SHADER_STAGES ]; + uint materialIDs[ MAX_SHADER_STAGES ]; + uint materialPackIDs[ MAX_SHADER_STAGES ]; + /* bool colorDynamic[MAX_SHADER_STAGES]; + bool texMatricesDynamic[ MAX_SHADER_STAGES ]; */ + inline int index() const { return int( ( sort & SORT_INDEX_MASK ) ); } @@ -2845,7 +2867,10 @@ enum class dynamicLightRenderer_t { LEGACY, TILED }; // Generic shapes drawSurf_t *genericQuad; + bool materialsGenerated; + bool hasSkybox; + bool drawingSky = false; drawSurf_t *skybox; vec3_t sunLight; // from the sky shader for this level @@ -2905,6 +2930,8 @@ enum class dynamicLightRenderer_t { LEGACY, TILED }; float fogTable[ FOG_TABLE_SIZE ]; scissorState_t scissor; + + bool generatingMaterials = false; }; extern const matrix_t quakeToOpenGLMatrix; @@ -3001,6 +3028,10 @@ enum class dynamicLightRenderer_t { LEGACY, TILED }; extern cvar_t *r_arb_texture_gather; extern cvar_t *r_arb_gpu_shader5; extern cvar_t *r_arb_bindless_texture; + extern cvar_t *r_arb_shader_draw_parameters; + extern cvar_t *r_arb_shader_storage_buffer_object; + extern cvar_t *r_arb_gpu_shader_int64; + extern cvar_t *r_arb_multi_draw_indirect; extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_singleShader; // make most world faces use default shader @@ -3253,10 +3284,12 @@ inline bool checkGLErrors() void GL_Bind( image_t *image ); void GL_BindNearestCubeMap( GLint location, const vec3_t xyz ); void GL_Unbind( image_t *image ); - void BindAnimatedImage( GLint location, textureBundle_t *bundle ); + bool AnimatedImageUpdated( textureBundle_t* bundle, image_t* currentImage ); + image_t* GetAnimatedImage( textureBundle_t* bundle, image_t* currentImage ); + GLuint64 BindAnimatedImage( int unit, textureBundle_t *bundle ); void GL_TextureFilter( image_t *image, filterType_t filterType ); void GL_BindProgram( shaderProgram_t *program ); - void GL_BindToTMU( GLint unit, image_t *image ); + GLuint64 GL_BindToTMU( int unit, image_t *image ); void GL_BindNullProgram(); void GL_SetDefaultState(); void GL_SelectTexture( int unit ); @@ -3455,6 +3488,13 @@ inline bool checkGLErrors() VBO_t *vbo; IBO_t *ibo; + bool useMaterialSystem = false; + bool generatingMaterials = false; + uint materialPackID = 0; + uint materialID = 0; + uint currentSSBOOffset = 0; + drawSurf_t* currentDrawSurf; + stageVars_t svars; shader_t *surfaceShader; @@ -3472,6 +3512,7 @@ inline bool checkGLErrors() int multiDrawPrimitives; glIndex_t *multiDrawIndexes[ MAX_MULTIDRAW_PRIMITIVES ]; int multiDrawCounts[ MAX_MULTIDRAW_PRIMITIVES ]; + uint multiDrawOffsets[ MAX_MULTIDRAW_PRIMITIVES ]; bool vboVertexSkinning; int numBones; @@ -3520,7 +3561,12 @@ inline bool checkGLErrors() void Tess_DrawArrays( GLenum elementType ); void Tess_CheckOverflow( int verts, int indexes ); + void SetNormalScale( const shaderStage_t* pStage, vec3_t normalScale ); + void SetRgbaGen( const shaderStage_t* pStage, colorGen_t* rgbGen, alphaGen_t* alphaGen ); void Tess_ComputeColor( shaderStage_t *pStage ); + void Tess_ComputeTexMatrices( shaderStage_t* pStage ); + // image_t* GetLightMap(); + // image_t* GetDeluxeMap(); void Tess_StageIteratorDebug(); void Tess_StageIteratorColor(); diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index 033143d051..6e78f02047 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // tr_main.c -- main control flow for each frame #include "tr_local.h" +#include "Material.h" trGlobals_t tr; @@ -834,6 +835,11 @@ static void SetFarClip() vec3_t v; float distance; + if ( glConfig2.materialSystemAvailable ) { + VectorCopy( materialSystem.worldViewBounds[0], tr.viewParms.visBounds[0] ); + VectorCopy( materialSystem.worldViewBounds[1], tr.viewParms.visBounds[1] ); + } + if ( i & 1 ) { v[ 0 ] = tr.viewParms.visBounds[ 0 ][ 0 ]; @@ -2006,6 +2012,15 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, i tr.refdef.numDrawSurfs++; + // Portal and sky surfaces are not handled by the material system at all + if ( materialSystem.generatingWorldCommandBuffer && ( shader->isPortal || shader->isSky ) ) { + if ( shader->isSky && std::find( materialSystem.skyShaders.begin(), materialSystem.skyShaders.end(), shader ) + == materialSystem.skyShaders.end() ) { + materialSystem.skyShaders.emplace_back( shader ); + } + return; + } + if ( shader->depthShader != nullptr ) { R_AddDrawSurf( surface, shader->depthShader, 0, 0, bspSurface ); } @@ -2023,7 +2038,7 @@ static void R_SortDrawSurfs() int i, sort; // it is possible for some views to not have any surfaces - if ( tr.viewParms.numDrawSurfs < 1 ) + if ( !glConfig2.materialSystemAvailable && tr.viewParms.numDrawSurfs < 1 ) { // we still need to add it for hyperspace cases R_AddDrawViewCmd( false ); @@ -2850,7 +2865,7 @@ void R_RenderView( viewParms_t *parms ) // set the projection matrix with the far clip plane set at infinity // this required for the CHC++ algorithm - R_SetupProjection( true ); + R_SetupProjection( false ); R_SetupFrustum(); @@ -2858,7 +2873,20 @@ void R_RenderView( viewParms_t *parms ) // because it requires the decalBits R_CullDecalProjectors(); + if ( !tr.materialsGenerated ) { + materialSystem.GenerateMaterials(); + tr.materialsGenerated = true; + } + // materialSystem.frameStart = true; + + const uint current_r_drawworld = r_drawworld->integer; + const uint current_r_nocull = r_nocull->integer; + if ( glConfig2.materialSystemAvailable ) { + r_drawworld->integer = 0; + } R_AddWorldSurfaces(); + r_drawworld->integer = current_r_drawworld; + r_nocull->integer = current_r_nocull; R_AddPolygonSurfaces(); diff --git a/src/engine/renderer/tr_public.h b/src/engine/renderer/tr_public.h index ef20ee78a5..848f6b322c 100644 --- a/src/engine/renderer/tr_public.h +++ b/src/engine/renderer/tr_public.h @@ -85,6 +85,11 @@ struct glconfig2_t bool textureIntegerAvailable; bool textureRGAvailable; bool bindlessTexturesAvailable; + bool shaderDrawParametersAvailable; + bool SSBOAvailable; + bool shaderInt64Available; + bool multiDrawIndirectAvailable; + bool materialSystemAvailable; bool gpuShader4Available; bool textureGatherAvailable; int maxDrawBuffers; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 22c47de4ac..4037f5dac9 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_shade.c #include "tr_local.h" #include "gl_shader.h" +#include "Material.h" /* ================================================================================= @@ -77,9 +78,11 @@ static void GLSL_InitGPUShadersOrError() // single texture rendering gl_shaderManager.load( gl_generic2DShader ); gl_shaderManager.load( gl_genericShader ); + gl_shaderManager.load( gl_genericShaderMaterial ); // standard light mapping gl_shaderManager.load( gl_lightMappingShader ); + gl_shaderManager.load( gl_lightMappingShaderMaterial ); if ( glConfig2.dynamicLight ) { @@ -271,7 +274,9 @@ void GLSL_ShutdownGPUShaders() gl_shaderManager.freeAll(); gl_genericShader = nullptr; + gl_genericShaderMaterial = nullptr; gl_lightMappingShader = nullptr; + gl_lightMappingShaderMaterial = nullptr; gl_forwardLightingShader_omniXYZ = nullptr; gl_forwardLightingShader_projXYZ = nullptr; gl_forwardLightingShader_directionalSun = nullptr; @@ -320,12 +325,16 @@ void Tess_DrawElements() return; } + // globalCommandQueue.SetDrawcallUniforms(); + // move tess data through the GPU, finally if ( glState.currentVBO && glState.currentIBO ) { if ( tess.multiDrawPrimitives ) { - glMultiDrawElements( GL_TRIANGLES, tess.multiDrawCounts, GL_INDEX_TYPE, ( const GLvoid ** ) tess.multiDrawIndexes, tess.multiDrawPrimitives ); + if ( !tess.generatingMaterials ) { + glMultiDrawElements( GL_TRIANGLES, tess.multiDrawCounts, GL_INDEX_TYPE, ( const GLvoid** ) tess.multiDrawIndexes, tess.multiDrawPrimitives ); + } backEnd.pc.c_multiDrawElements++; backEnd.pc.c_multiDrawPrimitives += tess.multiDrawPrimitives; @@ -336,6 +345,10 @@ void Tess_DrawElements() { backEnd.pc.c_multiVboIndexes += tess.multiDrawCounts[ i ]; backEnd.pc.c_indexes += tess.multiDrawCounts[ i ]; + if ( tess.generatingMaterials ) { + materialSystem.AddDrawCommand( tess.materialID, tess.materialPackID, tess.currentSSBOOffset, + ( GLuint ) tess.multiDrawCounts[i], tess.multiDrawOffsets[i] ); + } } } else @@ -346,7 +359,11 @@ void Tess_DrawElements() base = tess.indexBase * sizeof( glIndex_t ); } - glDrawRangeElements( GL_TRIANGLES, 0, tess.numVertexes, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET( base ) ); + if ( tess.generatingMaterials ) { + materialSystem.AddDrawCommand( tess.materialID, tess.materialPackID, tess.currentSSBOOffset, tess.numIndexes, tess.indexBase ); + } else { + glDrawRangeElements( GL_TRIANGLES, 0, tess.numVertexes, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET( base ) ); + } backEnd.pc.c_drawElements++; @@ -359,13 +376,18 @@ void Tess_DrawElements() } else { - glDrawElements( GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, tess.indexes ); + if ( tess.generatingMaterials ) { + materialSystem.AddDrawCommand( tess.materialID, tess.materialPackID, tess.currentSSBOOffset, tess.numIndexes, tess.indexBase ); + } else { + glDrawElements( GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, tess.indexes ); + } backEnd.pc.c_drawElements++; backEnd.pc.c_indexes += tess.numIndexes; backEnd.pc.c_vertexes += tess.numVertexes; } + tess.generatingMaterials = false; } /* @@ -481,7 +503,9 @@ static void DrawTris() gl_genericShader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); // bind u_ColorMap - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); gl_genericShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); gl_genericShader->SetRequiredVertexPointers(); @@ -566,7 +590,7 @@ void Tess_Begin( void ( *stageIteratorFunc )(), } } -static void SetNormalScale( const shaderStage_t *pStage, vec3_t normalScale ) +void SetNormalScale( const shaderStage_t *pStage, vec3_t normalScale ) { float normalIntensity = RB_EvalExpression( &pStage->normalIntensityExp, 1.0 ); @@ -582,7 +606,7 @@ static void SetNormalScale( const shaderStage_t *pStage, vec3_t normalScale ) normalScale[ 2 ] = pStage->normalScale[ 2 ] * r_normalScale->value; } -static void SetRgbaGen( const shaderStage_t *pStage, colorGen_t *rgbGen, alphaGen_t *alphaGen ) +void SetRgbaGen( const shaderStage_t *pStage, colorGen_t *rgbGen, alphaGen_t *alphaGen ) { switch ( pStage->rgbGen ) { @@ -651,21 +675,29 @@ static void Render_generic2D( shaderStage_t *pStage ) alphaGen_t alphaGen; SetRgbaGen( pStage, &rgbGen, &alphaGen ); gl_generic2DShader->SetUniform_ColorModulate( rgbGen, alphaGen ); + GL_CheckErrors(); // u_Color gl_generic2DShader->SetUniform_Color( tess.svars.color ); + GL_CheckErrors(); gl_generic2DShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + GL_CheckErrors(); gl_generic2DShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); + GL_CheckErrors(); // u_DeformGen gl_generic2DShader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); + GL_CheckErrors(); // bind u_ColorMap - BindAnimatedImage( gl_generic2DShader->GetUniformLocation_ColorMap(), &pStage->bundle[TB_COLORMAP]); + gl_generic2DShader->SetUniform_ColorMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); + GL_CheckErrors(); gl_generic2DShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); + GL_CheckErrors(); glEnable( GL_DEPTH_CLAMP ); + GL_CheckErrors(); if ( hasDepthFade ) { @@ -674,12 +706,16 @@ static void Render_generic2D( shaderStage_t *pStage ) if ( needDepthMap ) { - GL_BindToTMU( gl_generic2DShader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_generic2DShader->SetUniform_DepthMapBindless( + GL_BindToTMU( 1, tr.currentDepthImage ) + ); } gl_generic2DShader->SetRequiredVertexPointers(); + GL_CheckErrors(); Tess_DrawElements(); + GL_CheckErrors(); glDisable( GL_DEPTH_CLAMP ); @@ -692,6 +728,12 @@ void Render_generic3D( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_generic3D ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + tess.generatingMaterials = true; + Tess_DrawElements(); + return; + } + GL_State( pStage->stateBits ); bool hasDepthFade = pStage->hasDepthFade && !tess.surfaceShader->autoSpriteMode; @@ -764,11 +806,13 @@ void Render_generic3D( shaderStage_t *pStage ) if ( pStage->type == stageType_t::ST_STYLELIGHTMAP ) { // GL_Bind( GetLightMap() ); - GL_BindToTMU( gl_genericShader->GetUniformLocation_ColorMap(), GetLightMap() ); + gl_genericShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, GetLightMap() ) + ); } else { - BindAnimatedImage( gl_genericShader->GetUniformLocation_ColorMap(), &pStage->bundle[TB_COLORMAP] ); + gl_genericShader->SetUniform_ColorMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); } gl_genericShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); @@ -780,7 +824,9 @@ void Render_generic3D( shaderStage_t *pStage ) if ( needDepthMap ) { - GL_BindToTMU( gl_genericShader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_genericShader->SetUniform_DepthMapBindless( + GL_BindToTMU( 1, tr.currentDepthImage ) + ); } gl_genericShader->SetRequiredVertexPointers(); @@ -848,6 +894,12 @@ void Render_lightMapping( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_lightMapping ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + tess.generatingMaterials = true; + Tess_DrawElements(); + return; + } + lightMode_t lightMode = lightMode_t::FULLBRIGHT; deluxeMode_t deluxeMode = deluxeMode_t::NONE; @@ -1028,14 +1080,18 @@ void Render_lightMapping( shaderStage_t *pStage ) gl_lightMappingShader->SetUniformBlock_Lights( tr.dlightUBO ); } else { - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_LightsTexture(), tr.dlightImage ); + gl_lightMappingShader->SetUniform_LightsTextureBindless( + GL_BindToTMU( BIND_LIGHTS, tr.dlightImage ) + ); } } // bind u_LightTiles if ( r_dynamicLightRenderer.Get() == Util::ordinal( dynamicLightRenderer_t::TILED ) ) { - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_LightTiles(), tr.lighttileRenderImage ); + gl_lightMappingShader->SetUniform_LightTilesIntBindless( + GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) + ); } } @@ -1071,12 +1127,16 @@ void Render_lightMapping( shaderStage_t *pStage ) // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_HeightMap(), pStage->bundle[TB_HEIGHTMAP].image[0] ); + gl_lightMappingShader->SetUniform_HeightMapBindless( + GL_BindToTMU( BIND_HEIGHTMAP, pStage->bundle[TB_HEIGHTMAP].image[0] ) + ); } } // bind u_DiffuseMap - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_DiffuseMap(), pStage->bundle[TB_DIFFUSEMAP].image[0] ); + gl_lightMappingShader->SetUniform_DiffuseMapBindless( + GL_BindToTMU( BIND_DIFFUSEMAP, pStage->bundle[TB_DIFFUSEMAP].image[0] ) + ); if ( pStage->type != stageType_t::ST_LIGHTMAP ) { @@ -1086,7 +1146,9 @@ void Render_lightMapping( shaderStage_t *pStage ) // bind u_NormalMap if ( !!r_normalMapping->integer || pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_lightMappingShader->SetUniform_NormalMapBindless( + GL_BindToTMU( BIND_NORMALMAP, pStage->bundle[TB_NORMALMAP].image[0] ) + ); } // bind u_NormalScale @@ -1101,7 +1163,9 @@ void Render_lightMapping( shaderStage_t *pStage ) // bind u_MaterialMap if ( pStage->enableSpecularMapping || pStage->enablePhysicalMapping ) { - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_MaterialMap(), pStage->bundle[TB_MATERIALMAP].image[0] ); + gl_lightMappingShader->SetUniform_MaterialMapBindless( + GL_BindToTMU( BIND_MATERIALMAP, pStage->bundle[TB_MATERIALMAP].image[0] ) + ); } if ( pStage->enableSpecularMapping ) @@ -1197,10 +1261,14 @@ void Render_lightMapping( shaderStage_t *pStage ) } // bind u_EnvironmentMap0 - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_EnvironmentMap0(), cubeMap0 ); + gl_lightMappingShader->SetUniform_EnvironmentMap0Bindless( + GL_BindToTMU( BIND_ENVIRONMENTMAP0, cubeMap0 ) + ); // bind u_EnvironmentMap1 - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_EnvironmentMap1(), cubeMap1 ); + gl_lightMappingShader->SetUniform_EnvironmentMap1Bindless( + GL_BindToTMU( BIND_ENVIRONMENTMAP1, cubeMap1 ) + ); // bind u_EnvironmentInterpolation gl_lightMappingShader->SetUniform_EnvironmentInterpolation( interpolation ); @@ -1218,15 +1286,29 @@ void Render_lightMapping( shaderStage_t *pStage ) } // bind u_LightMap - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_LightMap(), lightmap ); + if ( !enableGridLighting ) { + gl_lightMappingShader->SetUniform_LightMapBindless( + GL_BindToTMU( BIND_LIGHTMAP, lightmap ) + ); + } else { + gl_lightMappingShader->SetUniform_LightGrid1Bindless( GL_BindToTMU( BIND_LIGHTMAP, lightmap ) ); + } // bind u_DeluxeMap - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_DeluxeMap(), deluxemap ); + if ( !enableGridDeluxeMapping ) { + gl_lightMappingShader->SetUniform_DeluxeMapBindless( + GL_BindToTMU( BIND_DELUXEMAP, deluxemap ) + ); + } else { + gl_lightMappingShader->SetUniform_LightGrid2Bindless( GL_BindToTMU( BIND_DELUXEMAP, deluxemap ) ); + } // bind u_GlowMap if ( !!r_glowMapping->integer ) { - GL_BindToTMU( gl_lightMappingShader->GetUniformLocation_GlowMap(), pStage->bundle[TB_GLOWMAP].image[0] ); + gl_lightMappingShader->SetUniform_GlowMapBindless( + GL_BindToTMU( BIND_GLOWMAP, pStage->bundle[TB_GLOWMAP].image[0] ) + ); } gl_lightMappingShader->SetRequiredVertexPointers(); @@ -1242,6 +1324,10 @@ 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 ); @@ -1291,12 +1377,16 @@ static void Render_shadowFill( shaderStage_t *pStage ) // bind u_ColorMap if ( ( pStage->stateBits & GLS_ATEST_BITS ) != 0 ) { - GL_BindToTMU( gl_shadowFillShader->GetUniformLocation_ColorMap(), pStage->bundle[TB_COLORMAP].image[0] ); + gl_shadowFillShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) + ); gl_shadowFillShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); } else { - GL_BindToTMU( gl_shadowFillShader->GetUniformLocation_ColorMap(), tr.whiteImage ); + gl_shadowFillShader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.whiteImage ) + ); } Tess_DrawElements(); @@ -1354,7 +1444,9 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_HeightMap(), pStage->bundle[TB_HEIGHTMAP].image[0] ); + gl_forwardLightingShader_omniXYZ->SetUniform_HeightMapBindless( + GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) + ); } } @@ -1410,7 +1502,9 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, GL_CheckErrors(); // bind u_DiffuseMap - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_DiffuseMap(), pStage->bundle[TB_DIFFUSEMAP].image[0] ); + gl_forwardLightingShader_omniXYZ->SetUniform_DiffuseMapBindless( + GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) + ); if ( pStage->type != stageType_t::ST_LIGHTMAP ) { @@ -1418,7 +1512,9 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, } // bind u_NormalMap - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_forwardLightingShader_omniXYZ->SetUniform_NormalMapBindless( + GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) + ); // bind u_NormalScale if ( pStage->enableNormalMapping ) @@ -1430,7 +1526,9 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, } // bind u_MaterialMap - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_MaterialMap(), pStage->bundle[TB_MATERIALMAP].image[0] ); + gl_forwardLightingShader_omniXYZ->SetUniform_MaterialMapBindless( + GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) + ); // FIXME: physical mapping is not implemented. if ( pStage->enableSpecularMapping ) @@ -1442,20 +1540,26 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, } // bind u_AttenuationMapXY - BindAnimatedImage( gl_forwardLightingShader_omniXYZ->GetUniformLocation_AttenuationMapXY(), &attenuationXYStage->bundle[TB_COLORMAP]); + gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapXYBindless( + BindAnimatedImage( 3, &attenuationXYStage->bundle[TB_COLORMAP]) ); // bind u_AttenuationMapZ - BindAnimatedImage( gl_forwardLightingShader_omniXYZ->GetUniformLocation_AttenuationMapZ(), &attenuationZStage->bundle[TB_COLORMAP]); + gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapZBindless( + BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); // bind u_ShadowMap if ( shadowCompare ) { - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_ShadowMap(), tr.shadowCubeFBOImage[light->shadowLOD] ); - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_ShadowClipMap(), tr.shadowClipCubeFBOImage[light->shadowLOD] ); + gl_forwardLightingShader_omniXYZ->SetUniform_ShadowMapBindless( + GL_BindToTMU( 5, tr.shadowCubeFBOImage[light->shadowLOD] ) ); + gl_forwardLightingShader_omniXYZ->SetUniform_ShadowClipMapBindless( + GL_BindToTMU( 7, tr.shadowClipCubeFBOImage[light->shadowLOD] ) ); } // bind u_RandomMap - GL_BindToTMU( gl_forwardLightingShader_omniXYZ->GetUniformLocation_RandomMap(), tr.randomNormalsImage ); + gl_forwardLightingShader_omniXYZ->SetUniform_RandomMapBindless( + GL_BindToTMU( 6, tr.randomNormalsImage ) + ); gl_forwardLightingShader_omniXYZ->SetRequiredVertexPointers(); @@ -1514,7 +1618,9 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_HeightMap(), pStage->bundle[TB_HEIGHTMAP].image[0] ); + gl_forwardLightingShader_projXYZ->SetUniform_HeightMapBindless( + GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) + ); } } @@ -1571,7 +1677,9 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, GL_CheckErrors(); // bind u_DiffuseMap - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_DiffuseMap(), pStage->bundle[TB_DIFFUSEMAP].image[0] ); + gl_forwardLightingShader_projXYZ->SetUniform_DiffuseMapBindless( + GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) + ); if ( pStage->type != stageType_t::ST_LIGHTMAP ) { @@ -1579,7 +1687,9 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, } // bind u_NormalMap - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_forwardLightingShader_projXYZ->SetUniform_NormalMapBindless( + GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) + ); // bind u_NormalScale if ( pStage->enableNormalMapping ) @@ -1591,7 +1701,9 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, } // bind u_MaterialMap - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_MaterialMap(), pStage->bundle[TB_MATERIALMAP].image[0] ); + gl_forwardLightingShader_projXYZ->SetUniform_MaterialMapBindless( + GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) + ); // FIXME: physical mapping is not implemented. if ( pStage->enableSpecularMapping ) @@ -1603,20 +1715,28 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, } // bind u_AttenuationMapXY - BindAnimatedImage( gl_forwardLightingShader_projXYZ->GetUniformLocation_AttenuationMapXY(), &attenuationXYStage->bundle[TB_COLORMAP]); + gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapXYBindless( + BindAnimatedImage( 3, &attenuationXYStage->bundle[TB_COLORMAP] ) ); // bind u_AttenuationMapZ - BindAnimatedImage( gl_forwardLightingShader_projXYZ->GetUniformLocation_AttenuationMapZ(), &attenuationZStage->bundle[TB_COLORMAP]); + gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapZBindless( + BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); // bind u_ShadowMap if ( shadowCompare ) { - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_ShadowMap0(), tr.shadowMapFBOImage[light->shadowLOD] ); - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_ShadowClipMap0(), tr.shadowClipMapFBOImage[light->shadowLOD] ); + gl_forwardLightingShader_projXYZ->SetUniform_ShadowMap0Bindless( + GL_BindToTMU( 5, tr.shadowMapFBOImage[light->shadowLOD] ) + ); + gl_forwardLightingShader_projXYZ->SetUniform_ShadowClipMap0Bindless( + GL_BindToTMU( 7, tr.shadowClipMapFBOImage[light->shadowLOD] ) + ); } // bind u_RandomMap - GL_BindToTMU( gl_forwardLightingShader_projXYZ->GetUniformLocation_RandomMap(), tr.randomNormalsImage ); + gl_forwardLightingShader_projXYZ->SetUniform_RandomMapBindless( + GL_BindToTMU( 6, tr.randomNormalsImage ) + ); gl_forwardLightingShader_projXYZ->SetRequiredVertexPointers(); @@ -1673,7 +1793,9 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_HeightMap(), pStage->bundle[TB_HEIGHTMAP].image[0] ); + gl_forwardLightingShader_directionalSun->SetUniform_HeightMapBindless( + GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) + ); } } @@ -1734,7 +1856,9 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef GL_CheckErrors(); // bind u_DiffuseMap - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_DiffuseMap(), pStage->bundle[TB_DIFFUSEMAP].image[0] ); + gl_forwardLightingShader_directionalSun->SetUniform_DiffuseMapBindless( + GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) + ); if ( pStage->type != stageType_t::ST_LIGHTMAP ) { @@ -1742,7 +1866,9 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef } // bind u_NormalMap - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_forwardLightingShader_directionalSun->SetUniform_NormalMapBindless( + GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) + ); // bind u_NormalScale if ( pStage->enableNormalMapping ) @@ -1754,7 +1880,9 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef } // bind u_MaterialMap - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_MaterialMap(), pStage->bundle[TB_MATERIALMAP].image[0] ); + gl_forwardLightingShader_directionalSun->SetUniform_MaterialMapBindless( + GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) + ); // FIXME: physical mapping is not implemented. if ( pStage->enableSpecularMapping ) @@ -1767,31 +1895,51 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef // bind u_ShadowMap if ( shadowCompare ) { - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowMap0(), tr.sunShadowMapFBOImage[0] ); - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowClipMap0(), tr.sunShadowClipMapFBOImage[0] ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap0Bindless( + GL_BindToTMU( 5, tr.sunShadowMapFBOImage[ 0 ] ) + ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap0Bindless( + GL_BindToTMU( 10, tr.sunShadowClipMapFBOImage[ 0 ] ) + ); if ( r_parallelShadowSplits->integer >= 1 ) { - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowMap1(), tr.sunShadowMapFBOImage[ 1 ] ); - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowClipMap1(), tr.sunShadowClipMapFBOImage[ 1 ] ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap1Bindless( + GL_BindToTMU( 6, tr.sunShadowMapFBOImage[ 1 ] ) + ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap1Bindless( + GL_BindToTMU( 11, tr.sunShadowClipMapFBOImage[ 1 ] ) + ); } if ( r_parallelShadowSplits->integer >= 2 ) { - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowMap2(), tr.sunShadowMapFBOImage[ 2 ] ); ; - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowClipMap2(), tr.sunShadowClipMapFBOImage[ 2 ] ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap2Bindless( + GL_BindToTMU( 7, tr.sunShadowMapFBOImage[ 2 ] ) + ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap2Bindless( + GL_BindToTMU( 12, tr.sunShadowClipMapFBOImage[ 2 ] ) + ); } if ( r_parallelShadowSplits->integer >= 3 ) { - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowMap3(), tr.sunShadowMapFBOImage[ 3 ] ); - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowClipMap3(), tr.sunShadowClipMapFBOImage[ 3 ] ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap3Bindless( + GL_BindToTMU( 8, tr.sunShadowMapFBOImage[ 3 ] ) + ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap3Bindless( + GL_BindToTMU( 13, tr.sunShadowClipMapFBOImage[ 3 ] ) + ); } if ( r_parallelShadowSplits->integer >= 4 ) { - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowMap4(), tr.sunShadowMapFBOImage[ 4 ] ); - GL_BindToTMU( gl_forwardLightingShader_directionalSun->GetUniformLocation_ShadowClipMap4(), tr.sunShadowClipMapFBOImage[ 4 ] ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap4Bindless( + GL_BindToTMU( 9, tr.sunShadowMapFBOImage[ 4 ] ) + ); + gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap4Bindless( + GL_BindToTMU( 14, tr.sunShadowClipMapFBOImage[ 4 ] ) + ); } } @@ -1806,6 +1954,10 @@ void Render_reflection_CB( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_reflection_CB ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + return; + } + GL_State( pStage->stateBits ); // choose right shader program ---------------------------------- @@ -1847,7 +1999,9 @@ void Render_reflection_CB( shaderStage_t *pStage ) } // bind u_NormalMap - GL_BindToTMU( gl_reflectionShader->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_reflectionShader->SetUniform_NormalMapBindless( + GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) + ); // bind u_NormalScale if ( pStage->enableNormalMapping ) @@ -1872,7 +2026,9 @@ void Render_reflection_CB( shaderStage_t *pStage ) // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_reflectionShader->GetUniformLocation_HeightMap(), pStage->bundle[TB_HEIGHTMAP].image[0] ); + gl_reflectionShader->SetUniform_HeightMapBindless( + GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) + ); } } @@ -1887,6 +2043,10 @@ void Render_skybox( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_skybox ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + return; + } + GL_State( pStage->stateBits ); gl_skyboxShader->BindProgram( pStage->deformIndex ); @@ -1897,7 +2057,9 @@ void Render_skybox( shaderStage_t *pStage ) gl_skyboxShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_ColorMap - GL_BindToTMU( gl_skyboxShader->GetUniformLocation_ColorMap(), pStage->bundle[TB_COLORMAP].image[0] ); + gl_skyboxShader->SetUniform_ColorMapCubeBindless( + GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) + ); // u_InverseLightFactor gl_skyboxShader->SetUniform_InverseLightFactor( tr.mapInverseLightFactor ); @@ -1913,6 +2075,10 @@ void Render_screen( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_screen ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + return; + } + GL_State( pStage->stateBits ); gl_screenShader->BindProgram( pStage->deformIndex ); @@ -1925,7 +2091,7 @@ void Render_screen( shaderStage_t *pStage ) gl_screenShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_CurrentMap - BindAnimatedImage( gl_screenShader->GetUniformLocation_CurrentMap(), &pStage->bundle[TB_COLORMAP]); + gl_screenShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); Tess_DrawElements(); @@ -1936,6 +2102,10 @@ void Render_portal( shaderStage_t *pStage ) { GLimp_LogComment( "--- Render_portal ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + return; + } + GL_State( pStage->stateBits ); // enable shader, set arrays @@ -1952,7 +2122,7 @@ void Render_portal( shaderStage_t *pStage ) gl_portalShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // bind u_CurrentMap - BindAnimatedImage( gl_portalShader->GetUniformLocation_CurrentMap(), &pStage->bundle[TB_COLORMAP] ); + gl_portalShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); Tess_DrawElements(); @@ -1966,6 +2136,10 @@ void Render_heatHaze( shaderStage_t *pStage ) GLimp_LogComment( "--- Render_heatHaze ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + return; + } + // remove alpha test stateBits = pStage->stateBits; stateBits &= ~GLS_ATEST_BITS; @@ -2025,7 +2199,9 @@ void Render_heatHaze( shaderStage_t *pStage ) R_BindFBO( tr.mainFBO[ 1 - backEnd.currentMainFBO ] ); // bind u_NormalMap - GL_BindToTMU( gl_heatHazeShader->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_heatHazeShader->SetUniform_NormalMapBindless( + GL_BindToTMU( 0, pStage->bundle[TB_NORMALMAP].image[0] ) + ); if ( pStage->enableNormalMapping ) { @@ -2039,7 +2215,9 @@ void Render_heatHaze( shaderStage_t *pStage ) } // bind u_CurrentMap - GL_BindToTMU( gl_heatHazeShader->GetUniformLocation_CurrentMap(), tr.currentRenderImage[backEnd.currentMainFBO] ); + gl_heatHazeShader->SetUniform_CurrentMapBindless( + GL_BindToTMU( 1, tr.currentRenderImage[backEnd.currentMainFBO] ) + ); gl_heatHazeShader->SetRequiredVertexPointers(); @@ -2047,7 +2225,9 @@ void Render_heatHaze( shaderStage_t *pStage ) // copy to foreground image R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); - GL_BindToTMU( gl_heatHazeShader->GetUniformLocation_CurrentMap(), tr.currentRenderImage[1 - backEnd.currentMainFBO] ); + gl_heatHazeShader->SetUniform_CurrentMapBindless( + GL_BindToTMU( 1, tr.currentRenderImage[1 - backEnd.currentMainFBO] ) + ); gl_heatHazeShader->SetUniform_DeformMagnitude( 0.0f ); Tess_DrawElements(); @@ -2062,6 +2242,10 @@ void Render_liquid( shaderStage_t *pStage ) GLimp_LogComment( "--- Render_liquid ---\n" ); + if ( materialSystem.generatingWorldCommandBuffer ) { + return; + } + // Tr3B: don't allow blend effects GL_State( pStage->stateBits & ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_DEPTHMASK_TRUE ) ); @@ -2102,13 +2286,13 @@ void Render_liquid( shaderStage_t *pStage ) } // bind u_CurrentMap - GL_BindToTMU( gl_liquidShader->GetUniformLocation_CurrentMap(), tr.currentRenderImage[backEnd.currentMainFBO] ); + gl_liquidShader->SetUniform_CurrentMapBindless( GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) ); // bind u_PortalMap - GL_BindToTMU( gl_liquidShader->GetUniformLocation_PortalMap(), tr.portalRenderImage ); + gl_liquidShader->SetUniform_PortalMapBindless( GL_BindToTMU( 1, tr.portalRenderImage ) ); // depth texture - GL_BindToTMU( gl_liquidShader->GetUniformLocation_DepthMap(), tr.currentDepthImage ); + gl_liquidShader->SetUniform_DepthMapBindless( GL_BindToTMU( 2, tr.currentDepthImage ) ); // bind u_HeightMap u_depthScale u_reliefOffsetBias if ( pStage->enableReliefMapping ) @@ -2122,12 +2306,12 @@ void Render_liquid( shaderStage_t *pStage ) // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - GL_BindToTMU( gl_liquidShader->GetUniformLocation_HeightMap(), pStage->bundle[TB_HEIGHTMAP].image[0] ); + gl_liquidShader->SetUniform_HeightMapBindless( GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) ); } } // bind u_NormalMap - GL_BindToTMU( gl_liquidShader->GetUniformLocation_NormalMap(), pStage->bundle[TB_NORMALMAP].image[0] ); + gl_liquidShader->SetUniform_NormalMapBindless( GL_BindToTMU( 3, pStage->bundle[TB_NORMALMAP].image[0] ) ); // bind u_NormalScale if ( pStage->enableNormalMapping ) @@ -2257,7 +2441,9 @@ static void Render_fog() gl_fogQuake3Shader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); // bind u_ColorMap - GL_BindToTMU( gl_fogQuake3Shader->GetUniformLocation_ColorMap(), tr.fogImage ); + gl_fogQuake3Shader->SetUniform_ColorMapBindless( + GL_BindToTMU( 0, tr.fogImage ) + ); gl_fogQuake3Shader->SetRequiredVertexPointers(); @@ -2508,7 +2694,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) Tess_ComputeTexMatrices =============== */ -static void Tess_ComputeTexMatrices( shaderStage_t *pStage ) +void Tess_ComputeTexMatrices( shaderStage_t *pStage ) { GLimp_LogComment( "--- Tess_ComputeTexMatrices ---\n" ); @@ -2589,6 +2775,12 @@ void Tess_StageIteratorColor() Tess_ComputeColor( pStage ); 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]; + } + pStage->colorRenderer( pStage ); } @@ -2815,7 +3007,7 @@ Render tesselated data */ void Tess_End() { - if ( ( tess.numIndexes == 0 || tess.numVertexes == 0 ) && tess.multiDrawPrimitives == 0 ) + if ( ( tess.numIndexes == 0 || tess.numVertexes == 0 ) && tess.multiDrawPrimitives == 0 && !tr.drawingSky ) { return; } diff --git a/src/engine/renderer/tr_sky.cpp b/src/engine/renderer/tr_sky.cpp index 687c123631..1cea18a5f5 100644 --- a/src/engine/renderer/tr_sky.cpp +++ b/src/engine/renderer/tr_sky.cpp @@ -26,19 +26,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //====================================================================================== -static void Tess_ComputeTexMatrices( shaderStage_t* pStage ) { - int i; - vec_t* matrix; - - GLimp_LogComment( "--- Tess_ComputeTexMatrices ---\n" ); - - for ( i = 0; i < MAX_TEXTURE_BUNDLES; i++ ) { - matrix = tess.svars.texMatrices[i]; - - RB_CalcTexMatrix( &pStage->bundle[i], matrix ); - } -} - /* ================ Tess_StageIteratorSky @@ -65,6 +52,8 @@ void Tess_StageIteratorSky() return; } + tr.drawingSky = false; + // Store the current projection, modelView and modelViewProjection matrices if we're drawing the skybox in a portal // since portals set up the projection matrix differently matrix_t currentProjectionMatrix; @@ -126,7 +115,9 @@ void Tess_StageIteratorSky() GL_State( GLS_DEFAULT ); // bind u_ColorMap - GL_BindToTMU( gl_skyboxShader->GetUniformLocation_ColorMap(), tess.surfaceShader->sky.outerbox ); + gl_skyboxShader->SetUniform_ColorMapCubeBindless( + GL_BindToTMU( 0, tess.surfaceShader->sky.outerbox ) + ); // Only render the outer skybox at this stage gl_skyboxShader->SetUniform_UseCloudMap( false ); @@ -149,7 +140,9 @@ void Tess_StageIteratorSky() gl_skyboxShader->SetUniform_TextureMatrix( tess.svars.texMatrices[TB_COLORMAP] ); - GL_BindToTMU( gl_skyboxShader->GetUniformLocation_CloudMap(), tess.surfaceShader->stages[stage]->bundle[TB_COLORMAP].image[0] ); + gl_skyboxShader->SetUniform_CloudMapBindless( + GL_BindToTMU( 1, tess.surfaceShader->stages[stage]->bundle[TB_COLORMAP].image[0] ) + ); uint32_t alphaTestBits = pStage->stateBits & GLS_ATEST_BITS; diff --git a/src/engine/renderer/tr_surface.cpp b/src/engine/renderer/tr_surface.cpp index 8eff30e39a..f1d7390b14 100644 --- a/src/engine/renderer/tr_surface.cpp +++ b/src/engine/renderer/tr_surface.cpp @@ -166,7 +166,6 @@ static bool Tess_SurfaceVBO( VBO_t *vbo, IBO_t *ibo, int numIndexes, int firstIn Tess_CheckVBOAndIBO( vbo, ibo ); - //lazy merge multidraws together bool mergeBack = false; bool mergeFront = false; @@ -195,11 +194,13 @@ static bool Tess_SurfaceVBO( VBO_t *vbo, IBO_t *ibo, int numIndexes, int firstIn else if ( mergeBack ) { tess.multiDrawIndexes[ tess.multiDrawPrimitives - 1 ] = firstIndexOffset; + tess.multiDrawOffsets[ tess.multiDrawPrimitives - 1 ] = (GLuint) firstIndex; tess.multiDrawCounts[ tess.multiDrawPrimitives - 1 ] += numIndexes; } else { tess.multiDrawIndexes[ tess.multiDrawPrimitives ] = firstIndexOffset; + tess.multiDrawOffsets[ tess.multiDrawPrimitives ] = (GLuint) firstIndex; tess.multiDrawCounts[ tess.multiDrawPrimitives ] = numIndexes; tess.multiDrawPrimitives++; diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index 7c72ad370e..656f5afaa8 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // tr_vbo.c #include "tr_local.h" +#include "Material.h" // "templates" for VBO vertex data layouts @@ -881,6 +882,7 @@ void R_BindIBO( IBO_t *ibo ) glState.currentIBO = ibo; + backEnd.pc.c_vboIndexBuffers++; } } @@ -1072,6 +1074,18 @@ static void R_InitLightUBO() } } +static void R_InitCommandQueueBuffers() { + if( glConfig2.SSBOAvailable ) { + materialsSSBO.GenBuffer(); + // drawcallStateSSBO.GenBuffer(); + } + + if( glConfig2.multiDrawIndirectAvailable ) { + // commandQueueBuffer.GenBuffer(); + commandBuffer.GenBuffer(); + } +} + /* ============ R_InitVBOs @@ -1117,6 +1131,8 @@ void R_InitVBOs() R_InitLightUBO(); + R_InitCommandQueueBuffers(); + GL_CheckErrors(); } @@ -1193,6 +1209,16 @@ void R_ShutdownVBOs() tr.dlightUBO = 0; } + if ( glConfig2.SSBOAvailable ) { + materialsSSBO.DelBuffer(); + // drawcallStateSSBO.DelBuffer(); + } + + if ( glConfig2.multiDrawIndirectAvailable ) { + // commandQueueBuffer.DelBuffer(); + commandBuffer.DelBuffer(); + } + tess.verts = tess.vertsBuffer = nullptr; tess.indexes = tess.indexesBuffer = nullptr; } diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 2698ef71a7..79860210d7 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #include "gl_shader.h" +#include "Material.h" static Cvar::Modified> r_showCluster( "r_showCluster", "print PVS cluster at current location", Cvar::CHEAT, false ); @@ -435,7 +436,7 @@ static void R_RecursiveWorldNode( bspNode_t *node, int planeBits, int decalBits do { // if the node wasn't marked as potentially visible, exit - if ( node->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] ) + if ( node->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] && !materialSystem.generatingWorldCommandBuffer ) { return; } diff --git a/src/engine/sys/sdl_glimp.cpp b/src/engine/sys/sdl_glimp.cpp index d818841d97..6e9ee4c797 100644 --- a/src/engine/sys/sdl_glimp.cpp +++ b/src/engine/sys/sdl_glimp.cpp @@ -1942,6 +1942,21 @@ static void GLimp_InitExtensions() // not required by any OpenGL version glConfig2.bindlessTexturesAvailable = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_bindless_texture, r_arb_bindless_texture->value ); + // made required in OpenGL 4.6 + glConfig2.shaderDrawParametersAvailable = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_shader_draw_parameters, r_arb_shader_draw_parameters->value ); + + // made required in OpenGL 4.3 + glConfig2.SSBOAvailable = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_shader_storage_buffer_object, r_arb_shader_storage_buffer_object->value ); + + // made required in OpenGL 4.0 + glConfig2.multiDrawIndirectAvailable = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_multi_draw_indirect, r_arb_multi_draw_indirect->value ); + + // not required by any OpenGL version + glConfig2.shaderInt64Available = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_gpu_shader_int64, r_arb_gpu_shader_int64->value ); + + glConfig2.materialSystemAvailable = glConfig2.shaderDrawParametersAvailable && glConfig2.SSBOAvailable && + glConfig2.multiDrawIndirectAvailable && glConfig2.bindlessTexturesAvailable; + GL_CheckErrors(); }