Panagiotis Christopoulos Charitos преди 3 години
родител
ревизия
600eafdf09

+ 1 - 1
AnKi/Collision/Aabb.h

@@ -16,7 +16,7 @@ namespace anki {
 class Aabb
 {
 public:
-	static constexpr CollisionShapeType kClassType = CollisionShapeType::kAABB;
+	static constexpr CollisionShapeType kClassType = CollisionShapeType::kAabb;
 
 	/// Will not initialize any memory, nothing.
 	Aabb()

+ 2 - 2
AnKi/Collision/Common.h

@@ -35,9 +35,9 @@ enum class CollisionShapeType : U8
 	kPlane,
 	kLineSegment,
 	kRay,
-	kAABB,
+	kAabb,
 	kSphere,
-	kOBB,
+	kObb,
 	kConvexHull,
 	kCone,
 

+ 1 - 1
AnKi/Collision/Obb.h

@@ -18,7 +18,7 @@ namespace anki {
 class Obb
 {
 public:
-	static constexpr CollisionShapeType kClassType = CollisionShapeType::kOBB;
+	static constexpr CollisionShapeType kClassType = CollisionShapeType::kObb;
 
 	/// Will not initialize any memory, nothing.
 	Obb()

+ 1 - 0
AnKi/Core/GpuMemoryPools.h

@@ -187,6 +187,7 @@ public:
 	void newCopy(StackMemoryPool& frameCpuPool, PtrSize gpuSceneDestOffset, PtrSize dataSize, const void* data);
 
 	/// Copy the data to the GPU scene buffer.
+	/// @note Not thread-safe. Nothing else should be happening before calling it.
 	void patchGpuScene(RebarStagingGpuMemoryPool& rebarPool, CommandBuffer& cmdb, const BufferPtr& gpuSceneBuffer);
 
 private:

+ 2 - 1
AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h

@@ -21,6 +21,8 @@ public:
 	/// The offset in the SegregatedListsGpuMemoryPoolToken::getBuffer() buffer.
 	PtrSize m_offset = kMaxPtrSize;
 
+	PtrSize m_size = kMaxPtrSize;
+
 	Bool operator==(const SegregatedListsGpuMemoryPoolToken& b) const
 	{
 		return m_offset == b.m_offset && m_chunk == b.m_chunk && m_chunkOffset == b.m_chunkOffset && m_size == b.m_size;
@@ -29,7 +31,6 @@ public:
 private:
 	void* m_chunk = nullptr;
 	PtrSize m_chunkOffset = kMaxPtrSize;
-	PtrSize m_size = kMaxPtrSize;
 };
 
 /// GPU memory allocator based on segregated lists. It allocates a GPU buffer with some initial size. If there is a need

+ 1 - 0
AnKi/Scene/Common.h

@@ -8,6 +8,7 @@
 #include <AnKi/Util/String.h>
 #include <AnKi/Scene/Forward.h>
 #include <AnKi/Core/GpuMemoryPools.h>
+#include <AnKi/Shaders/Include/GpuSceneTypes.h>
 #include <functional>
 
 namespace anki {

+ 105 - 2
AnKi/Scene/Components/ModelComponent.cpp

@@ -22,6 +22,12 @@ ModelComponent::ModelComponent(SceneNode* node)
 ModelComponent::~ModelComponent()
 {
 	m_modelPatchMergeKeys.destroy(m_node->getMemoryPool());
+
+	GpuSceneMemoryPool& gpuScene = *getExternalSubsystems(*m_node).m_gpuSceneMemoryPool;
+	gpuScene.free(m_gpuSceneMeshGpuViews);
+	gpuScene.free(m_gpuSceneUniforms);
+
+	m_gpuSceneUniformsOffsetPerPatch.destroy(m_node->getMemoryPool());
 }
 
 Error ModelComponent::loadModelResource(CString filename)
@@ -31,11 +37,12 @@ Error ModelComponent::loadModelResource(CString filename)
 	ModelResourcePtr rsrc;
 	ANKI_CHECK(getExternalSubsystems(*m_node).m_resourceManager->loadResource(filename, rsrc));
 	m_model = std::move(rsrc);
+	const U32 modelPatchCount = m_model->getModelPatches().getSize();
 
 	m_modelPatchMergeKeys.destroy(m_node->getMemoryPool());
-	m_modelPatchMergeKeys.create(m_node->getMemoryPool(), m_model->getModelPatches().getSize());
+	m_modelPatchMergeKeys.create(m_node->getMemoryPool(), modelPatchCount);
 
-	for(U32 i = 0; i < m_model->getModelPatches().getSize(); ++i)
+	for(U32 i = 0; i < modelPatchCount; ++i)
 	{
 		Array<U64, 2> toHash;
 		toHash[0] = i;
@@ -43,6 +50,102 @@ Error ModelComponent::loadModelResource(CString filename)
 		m_modelPatchMergeKeys[i] = computeHash(&toHash[0], sizeof(toHash));
 	}
 
+	// GPU scene allocations
+	GpuSceneMemoryPool& gpuScene = *getExternalSubsystems(*m_node).m_gpuSceneMemoryPool;
+
+	gpuScene.free(m_gpuSceneMeshGpuViews);
+	gpuScene.allocate(sizeof(MeshGpuView) * m_modelPatchMergeKeys.getSize(), 4, m_gpuSceneMeshGpuViews);
+
+	U32 uniformsSize = 0;
+	m_gpuSceneUniformsOffsetPerPatch.resize(m_node->getMemoryPool(), modelPatchCount);
+	for(U32 i = 0; i < modelPatchCount; ++i)
+	{
+		m_gpuSceneUniformsOffsetPerPatch[i] = uniformsSize / 4;
+
+		const U32 size = U32(m_model->getModelPatches()[i].getMaterial()->getPrefilledLocalUniforms().getSizeInBytes());
+		ANKI_ASSERT((size % 4) == 0);
+		uniformsSize += size;
+	}
+
+	gpuScene.free(m_gpuSceneUniforms);
+	gpuScene.allocate(uniformsSize, 4, m_gpuSceneUniforms);
+
+	for(U32 i = 0; i < modelPatchCount; ++i)
+	{
+		m_gpuSceneUniformsOffsetPerPatch[i] += DwordOffset(m_gpuSceneUniforms.m_offset / 4);
+	}
+
+	return Error::kNone;
+}
+
+Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
+{
+	if(ANKI_UNLIKELY(m_dirty && m_model.isCreated()))
+	{
+		GpuSceneMicroPatcher& gpuScenePatcher = *getExternalSubsystems(*info.m_node).m_gpuSceneMicroPatcher;
+
+		// Upload the mesh views
+		const U32 modelPatchCount = m_model->getModelPatches().getSize();
+		DynamicArrayRaii<MeshGpuView> meshViews(info.m_framePool, modelPatchCount);
+		for(U32 i = 0; i < modelPatchCount; ++i)
+		{
+			MeshGpuView& view = meshViews[i];
+			const ModelPatch& patch = m_model->getModelPatches()[i];
+			const MeshResource& mesh = *patch.getMesh();
+
+			zeroMemory(view);
+			view.m_positionScale = mesh.getPositionsScale();
+			view.m_positionTranslation = mesh.getPositionsTranslation();
+
+			for(U32 l = 0; l < mesh.getLodCount(); ++l)
+			{
+				for(VertexStreamId stream = VertexStreamId::kPosition; stream <= VertexStreamId::kBoneWeights; ++stream)
+				{
+					if(!mesh.isVertexStreamPresent(stream))
+					{
+						continue;
+					}
+
+					PtrSize offset;
+					U32 vertCount;
+					mesh.getVertexStreamInfo(l, stream, offset, vertCount);
+
+					ANKI_ASSERT((offset % 4) == 0);
+					view.m_vertexOffsets[l][U32(stream)] = U32(offset / 4);
+				}
+
+				PtrSize offset;
+				U32 indexCount;
+				IndexType indexType;
+				mesh.getIndexBufferInfo(l, offset, indexCount, indexType);
+				view.m_indexOffsets[l] = U32(offset);
+				view.m_indexCounts[l] = indexCount;
+			}
+		}
+
+		gpuScenePatcher.newCopy(*info.m_framePool, m_gpuSceneMeshGpuViews.m_offset, meshViews.getSizeInBytes(),
+								&meshViews[0]);
+
+		// Upload the uniforms
+		DynamicArrayRaii<U32> allUniforms(info.m_framePool, U32(m_gpuSceneUniforms.m_size / 4));
+		U32 count = 0;
+		for(U32 i = 0; i < modelPatchCount; ++i)
+		{
+			const ModelPatch& patch = m_model->getModelPatches()[i];
+			const MaterialResource& mtl = *patch.getMaterial();
+			memcpy(&allUniforms[count], mtl.getPrefilledLocalUniforms().getBegin(),
+				   mtl.getPrefilledLocalUniforms().getSizeInBytes());
+
+			count += U32(mtl.getPrefilledLocalUniforms().getSizeInBytes() / 4);
+		}
+
+		ANKI_ASSERT(count * 4 == m_gpuSceneUniforms.m_size);
+		gpuScenePatcher.newCopy(*info.m_framePool, m_gpuSceneUniforms.m_offset, m_gpuSceneUniforms.m_size,
+								&allUniforms[0]);
+	}
+
+	updated = m_dirty;
+	m_dirty = false;
 	return Error::kNone;
 }
 

+ 16 - 6
AnKi/Scene/Components/ModelComponent.h

@@ -41,6 +41,17 @@ public:
 		return m_model.isCreated();
 	}
 
+	DwordOffset getMeshViewsGpuSceneOffset() const
+	{
+		ANKI_ASSERT((m_gpuSceneMeshGpuViews.m_offset % 4) == 0);
+		return DwordOffset(m_gpuSceneMeshGpuViews.m_offset / 4);
+	}
+
+	DwordOffset getUniformsGpuSceneOffset(U32 meshPatchIdx) const
+	{
+		return m_gpuSceneUniformsOffsetPerPatch[meshPatchIdx];
+	}
+
 private:
 	SceneNode* m_node = nullptr;
 	ModelResourcePtr m_model;
@@ -48,12 +59,11 @@ private:
 	DynamicArray<U64> m_modelPatchMergeKeys;
 	Bool m_dirty = true;
 
-	Error update([[maybe_unused]] SceneComponentUpdateInfo& info, Bool& updated)
-	{
-		updated = m_dirty;
-		m_dirty = false;
-		return Error::kNone;
-	}
+	SegregatedListsGpuMemoryPoolToken m_gpuSceneMeshGpuViews;
+	SegregatedListsGpuMemoryPoolToken m_gpuSceneUniforms;
+	DynamicArray<DwordOffset> m_gpuSceneUniformsOffsetPerPatch;
+
+	Error update(SceneComponentUpdateInfo& info, Bool& updated);
 };
 /// @}
 

+ 6 - 0
AnKi/Scene/Components/MoveComponent.h

@@ -139,6 +139,12 @@ public:
 	}
 	/// @}
 
+	DwordOffset getTransformsGpuSceneOffset() const
+	{
+		ANKI_ASSERT((m_gpuSceneTransforms.m_offset % 4) == 0);
+		return DwordOffset(m_gpuSceneTransforms.m_offset / 4);
+	}
+
 private:
 	/// The transformation in local space
 	Transform m_ltrf = Transform::getIdentity();

+ 0 - 1
AnKi/Scene/Components/RenderComponent.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Util/Logger.h>
-#include <AnKi/Shaders/Include/GpuSceneTypes.h>
 
 namespace anki {
 

+ 7 - 2
AnKi/Scene/Components/RenderComponent.h

@@ -104,15 +104,20 @@ public:
 										 RebarStagingGpuMemoryPool& alloc,
 										 const Vec4& positionScaleAndTranslation = Vec4(1.0f, 0.0f, 0.0f, 0.0f));
 
+	DwordOffset getGpuSceneViewOffset() const
+	{
+		ANKI_ASSERT((m_gpuSceneRenderableGpuView.m_offset % 4) == 0);
+		return DwordOffset(m_gpuSceneRenderableGpuView.m_offset / 4);
+	}
+
 private:
 	RenderQueueDrawCallback m_callback = nullptr;
 	const void* m_userData = nullptr;
 	U64 m_mergeKey = kMaxU64;
 	FillRayTracingInstanceQueueElementCallback m_rtCallback = nullptr;
 	const void* m_rtCallbackUserData = nullptr;
-	RenderComponentFlag m_flags = RenderComponentFlag::kNone;
-
 	SegregatedListsGpuMemoryPoolToken m_gpuSceneRenderableGpuView;
+	RenderComponentFlag m_flags = RenderComponentFlag::kNone;
 
 	void onDestroy(SceneNode& node);
 };

+ 11 - 2
AnKi/Scene/Components/SpatialComponent.cpp

@@ -71,10 +71,10 @@ Error SpatialComponent::update([[maybe_unused]] SceneComponentUpdateInfo& info,
 			// Compute the AABB
 			switch(m_collisionObjectType)
 			{
-			case CollisionShapeType::kAABB:
+			case CollisionShapeType::kAabb:
 				m_derivedAabb = m_aabb;
 				break;
-			case CollisionShapeType::kOBB:
+			case CollisionShapeType::kObb:
 				m_derivedAabb = computeAabb(m_obb);
 				break;
 			case CollisionShapeType::kSphere:
@@ -92,10 +92,19 @@ Error SpatialComponent::update([[maybe_unused]] SceneComponentUpdateInfo& info,
 		else
 		{
 			m_node->getSceneGraph().getOctree().placeAlwaysVisible(&m_octreeInfo);
+
+			// Set something random
+			m_derivedAabb = Aabb(Vec3(-1.0f), Vec3(1.0f));
 		}
 
 		m_markedForUpdate = false;
 		m_placed = true;
+
+		// Update the GPU scene
+		Array<Vec3, 2> aabb;
+		aabb[0] = m_derivedAabb.getMin().xyz();
+		aabb[1] = m_derivedAabb.getMax().xyz();
+		info.m_gpuSceneMicroPatcher->newCopy(*info.m_framePool, m_gpuSceneAabb.m_offset, sizeof(aabb), &aabb[0]);
 	}
 
 	m_octreeInfo.reset();

+ 6 - 0
AnKi/Scene/Components/SpatialComponent.h

@@ -110,6 +110,12 @@ public:
 		return m_alwaysVisible;
 	}
 
+	DwordOffset getAabbGpuSceneOffset() const
+	{
+		ANKI_ASSERT((m_gpuSceneAabb.m_offset % 4) == 0);
+		return DwordOffset(m_gpuSceneAabb.m_offset / 4);
+	}
+
 private:
 	SceneNode* m_node;
 

+ 10 - 0
AnKi/Scene/ModelNode.cpp

@@ -192,6 +192,16 @@ void ModelNode::initRenderComponents()
 				&m_renderProxies[patchIdx]);
 		}
 
+		// Upload to GPU scene
+		RenderableGpuView2 view = {};
+		view.m_worldTransformsOffset = getFirstComponentOfType<MoveComponent>().getTransformsGpuSceneOffset();
+		view.m_aabbOffset = getFirstComponentOfType<SpatialComponent>().getAabbGpuSceneOffset();
+		view.m_uniformsOffset = getFirstComponentOfType<ModelComponent>().getUniformsGpuSceneOffset(patchIdx);
+		view.m_meshOffset =
+			getFirstComponentOfType<ModelComponent>().getMeshViewsGpuSceneOffset() + sizeof(MeshGpuView) / 4 * patchIdx;
+		getExternalSubsystems().m_gpuSceneMicroPatcher->newCopy(getFrameMemoryPool(), rc.getGpuSceneViewOffset() * 4,
+																sizeof(view), &view);
+
 		// Init the proxy
 		RenderProxy& proxy = m_renderProxies[patchIdx];
 		proxy.m_node = this;

+ 2 - 2
AnKi/Scene/Visibility.cpp

@@ -54,10 +54,10 @@ static Bool spatialInsideFrustum(const FrustumComponent& frc, const SpatialCompo
 {
 	switch(spc.getCollisionShapeType())
 	{
-	case CollisionShapeType::kOBB:
+	case CollisionShapeType::kObb:
 		return frc.insideFrustum(spc.getCollisionShape<Obb>());
 		break;
-	case CollisionShapeType::kAABB:
+	case CollisionShapeType::kAabb:
 		return frc.insideFrustum(spc.getCollisionShape<Aabb>());
 		break;
 	case CollisionShapeType::kSphere:

+ 16 - 8
AnKi/Shaders/Include/GpuSceneTypes.h

@@ -9,20 +9,28 @@
 
 ANKI_BEGIN_NAMESPACE
 
+/// Offset in DWORDs
+#if defined(__cplusplus)
+using DwordOffset = U32;
+#else
+#	define DwordOffset U32
+#endif
+
+/// @note All offsets in DWORD
 struct RenderableGpuView2
 {
-	U32 m_worldTransformsOffset; ///< First is the crnt transform and the 2nd the previous
-	U32 m_aabbOffset;
-	U32 m_uniformsOffset;
-	U32 m_meshOffset;
-	U32 m_boneTransformsOffset;
-	U32 m_previousBoneTransformsOffset;
+	DwordOffset m_worldTransformsOffset; ///< First is the crnt transform and the 2nd the previous
+	DwordOffset m_aabbOffset;
+	DwordOffset m_uniformsOffset;
+	DwordOffset m_meshOffset;
+	DwordOffset m_boneTransformsOffset;
+	DwordOffset m_previousBoneTransformsOffset;
 };
 
 struct MeshGpuView
 {
-	Vec3 m_positionScale;
-	F32 m_positionTranslation;
+	Vec3 m_positionTranslation;
+	F32 m_positionScale;
 
 	U32 m_vertexOffsets[kMaxLodCount][kMaxVertexStreamIds];
 	U32 m_indexCounts[kMaxLodCount];