Browse Source

Shadow cascade count refactoring

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
451f10f7ae

+ 24 - 28
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -227,45 +227,41 @@ Error GrManagerImpl::initInstance()
 	ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
 	ci.pApplicationInfo = &app;
 
-	// Validation layers
-	static Array<const char*, 1> LAYERS = {"VK_LAYER_KHRONOS_validation"};
-	Array<const char*, LAYERS.getSize()> layersToEnable; // Keep it alive in the stack
-	if(m_config->getGrValidation() || m_config->getGrDebugPrintf())
+	// Instance layers
+	DynamicArrayAuto<const char*> layersToEnable(getAllocator());
 	{
-		uint32_t count;
-		vkEnumerateInstanceLayerProperties(&count, nullptr);
+		U32 layerCount;
+		vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
 
-		if(count)
+		if(layerCount)
 		{
-			DynamicArrayAuto<VkLayerProperties> layerProps(getAllocator());
-			layerProps.create(count);
+			DynamicArrayAuto<VkLayerProperties> layerProps(getAllocator(), layerCount);
+			vkEnumerateInstanceLayerProperties(&layerCount, &layerProps[0]);
 
-			vkEnumerateInstanceLayerProperties(&count, &layerProps[0]);
-
-			U32 layersToEnableCount = 0;
-			for(const char* c : LAYERS)
+			ANKI_VK_LOGV("Found the following instance layers:");
+			for(const VkLayerProperties& layer : layerProps)
 			{
-				for(U32 i = 0; i < count; ++i)
+				ANKI_VK_LOGV("\t%s", layer.layerName);
+				CString layerName = layer.layerName;
+
+				static const char* validationName = "VK_LAYER_KHRONOS_validation";
+				if((m_config->getGrValidation() || m_config->getGrDebugPrintf()) && layerName == validationName)
 				{
-					if(CString(c) == layerProps[i].layerName)
-					{
-						layersToEnable[layersToEnableCount++] = c;
-						break;
-					}
+					layersToEnable.emplaceBack(validationName);
 				}
 			}
+		}
 
-			if(layersToEnableCount)
+		if(layersToEnable.getSize())
+		{
+			ANKI_VK_LOGI("Will enable the following instance layers:");
+			for(const char* name : layersToEnable)
 			{
-				ANKI_VK_LOGI("Will enable the following layers:");
-				for(U32 i = 0; i < layersToEnableCount; ++i)
-				{
-					ANKI_VK_LOGI("\t%s", layersToEnable[i]);
-				}
-
-				ci.enabledLayerCount = layersToEnableCount;
-				ci.ppEnabledLayerNames = &layersToEnable[0];
+				ANKI_VK_LOGI("\t%s", name);
 			}
+
+			ci.enabledLayerCount = layersToEnable.getSize();
+			ci.ppEnabledLayerNames = &layersToEnable[0];
 		}
 	}
 

+ 1 - 1
AnKi/Renderer/ConfigVars.defs.h

@@ -63,7 +63,7 @@ ANKI_CONFIG_VAR_U32(RShadowMappingTileResolution, ((ANKI_PLATFORM_MOBILE) ? 128
 					"Shadowmapping tile resolution")
 ANKI_CONFIG_VAR_U32(RShadowMappingTileCountPerRowOrColumn, 16, 1, 256,
 					"Shadowmapping atlas will have this number squared number of tiles")
-ANKI_CONFIG_VAR_U32(RShadowMappingScratchTileCountX, 4 * (MAX_SHADOW_CASCADES2 + 2), 1, 256,
+ANKI_CONFIG_VAR_U32(RShadowMappingScratchTileCountX, 4 * (MAX_SHADOW_CASCADES + 2), 1, 256,
 					"Number of tiles of the scratch buffer in X")
 ANKI_CONFIG_VAR_U32(RShadowMappingScratchTileCountY, 4, 1, 256, "Number of tiles of the scratch buffer in Y")
 

+ 3 - 3
AnKi/Renderer/RenderQueue.h

@@ -163,8 +163,8 @@ static_assert(std::is_trivially_destructible<SpotLightQueueElement>::value == tr
 class DirectionalLightQueueElement final
 {
 public:
-	Array<Mat4, MAX_SHADOW_CASCADES2> m_textureMatrices;
-	Array<RenderQueue*, MAX_SHADOW_CASCADES2> m_shadowRenderQueues;
+	Array<Mat4, MAX_SHADOW_CASCADES> m_textureMatrices;
+	Array<RenderQueue*, MAX_SHADOW_CASCADES> m_shadowRenderQueues;
 	RenderQueueDrawCallback m_drawCallback;
 	const void* m_drawCallbackUserData;
 	U64 m_uuid; ///< Zero means that there is no dir light
@@ -172,7 +172,7 @@ public:
 	Vec3 m_direction;
 	F32 m_effectiveShadowDistance;
 	F32 m_shadowCascadesDistancePower;
-	U8 m_shadowCascadeCount; ///< Zero means that it doesn't case any shadows
+	U8 m_shadowCascadeCount; ///< Zero means that it doesn't cast any shadows.
 	U8 m_shadowLayer; ///< Renderer internal.
 
 	DirectionalLightQueueElement()

+ 9 - 9
AnKi/Renderer/ShadowMapping.cpp

@@ -524,15 +524,15 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 	{
 		DirectionalLightQueueElement& light = ctx.m_renderQueue->m_directionalLight;
 
-		Array<U64, MAX_SHADOW_CASCADES2> timestamps;
-		Array<U32, MAX_SHADOW_CASCADES2> cascadeIndices;
-		Array<U32, MAX_SHADOW_CASCADES2> drawcallCounts;
-		Array<UVec4, MAX_SHADOW_CASCADES2> atlasViewports;
-		Array<UVec4, MAX_SHADOW_CASCADES2> scratchViewports;
-		Array<TileAllocatorResult, MAX_SHADOW_CASCADES2> subResults;
-		Array<U32, MAX_SHADOW_CASCADES2> lods;
-		Array<U32, MAX_SHADOW_CASCADES2> renderQueueElementsLods;
-		Array<Bool, MAX_SHADOW_CASCADES2> blurAtlass;
+		Array<U64, MAX_SHADOW_CASCADES> timestamps;
+		Array<U32, MAX_SHADOW_CASCADES> cascadeIndices;
+		Array<U32, MAX_SHADOW_CASCADES> drawcallCounts;
+		Array<UVec4, MAX_SHADOW_CASCADES> atlasViewports;
+		Array<UVec4, MAX_SHADOW_CASCADES> scratchViewports;
+		Array<TileAllocatorResult, MAX_SHADOW_CASCADES> subResults;
+		Array<U32, MAX_SHADOW_CASCADES> lods;
+		Array<U32, MAX_SHADOW_CASCADES> renderQueueElementsLods;
+		Array<Bool, MAX_SHADOW_CASCADES> blurAtlass;
 
 		U32 activeCascades = 0;
 

+ 1 - 0
AnKi/Scene/CameraNode.cpp

@@ -73,6 +73,7 @@ void CameraNode::initCommon(FrustumType frustumType)
 	frc->setEnabledVisibilityTests(visibilityFlags);
 	frc->setLodDistance(0, getConfig().getLod0MaxDistance());
 	frc->setLodDistance(1, getConfig().getLod1MaxDistance());
+	frc->setShadowCascadeCount(getConfig().getSceneShadowCascadeCount());
 
 	// Extended frustum for RT
 	if(getSceneGraph().getGrManager().getDeviceCapabilities().m_rayTracingEnabled

+ 18 - 16
AnKi/Scene/Components/FrustumComponent.h

@@ -29,8 +29,6 @@ enum class FrustumComponentVisibilityTestFlag : U32
 	SHADOW_CASTERS = 1 << 3, ///< Render components that cast shadow
 	POINT_LIGHT_SHADOWS_ENABLED = 1 << 4,
 	SPOT_LIGHT_SHADOWS_ENABLED = 1 << 5,
-	DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES = 1 << 6,
-	DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE = 1 << 7,
 	REFLECTION_PROBES = 1 << 8,
 	REFLECTION_PROXIES = 1 << 9,
 	OCCLUDERS = 1 << 10,
@@ -47,13 +45,12 @@ enum class FrustumComponentVisibilityTestFlag : U32
 	SKYBOX = 1 << 21,
 
 	ALL = RENDER_COMPONENTS | LIGHT_COMPONENTS | LENS_FLARE_COMPONENTS | SHADOW_CASTERS | POINT_LIGHT_SHADOWS_ENABLED
-		  | SPOT_LIGHT_SHADOWS_ENABLED | DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES | DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE
-		  | REFLECTION_PROBES | REFLECTION_PROXIES | OCCLUDERS | DECALS | FOG_DENSITY_COMPONENTS
-		  | GLOBAL_ILLUMINATION_PROBES | EARLY_Z | GENERIC_COMPUTE_JOB_COMPONENTS | RAY_TRACING_SHADOWS | RAY_TRACING_GI
-		  | RAY_TRACING_REFLECTIONS | RAY_TRACING_PATH_TRACING | UI_COMPONENTS | SKYBOX,
+		  | SPOT_LIGHT_SHADOWS_ENABLED | REFLECTION_PROBES | REFLECTION_PROXIES | OCCLUDERS | DECALS
+		  | FOG_DENSITY_COMPONENTS | GLOBAL_ILLUMINATION_PROBES | EARLY_Z | GENERIC_COMPUTE_JOB_COMPONENTS
+		  | RAY_TRACING_SHADOWS | RAY_TRACING_GI | RAY_TRACING_REFLECTIONS | RAY_TRACING_PATH_TRACING | UI_COMPONENTS
+		  | SKYBOX,
 
-	ALL_SHADOWS_ENABLED =
-		POINT_LIGHT_SHADOWS_ENABLED | SPOT_LIGHT_SHADOWS_ENABLED | DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES,
+	ALL_SHADOWS_ENABLED = POINT_LIGHT_SHADOWS_ENABLED | SPOT_LIGHT_SHADOWS_ENABLED,
 
 	ALL_RAY_TRACING = RAY_TRACING_SHADOWS | RAY_TRACING_GI | RAY_TRACING_REFLECTIONS | RAY_TRACING_PATH_TRACING
 };
@@ -334,7 +331,17 @@ public:
 	F32 computeShadowCascadeDistance(U32 cascadeIdx) const
 	{
 		return anki::computeShadowCascadeDistance(cascadeIdx, m_shadowCascadesDistancePower,
-												  getEffectiveShadowDistance(), getCascadeCount());
+												  getEffectiveShadowDistance(), getShadowCascadeCount());
+	}
+
+	[[nodiscard]] U32 getShadowCascadeCount() const
+	{
+		return m_shadowCascadeCount;
+	}
+
+	void setShadowCascadeCount(U32 count)
+	{
+		m_shadowCascadeCount = U8(min(count, MAX_SHADOW_CASCADES));
 	}
 
 	const ConvexHullShape& getPerspectiveBoundingShapeWorldSpace() const
@@ -426,6 +433,8 @@ private:
 
 	Array<F32, MAX_LOD_COUNT - 1> m_maxLodDistances = {};
 
+	U8 m_shadowCascadeCount = 0;
+
 	class
 	{
 	public:
@@ -439,13 +448,6 @@ private:
 	Bool m_trfMarkedForUpdate : 1;
 
 	Bool updateInternal();
-
-	U32 getCascadeCount() const
-	{
-		return !!(m_flags & FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES)
-				   ? MAX_SHADOW_CASCADES2
-				   : 1;
-	}
 };
 /// @}
 

+ 2 - 2
AnKi/Scene/Components/LightComponent.cpp

@@ -70,7 +70,7 @@ void LightComponent::setupDirectionalLightQueueElement(const FrustumComponent& f
 													   WeakArray<FrustumComponent> cascadeFrustumComponents) const
 {
 	ANKI_ASSERT(m_type == LightComponentType::DIRECTIONAL);
-	ANKI_ASSERT(cascadeFrustumComponents.getSize() <= MAX_SHADOW_CASCADES2);
+	ANKI_ASSERT(cascadeFrustumComponents.getSize() <= MAX_SHADOW_CASCADES);
 
 	const U32 shadowCascadeCount = cascadeFrustumComponents.getSize();
 
@@ -101,7 +101,7 @@ void LightComponent::setupDirectionalLightQueueElement(const FrustumComponent& f
 		const F32 fovY = frustumComp.getFovY();
 
 		// Compute a sphere per cascade
-		Array<Sphere, MAX_SHADOW_CASCADES2> boundingSpheres;
+		Array<Sphere, MAX_SHADOW_CASCADES> boundingSpheres;
 		for(U32 i = 0; i < shadowCascadeCount; ++i)
 		{
 			// Compute the center of the sphere

+ 2 - 0
AnKi/Scene/ConfigVars.defs.h

@@ -7,6 +7,8 @@ ANKI_CONFIG_VAR_GROUP(SCENE)
 
 ANKI_CONFIG_VAR_F32(Lod0MaxDistance, 20.0f, 1.0f, MAX_F32, "Distance that will be used to calculate the LOD 0")
 ANKI_CONFIG_VAR_F32(Lod1MaxDistance, 40.0f, 2.0f, MAX_F32, "Distance that will be used to calculate the LOD 1")
+ANKI_CONFIG_VAR_U8(SceneShadowCascadeCount, (ANKI_OS_ANDROID) ? 2 : MAX_SHADOW_CASCADES, 1, MAX_SHADOW_CASCADES,
+				   "Max number of shadow cascades for directional lights")
 
 ANKI_CONFIG_VAR_U32(SceneOctreeMaxDepth, 5, 2, 10, "The max depth of the octree")
 ANKI_CONFIG_VAR_F32(SceneEarlyZDistance, 10.0f, 0.0f, MAX_F32,

+ 5 - 5
AnKi/Scene/GlobalIlluminationProbeNode.cpp

@@ -12,10 +12,6 @@
 
 namespace anki {
 
-constexpr FrustumComponentVisibilityTestFlag FRUSTUM_TEST_FLAGS =
-	FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS
-	| FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE;
-
 /// Feedback component
 class GlobalIlluminationProbeNode::MoveFeedbackComponent : public SceneComponent
 {
@@ -122,6 +118,7 @@ GlobalIlluminationProbeNode::GlobalIlluminationProbeNode(SceneGraph* scene, CStr
 		frc->setWorldTransform(m_cubeFaceTransforms[i]);
 		frc->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 		frc->setEffectiveShadowDistance(getConfig().getSceneReflectionProbeShadowEffectiveDistance());
+		frc->setShadowCascadeCount(1);
 	}
 
 	// Spatial component
@@ -184,8 +181,11 @@ Error GlobalIlluminationProbeNode::frameUpdate([[maybe_unused]] Second prevUpdat
 	// Check the reflection probe component and if it's marked for rendering enable the frustum components
 	const GlobalIlluminationProbeComponent& gic = getFirstComponentOfType<GlobalIlluminationProbeComponent>();
 
+	constexpr FrustumComponentVisibilityTestFlag frustumTestFlags =
+		FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS;
+
 	const FrustumComponentVisibilityTestFlag testFlags =
-		(gic.getMarkedForRendering()) ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
+		(gic.getMarkedForRendering()) ? frustumTestFlags : FrustumComponentVisibilityTestFlag::NONE;
 
 	iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) {
 		frc.setEnabledVisibilityTests(testFlags);

+ 5 - 5
AnKi/Scene/ReflectionProbeNode.cpp

@@ -13,10 +13,6 @@
 
 namespace anki {
 
-const FrustumComponentVisibilityTestFlag FRUSTUM_TEST_FLAGS =
-	FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS
-	| FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE;
-
 /// Feedback component
 class ReflectionProbeNode::MoveFeedbackComponent : public SceneComponent
 {
@@ -112,6 +108,7 @@ ReflectionProbeNode::ReflectionProbeNode(SceneGraph* scene, CString name)
 		frc->setWorldTransform(m_frustumTransforms[i]);
 		frc->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 		frc->setEffectiveShadowDistance(getConfig().getSceneReflectionProbeShadowEffectiveDistance());
+		frc->setShadowCascadeCount(1);
 	}
 
 	// Reflection probe comp
@@ -174,8 +171,11 @@ Error ReflectionProbeNode::frameUpdate([[maybe_unused]] Second prevUpdateTime, [
 	// Check the reflection probe component and if it's marked for rendering enable the frustum components
 	const ReflectionProbeComponent& reflc = getFirstComponentOfType<ReflectionProbeComponent>();
 
+	constexpr FrustumComponentVisibilityTestFlag frustumTestFlags =
+		FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS;
+
 	const FrustumComponentVisibilityTestFlag testFlags =
-		reflc.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
+		reflc.getMarkedForRendering() ? frustumTestFlags : FrustumComponentVisibilityTestFlag::NONE;
 
 	iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) {
 		frc.setEnabledVisibilityTests(testFlags);

+ 4 - 11
AnKi/Scene/Visibility.cpp

@@ -470,23 +470,16 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 			{
 				ANKI_ASSERT(lc->getShadowEnabled() == true && "Only with shadow for now");
 
-				U32 cascadeCount;
-				if(ANKI_UNLIKELY(!castsShadow))
+				U32 cascadeCount = max(testedFrc.getShadowCascadeCount(), U32(castsShadow));
+				if(!castsShadow)
 				{
 					cascadeCount = 0;
 				}
-				else if(!!(enabledVisibilityTests
-						   & FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE))
-				{
-					cascadeCount = 1;
-				}
 				else
 				{
-					ANKI_ASSERT(!!(enabledVisibilityTests
-								   & FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES));
-					cascadeCount = MAX_SHADOW_CASCADES2;
+					cascadeCount = max<U32>(testedFrc.getShadowCascadeCount(), 1);
 				}
-				ANKI_ASSERT(cascadeCount <= MAX_SHADOW_CASCADES2);
+				ANKI_ASSERT(cascadeCount <= MAX_SHADOW_CASCADES);
 
 				// Create some dummy frustum components and initialize them
 				WeakArray<FrustumComponent> cascadeFrustumComponents(

+ 3 - 3
AnKi/Shaders/Include/ClusteredShadingTypes.h

@@ -36,7 +36,7 @@ const U32 MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES = 8u;
 
 // Other consts
 const ANKI_RP F32 CLUSTER_OBJECT_FRUSTUM_NEAR_PLANE = 0.1f / 4.0f; ///< Near plane of various clusterer object frustums.
-const U32 MAX_SHADOW_CASCADES2 = 4u;
+const U32 MAX_SHADOW_CASCADES = 4u;
 const ANKI_RP F32 SUBSURFACE_MIN = 0.01f;
 
 /// Point light.
@@ -117,9 +117,9 @@ struct DirectionalLight
 	U32 m_shadowLayer; ///< Shadow layer used in RT shadows. Also used to show that it doesn't cast shadow.
 	U32 m_padding0;
 
-	Mat4 m_textureMatrices[MAX_SHADOW_CASCADES2];
+	Mat4 m_textureMatrices[MAX_SHADOW_CASCADES];
 };
-const U32 _ANKI_SIZEOF_DirectionalLight = 3u * ANKI_SIZEOF(Vec4) + MAX_SHADOW_CASCADES2 * ANKI_SIZEOF(Mat4);
+const U32 _ANKI_SIZEOF_DirectionalLight = 3u * ANKI_SIZEOF(Vec4) + MAX_SHADOW_CASCADES * ANKI_SIZEOF(Mat4);
 ANKI_SHADER_STATIC_ASSERT(sizeof(DirectionalLight) == _ANKI_SIZEOF_DirectionalLight);
 
 /// Representation of a reflection probe.

+ 1 - 1
AnKi/Shaders/LightFunctions.glsl

@@ -235,7 +235,7 @@ ANKI_RP F32 computeShadowFactorDirLight(DirectionalLight light, U32 cascadeIdx,
 #define ANKI_FAST_CASCADES_WORKAROUND 1 // Doesn't make sense but it's super fast
 
 #if ANKI_FAST_CASCADES_WORKAROUND
-	// Assumes MAX_SHADOW_CASCADES2 is 4
+	// Assumes MAX_SHADOW_CASCADES is 4
 	Mat4 lightProjectionMat;
 	switch(cascadeIdx)
 	{