Просмотр исходного кода

Add some render queue bits in the render components

Panagiotis Christopoulos Charitos 8 лет назад
Родитель
Сommit
587029bb9c

+ 1 - 1
src/anki/renderer/Drawer.cpp

@@ -153,7 +153,7 @@ void RenderableDrawer::setupUniforms(DrawContext& ctx, CompleteRenderingBuildInf
 {
 {
 	RenderQueueDrawContext dctx;
 	RenderQueueDrawContext dctx;
 	dctx.m_cameraTransform = ctx.m_viewMat.getInverse();
 	dctx.m_cameraTransform = ctx.m_viewMat.getInverse();
-	dctx.m_cmdb = ctx.m_cmdb;
+	dctx.m_commandBuffer = ctx.m_cmdb;
 	dctx.m_key = build.m_in.m_key;
 	dctx.m_key = build.m_in.m_key;
 	dctx.m_projectionMatrix = Mat4::getIdentity();
 	dctx.m_projectionMatrix = Mat4::getIdentity();
 	dctx.m_viewMatrix = ctx.m_viewMat;
 	dctx.m_viewMatrix = ctx.m_viewMat;

+ 4 - 3
src/anki/renderer/RenderQueue.h

@@ -42,18 +42,19 @@ class RenderQueueDrawContext final : public RenderingMatrices
 {
 {
 public:
 public:
 	RenderingKey m_key;
 	RenderingKey m_key;
-	CommandBufferPtr m_cmdb;
+	CommandBufferPtr m_commandBuffer;
+	StagingGpuMemoryManager* m_stagingGpuAllocator ANKI_DBG_NULLIFY;
 };
 };
 
 
 /// Draw callback.
 /// Draw callback.
 using RenderQueueElementDrawCallback = void (*)(
 using RenderQueueElementDrawCallback = void (*)(
-	const RenderQueueDrawContext& ctx, RenderQueueElement* elements, U elementCount);
+	RenderQueueDrawContext& ctx, WeakArray<const RenderQueueElement> elements);
 
 
 class RenderQueueElement final
 class RenderQueueElement final
 {
 {
 public:
 public:
 	RenderQueueElementDrawCallback m_callback;
 	RenderQueueElementDrawCallback m_callback;
-	void* m_userData;
+	const void* m_userData;
 	U64 m_mergeKey;
 	U64 m_mergeKey;
 	F32 m_distanceFromCamera;
 	F32 m_distanceFromCamera;
 };
 };

+ 69 - 2
src/anki/scene/ModelNode.cpp

@@ -33,6 +33,11 @@ public:
 	{
 	{
 		return getNode().buildRendering(in, out);
 		return getNode().buildRendering(in, out);
 	}
 	}
+
+	void setupRenderQueueElement(RenderQueueElement& el) const override
+	{
+		getNode().setupRenderQueueElement(el);
+	}
 };
 };
 
 
 ModelPatchNode::ModelPatchNode(SceneGraph* scene, CString name)
 ModelPatchNode::ModelPatchNode(SceneGraph* scene, CString name)
@@ -44,7 +49,7 @@ ModelPatchNode::~ModelPatchNode()
 {
 {
 }
 }
 
 
-Error ModelPatchNode::init(const ModelPatch* modelPatch)
+Error ModelPatchNode::init(const ModelPatch* modelPatch, U idx, const ModelNode& parent)
 {
 {
 	ANKI_ASSERT(modelPatch);
 	ANKI_ASSERT(modelPatch);
 
 
@@ -57,6 +62,12 @@ Error ModelPatchNode::init(const ModelPatch* modelPatch)
 	RenderComponent* rcomp = newComponent<ModelPatchRenderComponent>(this);
 	RenderComponent* rcomp = newComponent<ModelPatchRenderComponent>(this);
 	ANKI_CHECK(rcomp->init());
 	ANKI_CHECK(rcomp->init());
 
 
+	// Merge key
+	Array<U64, 2> toHash;
+	toHash[0] = idx;
+	toHash[1] = parent.m_model->getUuid();
+	m_mergeKey = computeHash(&toHash[0], sizeof(toHash));
+
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
@@ -97,6 +108,62 @@ Error ModelPatchNode::buildRendering(const RenderingBuildInfoIn& in, RenderingBu
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
+void ModelPatchNode::drawCallback(RenderQueueDrawContext& ctx, WeakArray<const RenderQueueElement> elements)
+{
+	ANKI_ASSERT(elements.getSize() > 0 && elements.getSize() <= MAX_INSTANCES);
+	ANKI_ASSERT(ctx.m_key.m_instanceCount == elements.getSize());
+
+	const ModelPatchNode& self = *static_cast<const ModelPatchNode*>(elements[0].m_userData);
+
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
+	// That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw anywhere
+	ANKI_ASSERT(self.m_modelPatch->getSubMeshesCount() == 0);
+
+	ModelRenderingInfo modelInf;
+	self.m_modelPatch->getRenderingDataSub(ctx.m_key, WeakArray<U8>(), modelInf);
+
+	// Program
+	cmdb->bindShaderProgram(modelInf.m_program);
+
+	// Set attributes
+	for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
+	{
+		const VertexAttributeInfo& attrib = modelInf.m_vertexAttributes[i];
+		cmdb->setVertexAttribute(i, attrib.m_bufferBinding, attrib.m_format, attrib.m_relativeOffset);
+	}
+
+	// Set vertex buffers
+	for(U i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
+	{
+		const VertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
+		cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
+	}
+
+	// Index buffer
+	cmdb->bindIndexBuffer(modelInf.m_indexBuffer, 0, IndexType::U16);
+
+	// Uniforms
+	Array<Mat4, MAX_INSTANCES> trfs;
+	trfs[0] = Mat4(self.getParent()->getComponent<MoveComponent>().getWorldTransform());
+	for(U i = 0; i < elements.getSize(); ++i)
+	{
+		trfs[i] = trfs[0];
+	}
+
+	StagingGpuMemoryToken token;
+	self.getComponent<RenderComponent>().allocateAndSetupUniforms(ctx, trfs, *ctx.m_stagingGpuAllocator, token);
+	cmdb->bindUniformBuffer(0, 0, token.m_buffer, token.m_offset, token.m_range);
+
+	// Draw
+	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
+		modelInf.m_indicesCountArray[0],
+		elements.getSize(),
+		modelInf.m_indicesOffsetArray[0] / sizeof(U16),
+		0,
+		0);
+}
+
 /// Feedback component.
 /// Feedback component.
 class ModelMoveFeedbackComponent : public SceneComponent
 class ModelMoveFeedbackComponent : public SceneComponent
 {
 {
@@ -144,7 +211,7 @@ Error ModelNode::init(const CString& modelFname)
 	{
 	{
 		ModelPatchNode* mpn;
 		ModelPatchNode* mpn;
 		StringAuto nname(getFrameAllocator());
 		StringAuto nname(getFrameAllocator());
-		ANKI_CHECK(getSceneGraph().newSceneNode(CString(), mpn, *it));
+		ANKI_CHECK(getSceneGraph().newSceneNode(CString(), mpn, *it, count, *this));
 
 
 		m_modelPatches[count++] = mpn;
 		m_modelPatches[count++] = mpn;
 		addChild(mpn);
 		addChild(mpn);

+ 12 - 1
src/anki/scene/ModelNode.h

@@ -18,6 +18,7 @@ namespace anki
 // Forward
 // Forward
 class ObbSpatialComponent;
 class ObbSpatialComponent;
 class BodyComponent;
 class BodyComponent;
+class ModelNode;
 
 
 /// @addtogroup scene
 /// @addtogroup scene
 /// @{
 /// @{
@@ -33,13 +34,23 @@ public:
 
 
 	~ModelPatchNode();
 	~ModelPatchNode();
 
 
-	ANKI_USE_RESULT Error init(const ModelPatch* modelPatch);
+	ANKI_USE_RESULT Error init(const ModelPatch* modelPatch, U idx, const ModelNode& parent);
 
 
 private:
 private:
 	Obb m_obb; ///< In world space. ModelNode will update it.
 	Obb m_obb; ///< In world space. ModelNode will update it.
 	const ModelPatch* m_modelPatch = nullptr; ///< The resource
 	const ModelPatch* m_modelPatch = nullptr; ///< The resource
+	U64 m_mergeKey = 0;
 
 
 	ANKI_USE_RESULT Error buildRendering(const RenderingBuildInfoIn& in, RenderingBuildInfoOut& out) const;
 	ANKI_USE_RESULT Error buildRendering(const RenderingBuildInfoIn& in, RenderingBuildInfoOut& out) const;
+
+	void setupRenderQueueElement(RenderQueueElement& el) const
+	{
+		el.m_callback = drawCallback;
+		el.m_userData = this;
+		el.m_mergeKey = m_mergeKey;
+	}
+
+	static void drawCallback(RenderQueueDrawContext& ctx, WeakArray<const RenderQueueElement> elements);
 };
 };
 
 
 /// The model scene node
 /// The model scene node

+ 37 - 0
src/anki/scene/ParticleEmitter.cpp

@@ -178,6 +178,11 @@ public:
 	{
 	{
 		return getNode().buildRendering(in, out);
 		return getNode().buildRendering(in, out);
 	}
 	}
+
+	void setupRenderQueueElement(RenderQueueElement& el) const override
+	{
+		getNode().setupRenderQueueElement(el);
+	}
 };
 };
 
 
 /// Feedback component
 /// Feedback component
@@ -302,6 +307,38 @@ Error ParticleEmitter::buildRendering(const RenderingBuildInfoIn& in, RenderingB
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
+void ParticleEmitter::drawCallback(RenderQueueDrawContext& ctx, WeakArray<const RenderQueueElement> elements)
+{
+	ANKI_ASSERT(elements.getSize() == 1);
+
+	const ParticleEmitter& self = *static_cast<const ParticleEmitter*>(elements[0].m_userData);
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
+	// Program
+	ShaderProgramPtr prog;
+	self.m_particleEmitterResource->getRenderingInfo(ctx.m_key.m_lod, prog);
+	cmdb->bindShaderProgram(prog);
+
+	// Vertex attribs
+	cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
+	cmdb->setVertexAttribute(1, 0, PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT), sizeof(Vec3));
+	cmdb->setVertexAttribute(
+		2, 0, PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT), sizeof(Vec3) + sizeof(F32));
+
+	// Vertex buff
+	cmdb->bindVertexBuffer(
+		0, self.m_vertBuffToken.m_buffer, self.m_vertBuffToken.m_offset, VERTEX_SIZE, VertexStepRate::INSTANCE);
+
+	// Uniforms
+	Array<Mat4, 1> trf = {{Mat4::getIdentity()}};
+	StagingGpuMemoryToken token;
+	self.getComponent<RenderComponent>().allocateAndSetupUniforms(ctx, trf, *ctx.m_stagingGpuAllocator, token);
+	cmdb->bindUniformBuffer(0, 0, token.m_buffer, token.m_offset, token.m_range);
+
+	// Draw
+	cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4, self.m_aliveParticlesCount, 0, 0);
+}
+
 void ParticleEmitter::onMoveComponentUpdate(MoveComponent& move)
 void ParticleEmitter::onMoveComponentUpdate(MoveComponent& move)
 {
 {
 	m_identityRotation = move.getWorldTransform().getRotation() == Mat3x4::getIdentity();
 	m_identityRotation = move.getWorldTransform().getRotation() == Mat3x4::getIdentity();

+ 9 - 0
src/anki/scene/ParticleEmitter.h

@@ -201,6 +201,15 @@ private:
 	ANKI_USE_RESULT Error buildRendering(const RenderingBuildInfoIn& in, RenderingBuildInfoOut& out) const;
 	ANKI_USE_RESULT Error buildRendering(const RenderingBuildInfoIn& in, RenderingBuildInfoOut& out) const;
 
 
 	void onMoveComponentUpdate(MoveComponent& move);
 	void onMoveComponentUpdate(MoveComponent& move);
+
+	void setupRenderQueueElement(RenderQueueElement& el) const
+	{
+		el.m_callback = drawCallback;
+		el.m_mergeKey = 0;
+		el.m_userData = this;
+	}
+
+	static void drawCallback(RenderQueueDrawContext& ctx, WeakArray<const RenderQueueElement> elements);
 };
 };
 /// @}
 /// @}
 
 

+ 1 - 1
src/anki/scene/RenderComponent.cpp

@@ -194,7 +194,7 @@ void RenderComponent::allocateAndSetupUniforms(const RenderQueueDrawContext& ctx
 		case ShaderVariableDataType::SAMPLER_3D:
 		case ShaderVariableDataType::SAMPLER_3D:
 		case ShaderVariableDataType::SAMPLER_CUBE:
 		case ShaderVariableDataType::SAMPLER_CUBE:
 		{
 		{
-			ctx.m_cmdb->bindTexture(
+			ctx.m_commandBuffer->bindTexture(
 				0, progVariant.getTextureUnit(progvar), mvar.getValue<TextureResourcePtr>()->getGrTexture());
 				0, progVariant.getTextureUnit(progvar), mvar.getValue<TextureResourcePtr>()->getGrTexture());
 			break;
 			break;
 		}
 		}

+ 2 - 0
src/anki/scene/RenderComponent.h

@@ -214,6 +214,8 @@ public:
 		StagingGpuMemoryManager& alloc,
 		StagingGpuMemoryManager& alloc,
 		StagingGpuMemoryToken& token) const;
 		StagingGpuMemoryToken& token) const;
 
 
+	virtual void setupRenderQueueElement(RenderQueueElement& el) const = 0;
+
 private:
 private:
 	Variables m_vars;
 	Variables m_vars;
 	MaterialResourcePtr m_mtl;
 	MaterialResourcePtr m_mtl;

+ 5 - 0
src/anki/scene/StaticGeometryNode.cpp

@@ -27,6 +27,11 @@ public:
 	{
 	{
 		return m_node->buildRendering(in, out);
 		return m_node->buildRendering(in, out);
 	}
 	}
+
+	void setupRenderQueueElement(RenderQueueElement& el) const override
+	{
+		ANKI_ASSERT(!"TODO");
+	}
 };
 };
 
 
 StaticGeometryPatchNode::StaticGeometryPatchNode(SceneGraph* scene, CString name)
 StaticGeometryPatchNode::StaticGeometryPatchNode(SceneGraph* scene, CString name)