Browse Source

Add some GPU visibility code

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
774916d5f4

+ 20 - 0
AnKi/Renderer/GpuVisibility.cpp

@@ -0,0 +1,20 @@
+// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Renderer/GpuVisibility.h>
+#include <AnKi/Renderer/Renderer.h>
+#include <AnKi/Scene/RenderStateBucket.h>
+#include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
+
+namespace anki {
+
+void GpuVisibility::populateRenderGraph(RenderingContext& ctx)
+{
+	// Allocate memory for the indirect commands
+
+	// TODO
+}
+
+} // end namespace anki

+ 31 - 0
AnKi/Renderer/GpuVisibility.h

@@ -0,0 +1,31 @@
+// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <AnKi/Renderer/RendererObject.h>
+
+namespace anki {
+
+/// @addtogroup renderer
+/// @{
+
+/// XXX
+class GpuVisibility : public RendererObject
+{
+public:
+	Error init()
+	{
+		return Error::kNone;
+	}
+
+	/// Populate the rendergraph.
+	void populateRenderGraph(RenderingContext& ctx);
+
+private:
+};
+/// @}
+
+} // end namespace anki

+ 1 - 1
AnKi/Scene/Components/ModelComponent.cpp

@@ -314,7 +314,7 @@ Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 			GpuSceneRenderableAabb gpuVolume;
 			gpuVolume.m_aabbMin = m_spatial.getAabbWorldSpace().getMin().xyz();
 			gpuVolume.m_aabbMax = m_spatial.getAabbWorldSpace().getMax().xyz();
-			gpuVolume.m_renderableOffset = m_patchInfos[i].m_gpuSceneIndexRenderable.getOffsetInGpuScene();
+			gpuVolume.m_renderableIndex = m_patchInfos[i].m_gpuSceneIndexRenderable.get();
 
 			for(RenderingTechnique t :
 				EnumBitsIterable<RenderingTechnique, RenderingTechniqueBit>(m_patchInfos[i].m_techniques))

+ 1 - 1
AnKi/Scene/Components/ParticleEmitterComponent.cpp

@@ -384,7 +384,7 @@ Error ParticleEmitterComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 		GpuSceneRenderableAabb aabb;
 		aabb.m_aabbMin = m_spatial.getAabbWorldSpace().getMin().xyz();
 		aabb.m_aabbMax = m_spatial.getAabbWorldSpace().getMax().xyz();
-		aabb.m_renderableOffset = m_gpuSceneIndexRenderable.getOffsetInGpuScene();
+		aabb.m_renderableIndex = m_gpuSceneIndexRenderable.get();
 		aabb.m_renderStateBucket = m_renderStateBuckets[t].get();
 		patcher.newCopy(*info.m_framePool, m_gpuSceneIndexAabbs[t].getOffsetInGpuScene(), aabb);
 	}

+ 6 - 0
AnKi/Scene/RenderStateBucket.cpp

@@ -15,6 +15,8 @@ RenderStateBucketContainer::~RenderStateBucketContainer()
 		{
 			ANKI_ASSERT(!b.m_program.isCreated() && b.m_userCount == 0);
 		}
+
+		ANKI_ASSERT(m_bucketItemCount[t] == 0);
 	}
 }
 
@@ -34,6 +36,8 @@ RenderStateBucketIndex RenderStateBucketContainer::addUser(const RenderStateInfo
 
 	LockGuard lock(m_mtx);
 
+	++m_bucketItemCount[technique];
+
 	// Search bucket
 	for(U32 i = 0; i < buckets.getSize(); ++i)
 	{
@@ -80,6 +84,8 @@ void RenderStateBucketContainer::removeUser(RenderStateBucketIndex& bucketIndex)
 
 		ANKI_ASSERT(bucketIndex.m_index < m_buckets[bucketIndex.m_technique].getSize());
 
+		--m_bucketItemCount[bucketIndex.m_technique];
+
 		ExtendedBucket& bucket = m_buckets[bucketIndex.m_technique][bucketIndex.m_index];
 		ANKI_ASSERT(bucket.m_userCount > 0 && bucket.m_program.isCreated());
 

+ 15 - 1
AnKi/Scene/RenderStateBucket.h

@@ -80,13 +80,15 @@ class RenderStateBucketContainer : public MakeSingleton<RenderStateBucketContain
 
 public:
 	/// Add a new user for a specific render state and rendering technique.
+	/// @note It's thread-safe against addUser and removeUser
 	RenderStateBucketIndex addUser(const RenderStateInfo& state, RenderingTechnique technique);
 
 	/// Remove the user.
+	/// @note It's thread-safe against addUser and removeUser
 	void removeUser(RenderStateBucketIndex& bucketIndex);
 
 	template<typename TFunc>
-	void interateBuckets(RenderingTechnique technique, TFunc func) const
+	void iterateBuckets(RenderingTechnique technique, TFunc func) const
 	{
 		for(const ExtendedBucket& b : m_buckets[technique])
 		{
@@ -97,6 +99,17 @@ public:
 		}
 	}
 
+	/// Get the number of renderables of all the buckets of a specific rendering technique.
+	U32 getBucketsItemCount(RenderingTechnique technique) const
+	{
+		return m_bucketItemCount[technique];
+	}
+
+	U32 getBucketCount(RenderingTechnique technique) const
+	{
+		return m_buckets[technique].getSize();
+	}
+
 private:
 	class ExtendedBucket : public RenderStateInfo
 	{
@@ -106,6 +119,7 @@ private:
 	};
 
 	Array<SceneDynamicArray<ExtendedBucket>, U32(RenderingTechnique::kCount)> m_buckets;
+	Array<U32, U32(RenderingTechnique::kCount)> m_bucketItemCount = {};
 	Mutex m_mtx;
 
 	RenderStateBucketContainer() = default;

+ 16 - 0
AnKi/Shaders/CollisionFunctions.hlsl

@@ -130,3 +130,19 @@ F32 testPlanePoint(Vec3 planeNormal, F32 planeOffset, Vec3 point3d)
 {
 	return dot(planeNormal, point3d) - planeOffset;
 }
+
+F32 testPlaneAabb(Vec3 planeNormal, F32 planeOffset, Vec3 aabbMin, Vec3 aabbMax)
+{
+	const bool3 ge = planeNormal >= 0.0;
+	const Vec3 diagMin = select(aabbMin, aabbMax, ge);
+	const Vec3 diagMax = select(aabbMax, aabbMin, ge);
+
+	F32 test = testPlanePoint(planeNormal, planeOffset, diagMin);
+	if(test > 0.0)
+	{
+		return test;
+	}
+
+	test = testPlanePoint(planeNormal, planeOffset, diagMax);
+	return (test >= 0.0) ? 0.0 : test;
+}

+ 87 - 0
AnKi/Shaders/GpuVisibility.ankiprog

@@ -0,0 +1,87 @@
+// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start comp
+
+#include <AnKi/Shaders/Include/GpuSceneTypes.h>
+#include <AnKi/Shaders/CollisionFunctions.hlsl>
+
+[[vk::binding(0)]] StructuredBuffer<GpuSceneRenderableAabb> g_aabbs;
+[[vk::binding(1)]] StructuredBuffer<GpuSceneRenderable> g_renderables;
+
+[[vk::binding(2)]] Texture2D<U32> g_hiZTex;
+
+// These 2 have the same size
+[[vk::binding(3)]] RWStructuredBuffer<GpuSceneRenderable> g_instanceRateRenderables;
+[[vk::binding(4)]] RWStructuredBuffer<DrawIndexedIndirectInfo> g_drawIndexedIndirects;
+
+// Index pointing to the above arrays. Its size is equal to the number of render state buckets
+[[vk::binding(5)]] RWStructuredBuffer<U32> g_drawIndirectOffset;
+
+[[vk::binding(6)]] ByteAddressBuffer g_gpuScene;
+
+struct Uniforms
+{
+	Vec4 m_clipPlanes[6u];
+
+	UVec3 m_padding;
+	U32 m_renderableCount;
+};
+
+[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+
+[numthreads(64, 1, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
+{
+	const U32 aabbIdx = svDispatchThreadId.x;
+	if(aabbIdx >= g_unis.m_renderableCount)
+	{
+		return;
+	}
+
+	const GpuSceneRenderableAabb aabb = g_aabbs[aabbIdx];
+
+	// Frustum test
+	//
+	Bool behindAtLeastOnePlane = false;
+	[unroll] for(U32 i = 0; i < 6; ++i)
+	{
+		const Bool behind =
+			testPlaneAabb(g_unis.m_clipPlanes[i].xyz, g_unis.m_clipPlanes[i].w, aabb.m_aabbMin, aabb.m_aabbMax) < 0.0;
+		behindAtLeastOnePlane = behindAtLeastOnePlane || behind;
+	}
+
+	if(behindAtLeastOnePlane)
+	{
+		return;
+	}
+
+	// TODO HiZ testing
+
+	// TODO LOD selection
+	const U32 lod = 0;
+
+	// Add the drawcall
+	//
+	U32 indirectIdx;
+	InterlockedAdd(g_drawIndirectOffset[aabb.m_renderStateBucket], 1, indirectIdx);
+
+	const GpuSceneRenderable renderableIn = g_renderables[aabb.m_renderableIndex];
+	const GpuSceneMeshLod meshLod =
+		g_gpuScene.Load<GpuSceneMeshLod>(renderableIn.m_geometryOffset + sizeof(GpuSceneMeshLod) * lod);
+
+	DrawIndexedIndirectInfo indirect;
+	indirect.m_indexCount = meshLod.m_indexCount;
+	indirect.m_instanceCount = 1;
+	indirect.m_firstIndex = meshLod.m_indexBufferOffset / 2;
+	indirect.m_vertexOffset = 0;
+	indirect.m_firstInstance = indirectIdx;
+	g_drawIndexedIndirects[indirectIdx] = indirect;
+
+	GpuSceneRenderable renderableOut = renderableIn;
+	renderableOut.m_geometryOffset += sizeof(GpuSceneMeshLod) * lod;
+	g_instanceRateRenderables[indirectIdx] = renderableOut;
+}
+
+#pragma anki end

+ 1 - 1
AnKi/Shaders/Include/GpuSceneTypes.h

@@ -25,7 +25,7 @@ typedef UVec4 GpuSceneRenderablePacked;
 struct GpuSceneRenderableAabb
 {
 	Vec3 m_aabbMin;
-	U32 m_renderableOffset; ///< Points to a GpuSceneRenderable
+	U32 m_renderableIndex; ///< Points to a GpuSceneRenderable
 
 	Vec3 m_aabbMax;
 	U32 m_renderStateBucket;