Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sm lights branching #255

Merged
merged 23 commits into from Jan 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a847b14
added option to use branching in shaders for shadow-casting point/spo…
dyunchik Dec 29, 2021
0246558
Modiffied ShadowMapFromCode sample to test branching for shadow-casti…
dyunchik Dec 29, 2021
ce2d709
added more point lights in ShadowMapFromCode sample to better test li…
dyunchik Dec 30, 2021
a13539c
Support for FineLightMaskGranularity with hlms_static_branch_shadow_m…
dyunchik Dec 30, 2021
6c76f8d
Support for FineLightMaskGranularity with hlms_static_branch_shadow_m…
dyunchik Dec 30, 2021
62fb30a
Use USE_STATIC_BRANCHING_FOR_SHADOWMAP_LIGHTS in ShadowMapFromCode sa…
dyunchik Dec 30, 2021
cb2e38c
Use USE_STATIC_BRANCHING_FOR_SHADOWMAP_LIGHTS in ShadowMapFromCode sa…
dyunchik Dec 30, 2021
af6863a
fixed sm lights branching for HLSL
dyunchik Jan 2, 2022
bba0738
fixed sm lights branching for glslvk
dyunchik Jan 3, 2022
2af1e3e
avoid unnessesary propeties to decrease shaders variants in sm lights…
dyunchik Jan 3, 2022
e4f9efd
minor shader optimization for sm lights branching technique
dyunchik Jan 3, 2022
3536c79
avoid 'unroll' attribute in hlsl shader of sm lights branching technique
dyunchik Jan 3, 2022
8d5d92f
fixed sm ligths branching technique for OpenGL
dyunchik Jan 4, 2022
0b2f234
Use consistent naming variables
darksylinc Jan 4, 2022
b6dc264
Fix ShadowMapFromCode w/out USE_STATIC_BRANCHING_FOR_SHADOWMAP_LIGHTS
darksylinc Jan 4, 2022
4e09afa
Use array of textures on all APIs
darksylinc Jan 4, 2022
51e191d
Fix shader compiler error when useStaticBranchShadowMapLights is on
darksylinc Jan 4, 2022
10d8da5
fixed texShadowMap array declaration in Metal
dyunchik Jan 4, 2022
b2677b6
Add restrictions to Hlms::setMaxShadowMapLights
darksylinc Jan 5, 2022
4e1a242
removed unused shadowmapIdx[]
dyunchik Jan 5, 2022
2faae0b
Merge branch 'sm_lights_branching'
darksylinc Jan 5, 2022
7568506
Merge branch 'sm_lights_branching'
darksylinc Jan 5, 2022
1d1ce16
Rename setMaxShadowMapLights to setStaticBranchingLights
darksylinc Jan 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Components/Hlms/Pbs/include/OgreHlmsPbs.h
Expand Up @@ -270,6 +270,8 @@ namespace Ogre
void postCommandBufferExecution( CommandBuffer *commandBuffer ) override;
void frameEnded() override;

void setStaticBranchingLights( bool staticBranchingLights ) override;

/** By default we see the reflection textures' mipmaps and store the largest one we found.
By calling resetIblSpecMipmap; you can reset this process thus if a reflection texture
with a large number of mipmaps was removed, these textures can be reevaluated
Expand Down
28 changes: 28 additions & 0 deletions Components/Hlms/Pbs/src/OgreHlmsPbs.cpp
Expand Up @@ -1732,6 +1732,8 @@ namespace Ogre

bool isPssmBlend = getProperty( HlmsBaseProp::PssmBlend ) != 0;
bool isPssmFade = getProperty( HlmsBaseProp::PssmFade ) != 0;
bool isStaticBranchShadowMapLights =
getProperty( HlmsBaseProp::StaticBranchShadowMapLights ) != 0;

bool isShadowCastingPointLight = false;

Expand Down Expand Up @@ -1852,6 +1854,12 @@ namespace Ogre
// float pssmFadePoint.
mapSize += 4;
}
if( isStaticBranchShadowMapLights )
{
// float numShadowMapPointLights;
// float numShadowMapSpotLights;
mapSize += 4 + 4;
}

mapSize = alignToNextMultiple<size_t>( mapSize, 16 );

Expand Down Expand Up @@ -2301,6 +2309,16 @@ namespace Ogre
// float pssmFadePoint
*passBufferPtr++ = *shadowNode->getPssmFade( 0 );
}
if( isStaticBranchShadowMapLights )
{
// float numShadowMapPointLights;
// float numShadowMapSpotLights;
*reinterpret_cast<uint32 * RESTRICT_ALIAS>( passBufferPtr ) = mRealShadowMapPointLights;
passBufferPtr++;
*reinterpret_cast<uint32 * RESTRICT_ALIAS>( passBufferPtr ) = mRealShadowMapSpotLights;
passBufferPtr++;
numPssmBlendsAndFade += 2;
}

passBufferPtr += alignToNextMultiple<size_t>( numPssmSplits + numPssmBlendsAndFade, 4 ) -
( numPssmSplits + numPssmBlendsAndFade );
Expand Down Expand Up @@ -3603,6 +3621,16 @@ namespace Ogre
mCurrentPassBuffer = 0;
}
//-----------------------------------------------------------------------------------
void HlmsPbs::setStaticBranchingLights( bool staticBranchingLights )
{
if( staticBranchingLights )
{
// Make sure we calculate light positions in pixel shaders
setShadowReceiversInPixelShader( true );
}
Hlms::setStaticBranchingLights( staticBranchingLights );
}
//-----------------------------------------------------------------------------------
void HlmsPbs::resetIblSpecMipmap( uint8 numMipmaps )
{
if( numMipmaps != 0u )
Expand Down
36 changes: 36 additions & 0 deletions OgreMain/include/OgreHlms.h
Expand Up @@ -211,11 +211,14 @@ namespace Ogre
HlmsManager *mHlmsManager;

LightGatheringMode mLightGatheringMode;
bool mStaticBranchingLights;
uint16 mNumLightsLimit;
uint16 mNumAreaApproxLightsLimit;
uint16 mNumAreaLtcLightsLimit;
uint32 mAreaLightsGlobalLightListStart;
uint32 mRealNumDirectionalLights;
uint32 mRealShadowMapPointLights;
uint32 mRealShadowMapSpotLights;
uint32 mRealNumAreaApproxLightsWithMask;
uint32 mRealNumAreaApproxLights;
uint32 mRealNumAreaLtcLights;
Expand Down Expand Up @@ -524,6 +527,38 @@ namespace Ogre
void setMaxNonCasterDirectionalLights( uint16 maxLights );
uint16 getMaxNonCasterDirectionalLights() const { return mNumLightsLimit; }

/** By default shadow-caster spot and point lights are hardcoded into shaders.

This means that if you have 8 spot/point lights and then you add a 9th one,
a whole new set of shaders will be created.
Even more if you have a combination of 3 spot and 5 point lights and the combination
has changed to 4 spot and 4 point lights then you'll get the next set of shaders

This setting allows you to tremendously reduce the amount of shader permutations
by forcing Ogre to switching to static branching with an upper limit to the max
number of shadow-casting spot or point lights.

See Hlms::setAreaLightForwardSettings
@remarks
All point and spot lights must share the same hlms_shadowmap atlas

This is mostly an D3D11 / HLSL SM 5.0 restriction
(https://github.com/OGRECave/ogre-next/pull/255) but it may also help with
performance in other APIs.

If multiple atlas support is needed, using Texture2DArrays may be a good solution,
although it is currently untested and may need additional fixes to get it working

@param maxShadowMapLights
Maximum number of shadow-caster spot and point lights.
0 to allow unlimited number of lights, at the cost of shader recompilations
when spot or point lights are added or removed or their combination are changed.

Default value is 0.
*/
virtual void setStaticBranchingLights( bool staticBranchingLights );
bool getStaticBranchingLights( void ) const { return mStaticBranchingLights; }

/** Area lights use regular Forward.
@param areaLightsApproxLimit
Maximum number of area approx lights that will be considered by the shader.
Expand Down Expand Up @@ -888,6 +923,7 @@ namespace Ogre
static const IdString DualParaboloidMapping;
static const IdString InstancedStereo;
static const IdString StaticBranchLights;
static const IdString StaticBranchShadowMapLights;
static const IdString NumShadowMapLights;
static const IdString NumShadowMapTextures;
static const IdString PssmSplits;
Expand Down
121 changes: 91 additions & 30 deletions OgreMain/src/OgreHlms.cpp
Expand Up @@ -132,6 +132,8 @@ namespace Ogre
const IdString HlmsBaseProp::DualParaboloidMapping = IdString( "hlms_dual_paraboloid_mapping" );
const IdString HlmsBaseProp::InstancedStereo = IdString( "hlms_instanced_stereo" );
const IdString HlmsBaseProp::StaticBranchLights = IdString( "hlms_static_branch_lights" );
const IdString HlmsBaseProp::StaticBranchShadowMapLights =
IdString( "hlms_static_branch_shadow_map_lights" );
const IdString HlmsBaseProp::NumShadowMapLights = IdString( "hlms_num_shadow_map_lights" );
const IdString HlmsBaseProp::NumShadowMapTextures = IdString( "hlms_num_shadow_map_textures" );
const IdString HlmsBaseProp::PssmSplits = IdString( "hlms_pssm_splits" );
Expand Down Expand Up @@ -249,6 +251,7 @@ namespace Ogre
mDataFolder( dataFolder ),
mHlmsManager( 0 ),
mLightGatheringMode( LightGatherForward ),
mStaticBranchingLights( false ),
mNumLightsLimit( 0u ),
mNumAreaApproxLightsLimit( 1u ),
mNumAreaLtcLightsLimit( 1u ),
Expand Down Expand Up @@ -1679,6 +1682,11 @@ namespace Ogre
//-----------------------------------------------------------------------------------
void Hlms::setMaxNonCasterDirectionalLights( uint16 maxLights ) { mNumLightsLimit = maxLights; }
//-----------------------------------------------------------------------------------
void Hlms::setStaticBranchingLights( bool staticBranchingLights )
{
mStaticBranchingLights = staticBranchingLights;
}
//-----------------------------------------------------------------------------------
void Hlms::setAreaLightForwardSettings( uint16 areaLightsApproxLimit, uint16 areaLightsLtcLimit )
{
mNumAreaApproxLightsLimit = areaLightsApproxLimit;
Expand Down Expand Up @@ -2600,6 +2608,7 @@ namespace Ogre
{
size_t numShadowMapLights = 0u;
size_t numPssmSplits = 0;
bool useStaticBranchShadowMapLights = false;

if( shadowNode )
{
Expand Down Expand Up @@ -2630,6 +2639,13 @@ namespace Ogre
setProperty( HlmsBaseProp::NumShadowMapTextures,
static_cast<int32>( contiguousShadowMapTex.size() ) );

useStaticBranchShadowMapLights =
mStaticBranchingLights && numShadowMapLights > numPssmSplits;
if( useStaticBranchShadowMapLights )
setProperty( HlmsBaseProp::StaticBranchShadowMapLights, 1 );
mRealShadowMapPointLights = 0u;
mRealShadowMapSpotLights = 0u;

{
const Ogre::CompositorShadowNodeDef *shadowNodeDef = shadowNode->getDefinition();

Expand Down Expand Up @@ -2660,8 +2676,9 @@ namespace Ogre
static_cast<int32>( shadowNode->getIndexToContiguousShadowMapTex(
shadowMapTexIdx ) ) );

if( shadowTexDef->uvOffset != Vector2::ZERO ||
shadowTexDef->uvLength != Vector2::UNIT_SCALE )
if( ( shadowTexDef->uvOffset != Vector2::ZERO ||
shadowTexDef->uvLength != Vector2::UNIT_SCALE ) ||
useStaticBranchShadowMapLights )
{
propName.resize( basePropSize );
propName.a( "_uvs_fulltex" );
Expand Down Expand Up @@ -2708,18 +2725,8 @@ namespace Ogre
setProperty( propName.c_str(), shadowTexDef->arrayIdx );

const Light *light = shadowNode->getLightAssociatedWith( shadowMapTexIdx );
if( light->getType() == Light::LT_DIRECTIONAL )
{
propName.resize( basePropSize );
propName.a( "_is_directional_light" );
setProperty( propName.c_str(), 1 );
}
else if( light->getType() == Light::LT_POINT )
if( useStaticBranchShadowMapLights )
{
propName.resize( basePropSize );
propName.a( "_is_point_light" );
setProperty( propName.c_str(), 1 );

fractPart = modff( (float)shadowTexDef->uvLength.x, &intPart );
propName.resize( basePropSize );
propName.a( "_uv_length_x_int" );
Expand All @@ -2735,12 +2742,58 @@ namespace Ogre
propName.resize( basePropSize );
propName.a( "_uv_length_y_fract" );
setProperty( propName.c_str(), ( int32 )( fractPart * 100000.0f ) );

if( light->getType() == Light::LT_DIRECTIONAL )
{
propName.resize( basePropSize );
propName.a( "_is_directional_light" );
setProperty( propName.c_str(), 1 );
}
else if( light->getType() == Light::LT_POINT )
{
++mRealShadowMapPointLights;
}
else if( light->getType() == Light::LT_SPOTLIGHT )
{
++mRealShadowMapSpotLights;
}
}
else if( light->getType() == Light::LT_SPOTLIGHT )
else
{
propName.resize( basePropSize );
propName.a( "_is_spot" );
setProperty( propName.c_str(), 1 );
if( light->getType() == Light::LT_DIRECTIONAL )
{
propName.resize( basePropSize );
propName.a( "_is_directional_light" );
setProperty( propName.c_str(), 1 );
}
else if( light->getType() == Light::LT_POINT )
{
propName.resize( basePropSize );
propName.a( "_is_point_light" );
setProperty( propName.c_str(), 1 );

fractPart = modff( (float)shadowTexDef->uvLength.x, &intPart );
propName.resize( basePropSize );
propName.a( "_uv_length_x_int" );
setProperty( propName.c_str(), (int32)intPart );
propName.resize( basePropSize );
propName.a( "_uv_length_x_fract" );
setProperty( propName.c_str(), ( int32 )( fractPart * 100000.0f ) );

fractPart = modff( (float)shadowTexDef->uvLength.y, &intPart );
propName.resize( basePropSize );
propName.a( "_uv_length_y_int" );
setProperty( propName.c_str(), (int32)intPart );
propName.resize( basePropSize );
propName.a( "_uv_length_y_fract" );
setProperty( propName.c_str(), ( int32 )( fractPart * 100000.0f ) );
}
else if( light->getType() == Light::LT_SPOTLIGHT )
{
propName.resize( basePropSize );
propName.a( "_is_spot" );
setProperty( propName.c_str(), 1 );
}
}

++shadowMapTexIdx;
Expand Down Expand Up @@ -2926,8 +2979,8 @@ namespace Ogre
numLightsPerType[Light::LT_POINT] + numLightsPerType[Light::LT_SPOTLIGHT] );
setProperty( HlmsBaseProp::LightsSpotParams, numLightsPerType[Light::LT_SPOTLIGHT] );

if( numLightsPerType[Light::LT_POINT] && //
!numLightsPerType[Light::LT_DIRECTIONAL] && //
if( !useStaticBranchShadowMapLights && numLightsPerType[Light::LT_POINT] && //
!numLightsPerType[Light::LT_DIRECTIONAL] && //
!numLightsPerType[Light::LT_SPOTLIGHT] )
{
setProperty( HlmsBaseProp::AllPointLights, 1 );
Expand Down Expand Up @@ -3012,18 +3065,26 @@ namespace Ogre
}
}

// Deal with rest of non-caster directional lights
shadowMapLightIdx += numLightsPerType[Light::LT_DIRECTIONAL] - shadowCasterDirectional;

// Deal with the rest of the casting lights (point & spot)
const int32 numLights = numLightsPerType[Light::LT_SPOTLIGHT];
for( int32 i = numLightsPerType[Light::LT_DIRECTIONAL]; i < numLights; ++i )
if( useStaticBranchShadowMapLights )
{
propName.resize( basePropNameSize );
propName.a( shadowMapIdx, "_light_idx" ); // hlms_shadowmap0_light_idx
setProperty( propName.c_str(), shadowMapLightIdx );
++shadowMapIdx;
++shadowMapLightIdx;
setProperty( HlmsBaseProp::LightsPoint, 0 );
}
else
{
// Deal with rest of non-caster directional lights
shadowMapLightIdx +=
numLightsPerType[Light::LT_DIRECTIONAL] - shadowCasterDirectional;

// Deal with the rest of the casting lights (point & spot)
const int32 numLights = numLightsPerType[Light::LT_SPOTLIGHT];
for( int32 i = numLightsPerType[Light::LT_DIRECTIONAL]; i < numLights; ++i )
{
propName.resize( basePropNameSize );
propName.a( shadowMapIdx, "_light_idx" ); // hlms_shadowmap0_light_idx
setProperty( propName.c_str(), shadowMapLightIdx );
++shadowMapIdx;
++shadowMapLightIdx;
}
}
}
}
Expand Down