Browse Source

Fix a bug in draw stats

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
61f5e7de87

+ 1 - 1
AnKi/Renderer/ClusterBinning2.cpp

@@ -328,7 +328,7 @@ void ClusterBinning2::writeClusterUniformsInternal()
 		out.m_shadowCascadeDistances = Vec4(g_shadowCascade0DistanceCVar.get(), g_shadowCascade1DistanceCVar.get(),
 		out.m_shadowCascadeDistances = Vec4(g_shadowCascade0DistanceCVar.get(), g_shadowCascade1DistanceCVar.get(),
 											g_shadowCascade2DistanceCVar.get(), g_shadowCascade3DistanceCVar.get());
 											g_shadowCascade2DistanceCVar.get(), g_shadowCascade3DistanceCVar.get());
 
 
-		for(U cascade = 0; cascade < g_shadowCascadeCountCVar.get(); ++cascade)
+		for(U cascade = 0; cascade < out.m_shadowCascadeCount; ++cascade)
 		{
 		{
 			ANKI_ASSERT(m_runCtx.m_rctx->m_dirLightTextureMatrices[cascade] != Mat4::getZero());
 			ANKI_ASSERT(m_runCtx.m_rctx->m_dirLightTextureMatrices[cascade] != Mat4::getZero());
 			out.m_textureMatrices[cascade] = m_runCtx.m_rctx->m_dirLightTextureMatrices[cascade];
 			out.m_textureMatrices[cascade] = m_runCtx.m_rctx->m_dirLightTextureMatrices[cascade];

+ 21 - 28
AnKi/Renderer/Utils/Drawer.cpp

@@ -33,14 +33,8 @@ Error RenderableDrawer::init()
 	U32 count = 0;
 	U32 count = 0;
 	for(MutatorValue attachmentCount : kColorAttachmentCounts)
 	for(MutatorValue attachmentCount : kColorAttachmentCounts)
 	{
 	{
-		ANKI_CHECK(loadShaderProgram("ShaderBinaries/DrawerStats.ankiprogbin",
-									 Array<SubMutation, 2>{{{"CLEAR_COUNTER_BUFFER", 0}, {"COLOR_ATTACHMENT_COUNT", attachmentCount}}},
+		ANKI_CHECK(loadShaderProgram("ShaderBinaries/DrawerStats.ankiprogbin", Array<SubMutation, 1>{{{"COLOR_ATTACHMENT_COUNT", attachmentCount}}},
 									 m_stats.m_statsProg, m_stats.m_updateStatsGrProgs[count]));
 									 m_stats.m_statsProg, m_stats.m_updateStatsGrProgs[count]));
-
-		ANKI_CHECK(loadShaderProgram("ShaderBinaries/DrawerStats.ankiprogbin",
-									 Array<SubMutation, 2>{{{"CLEAR_COUNTER_BUFFER", 1}, {"COLOR_ATTACHMENT_COUNT", attachmentCount}}},
-									 m_stats.m_statsProg, m_stats.m_resetCounterGrProgs[count]));
-
 		++count;
 		++count;
 	}
 	}
 #endif
 #endif
@@ -118,11 +112,27 @@ void RenderableDrawer::drawMdi(const RenderableDrawerArguments& args, CommandBuf
 			// Get place to write new stats
 			// Get place to write new stats
 			getRenderer().getReadbackManager().allocateData(m_stats.m_readback, sizeof(U32), m_stats.m_statsBuffer, m_stats.m_statsBufferOffset);
 			getRenderer().getReadbackManager().allocateData(m_stats.m_readback, sizeof(U32), m_stats.m_statsBuffer, m_stats.m_statsBufferOffset);
 
 
-			// First drawcall clears the counter buffer for this frame
-			cmdb.bindShaderProgram(m_stats.m_resetCounterGrProgs[variant].get());
-			cmdb.bindStorageBuffer(0, 0, m_stats.m_statsBuffer, m_stats.m_statsBufferOffset, sizeof(U32));
-			cmdb.draw(PrimitiveTopology::kTriangles, 6);
+			// Allocate another atomic to count the passes. Do that because the calls to drawMdi might not be in the same order as they run on the GPU
+			U32* counter;
+			m_stats.m_passCountBuffer = RebarTransientMemoryPool::getSingleton().allocateFrame(sizeof(U32), counter);
+			*counter = 0;
 		}
 		}
+
+		U32* counter;
+		BufferOffsetRange threadCountBuff = RebarTransientMemoryPool::getSingleton().allocateFrame(sizeof(U32), counter);
+		*counter = 0;
+
+		cmdb.pushDebugMarker("Draw stats", Vec3(0.0f, 1.0f, 0.0f));
+
+		cmdb.bindShaderProgram(m_stats.m_updateStatsGrProgs[variant].get());
+		cmdb.bindStorageBuffer(0, 0, m_stats.m_statsBuffer, m_stats.m_statsBufferOffset, sizeof(U32));
+		cmdb.bindStorageBuffer(0, 1, threadCountBuff);
+		cmdb.bindStorageBuffer(0, 2, args.m_mdiDrawCountsBuffer);
+		cmdb.bindStorageBuffer(0, 3, m_stats.m_passCountBuffer);
+
+		cmdb.draw(PrimitiveTopology::kTriangles, 6);
+
+		cmdb.popDebugMarker();
 	}
 	}
 #endif
 #endif
 
 
@@ -167,24 +177,7 @@ void RenderableDrawer::drawMdi(const RenderableDrawerArguments& args, CommandBuf
 
 
 	ANKI_ASSERT(bucketCount == RenderStateBucketContainer::getSingleton().getBucketCount(args.m_renderingTechinuqe));
 	ANKI_ASSERT(bucketCount == RenderStateBucketContainer::getSingleton().getBucketCount(args.m_renderingTechinuqe));
 
 
-	// Update the stats
-#if ANKI_STATS_ENABLED
-	{
-		LockGuard lock(m_stats.m_mtx);
-
-		U32* counter;
-		BufferOffsetRange threadCountBuff = RebarTransientMemoryPool::getSingleton().allocateFrame(sizeof(U32), counter);
-		*counter = 0;
-
-		cmdb.bindShaderProgram(m_stats.m_updateStatsGrProgs[variant].get());
-		cmdb.bindStorageBuffer(0, 0, m_stats.m_statsBuffer, m_stats.m_statsBufferOffset, sizeof(U32));
-		cmdb.bindStorageBuffer(0, 1, threadCountBuff);
-		cmdb.bindStorageBuffer(0, 2, args.m_mdiDrawCountsBuffer);
-		cmdb.draw(PrimitiveTopology::kTriangles, 6);
-	}
-
 	g_maxDrawcallsStatVar.increment(allUserCount);
 	g_maxDrawcallsStatVar.increment(allUserCount);
-#endif
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 2 - 1
AnKi/Renderer/Utils/Drawer.h

@@ -64,13 +64,14 @@ private:
 
 
 		ShaderProgramResourcePtr m_statsProg;
 		ShaderProgramResourcePtr m_statsProg;
 		Array<ShaderProgramPtr, 3> m_updateStatsGrProgs;
 		Array<ShaderProgramPtr, 3> m_updateStatsGrProgs;
-		Array<ShaderProgramPtr, 3> m_resetCounterGrProgs;
 
 
 		U64 m_frameIdx = kMaxU64;
 		U64 m_frameIdx = kMaxU64;
 		SpinLock m_mtx;
 		SpinLock m_mtx;
 
 
 		Buffer* m_statsBuffer = nullptr;
 		Buffer* m_statsBuffer = nullptr;
 		PtrSize m_statsBufferOffset = 0;
 		PtrSize m_statsBufferOffset = 0;
+
+		BufferOffsetRange m_passCountBuffer;
 	} m_stats;
 	} m_stats;
 #endif
 #endif
 
 

+ 0 - 1
AnKi/Renderer/Utils/TraditionalDeferredShading.cpp

@@ -113,7 +113,6 @@ void TraditionalDeferredLightShading::drawLights(TraditionalDeferredLightShading
 			unis->m_dirLight.m_diffuseColor = dirLightc->getDiffuseColor().xyz();
 			unis->m_dirLight.m_diffuseColor = dirLightc->getDiffuseColor().xyz();
 			unis->m_dirLight.m_active = 1;
 			unis->m_dirLight.m_active = 1;
 			unis->m_dirLight.m_direction = dirLightc->getDirection();
 			unis->m_dirLight.m_direction = dirLightc->getDirection();
-			ANKI_ASSERT(info.m_effectiveShadowDistance > 0.0f);
 			unis->m_dirLight.m_effectiveShadowDistance = info.m_effectiveShadowDistance;
 			unis->m_dirLight.m_effectiveShadowDistance = info.m_effectiveShadowDistance;
 			unis->m_dirLight.m_lightMatrix = info.m_dirLightMatrix;
 			unis->m_dirLight.m_lightMatrix = info.m_dirLightMatrix;
 		}
 		}

+ 11 - 8
AnKi/Shaders/DrawerStats.ankiprog

@@ -7,7 +7,6 @@
 // It's simple drawcall that draws a very small quad to the screen. Only one thread of the fragment shader will read the multi-draw counts and write
 // It's simple drawcall that draws a very small quad to the screen. Only one thread of the fragment shader will read the multi-draw counts and write
 // the number of drawcalls in a buffer.
 // the number of drawcalls in a buffer.
 
 
-#pragma anki mutator CLEAR_COUNTER_BUFFER 0 1
 #pragma anki mutator COLOR_ATTACHMENT_COUNT 0 1 4
 #pragma anki mutator COLOR_ATTACHMENT_COUNT 0 1 4
 
 
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
@@ -37,10 +36,9 @@ VertOut main(U32 vertId : SV_VERTEXID)
 #pragma anki start frag
 #pragma anki start frag
 
 
 [[vk::binding(0)]] RWStructuredBuffer<U32> g_visibleObjectCount;
 [[vk::binding(0)]] RWStructuredBuffer<U32> g_visibleObjectCount;
-#if CLEAR_COUNTER_BUFFER == 0
 [[vk::binding(1)]] RWStructuredBuffer<U32> g_fragThreadCount;
 [[vk::binding(1)]] RWStructuredBuffer<U32> g_fragThreadCount;
 [[vk::binding(2)]] StructuredBuffer<U32> g_mdiDrawCounts;
 [[vk::binding(2)]] StructuredBuffer<U32> g_mdiDrawCounts;
-#endif
+[[vk::binding(3)]] RWStructuredBuffer<U32> g_passCount;
 
 
 #if COLOR_ATTACHMENT_COUNT > 0
 #if COLOR_ATTACHMENT_COUNT > 0
 struct FragOut
 struct FragOut
@@ -61,9 +59,6 @@ void
 #endif
 #endif
 main()
 main()
 {
 {
-#if CLEAR_COUNTER_BUFFER == 1
-	g_visibleObjectCount[0] = 0;
-#else
 	U32 threadIdx;
 	U32 threadIdx;
 	InterlockedAdd(g_fragThreadCount[0], 1, threadIdx);
 	InterlockedAdd(g_fragThreadCount[0], 1, threadIdx);
 
 
@@ -78,12 +73,20 @@ main()
 			visiblesCount += g_mdiDrawCounts[i];
 			visiblesCount += g_mdiDrawCounts[i];
 		}
 		}
 
 
-		if(visiblesCount > 0)
+		U32 passIdx;
+		InterlockedAdd(g_passCount[0], 1, passIdx);
+
+		if(passIdx == 0)
+		{
+			// 1st pass initializes the atomic
+			U32 origValue;
+			InterlockedExchange(g_visibleObjectCount[0], visiblesCount, origValue);
+		}
+		else if(visiblesCount > 0)
 		{
 		{
 			InterlockedAdd(g_visibleObjectCount[0], visiblesCount);
 			InterlockedAdd(g_visibleObjectCount[0], visiblesCount);
 		}
 		}
 	}
 	}
-#endif
 
 
 	discard;
 	discard;
 
 

+ 3 - 0
AnKi/Shaders/Intellisense.hlsl

@@ -189,6 +189,9 @@ void InterlockedAdd(T dest, T value, T& originalValue);
 template<typename T>
 template<typename T>
 void InterlockedAdd(T dest, T value);
 void InterlockedAdd(T dest, T value);
 
 
+template<typename T>
+void InterlockedExchange(T dest, T value, T& originalValue);
+
 // Wave ops
 // Wave ops
 
 
 template<typename T>
 template<typename T>