浏览代码

GPU particles: fixes

Panagiotis Christopoulos Charitos 1 月之前
父节点
当前提交
481454fa3f

+ 1 - 1
AnKi/Gr/D3D/D3DShaderProgram.cpp

@@ -52,7 +52,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	ANKI_ASSERT(inf.isValid());
 
 	// Create the shader references
-	GrHashMap<U64, U32> shaderUuidToMShadersIdx; // Shader UUID to m_shaders idx
+	GrHashMap<U32, U32> shaderUuidToMShadersIdx; // Shader UUID to m_shaders idx
 	if(inf.m_computeShader)
 	{
 		m_shaders.emplaceBack(inf.m_computeShader);

+ 2 - 2
AnKi/Gr/GrManager.h

@@ -90,14 +90,14 @@ public:
 		return m_cacheDir.toCString();
 	}
 
-	ANKI_INTERNAL U64 getNewUuid()
+	ANKI_INTERNAL U32 getNewUuid()
 	{
 		return m_uuidIndex.fetchAdd(1);
 	}
 
 protected:
 	GrString m_cacheDir;
-	Atomic<U64> m_uuidIndex = {1};
+	Atomic<U32> m_uuidIndex = {1};
 	GpuDeviceCapabilities m_capabilities;
 
 	GrManager();

+ 6 - 10
AnKi/Gr/GrObject.h

@@ -10,10 +10,7 @@
 
 namespace anki {
 
-/// @addtogroup graphics
-/// @{
-
-/// Graphics object type.
+// Graphics object type
 enum class GrObjectType : U8
 {
 	kBuffer,
@@ -35,7 +32,7 @@ enum class GrObjectType : U8
 	kFirst = 0
 };
 
-/// Base of all graphics objects.
+// Base of all graphics objects
 class GrObject
 {
 public:
@@ -62,13 +59,13 @@ public:
 		return m_refcount.fetchSub(1);
 	}
 
-	/// A unique identifier for caching objects.
-	U64 getUuid() const
+	// A unique identifier for caching objects
+	U32 getUuid() const
 	{
 		return m_uuid;
 	}
 
-	/// Get its name.
+	// Get its name
 	CString getName() const
 	{
 		return m_name;
@@ -76,10 +73,9 @@ public:
 
 private:
 	Char* m_name = nullptr;
-	U64 m_uuid;
+	U32 m_uuid;
 	mutable Atomic<I32> m_refcount;
 	GrObjectType m_type;
 };
-/// @}
 
 } // end namespace anki

+ 1 - 1
AnKi/Gr/Vulkan/VkCommandBuffer.cpp

@@ -362,7 +362,7 @@ void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
 		bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
 	}
 
-	self.m_descriptorState.setPipelineLayout(&impl.getPipelineLayout(), bindPoint);
+	self.m_descriptorState.setShaderProgram(&impl.getPipelineLayout(), impl.getUuid(), bindPoint);
 }
 
 void CommandBuffer::beginRenderPass(ConstWeakArray<RenderTarget> colorRts, RenderTarget* depthStencilRt, const TextureView& vrsRt, U8 vrsRtTexelSizeX,

+ 10 - 4
AnKi/Gr/Vulkan/VkDescriptor.h

@@ -155,18 +155,23 @@ public:
 		}
 	}
 
-	void setPipelineLayout(const PipelineLayout2* layout, VkPipelineBindPoint bindPoint)
+	void setShaderProgram(const PipelineLayout2* layout, U32 shaderProgramUuid, VkPipelineBindPoint bindPoint)
 	{
-		ANKI_ASSERT(layout);
-		if(layout != m_pipelineLayout || bindPoint != m_pipelineBindPoint)
+		ANKI_ASSERT(layout && shaderProgramUuid != 0);
+
+		// Make it dirty if the program changed as well. There is a case where 2 different programs end up with the same ppline layout because of
+		// the binding re-write in SPIR-V
+		const Bool programChanged = m_shaderProgramUuid != shaderProgramUuid;
+		if(layout != m_pipelineLayout || bindPoint != m_pipelineBindPoint || programChanged)
 		{
+			m_shaderProgramUuid = shaderProgramUuid;
 			m_pipelineLayout = layout;
 			m_pipelineBindPoint = bindPoint;
 			m_pushConstantsDirty = m_pushConstantsDirty || (m_pushConstSize != m_pipelineLayout->m_refl.m_fastConstantsSize);
 
 			for(U32 iset = 0; iset < m_pipelineLayout->m_dsetCount; ++iset)
 			{
-				if(m_sets[iset].m_dsLayout != m_pipelineLayout->m_dsetLayouts[iset])
+				if(m_sets[iset].m_dsLayout != m_pipelineLayout->m_dsetLayouts[iset] || programChanged)
 				{
 					m_sets[iset].m_dirty = true;
 					m_sets[iset].m_dsLayout = m_pipelineLayout->m_dsetLayouts[iset];
@@ -330,6 +335,7 @@ private:
 	};
 
 	const PipelineLayout2* m_pipelineLayout = nullptr;
+	U32 m_shaderProgramUuid = 0;
 	VkPipelineBindPoint m_pipelineBindPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM;
 	Array<DescriptorSet, kMaxRegisterSpaces> m_sets;
 	Array<VkDescriptorSet, kMaxRegisterSpaces> m_vkDsets = {};

+ 1 - 1
AnKi/Gr/Vulkan/VkShaderProgram.cpp

@@ -160,7 +160,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 
 	// Create the shader references
 	//
-	GrHashMap<U64, U32> shaderUuidToMShadersIdx; // Shader UUID to m_shaders idx
+	GrHashMap<U32, U32> shaderUuidToMShadersIdx; // Shader UUID to m_shaders idx
 	if(inf.m_computeShader)
 	{
 		m_shaders.emplaceBack(inf.m_computeShader);

+ 5 - 0
AnKi/Renderer/Utils/Drawer.cpp

@@ -71,6 +71,7 @@ void RenderableDrawer::setState(const RenderableDrawerArguments& args, CommandBu
 	cmdb.bindSrv(ANKI_MATERIAL_REGISTER_TRANSFORMS, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
 	cmdb.bindSrv(ANKI_MATERIAL_REGISTER_PARTICLE_EMITTERS, 0, GpuSceneArrays::ParticleEmitter::getSingleton().getBufferViewSafe());
 	cmdb.bindSrv(ANKI_MATERIAL_REGISTER_PARTICLE_EMITTERS2, 0, GpuSceneArrays::ParticleEmitter2::getSingleton().getBufferViewSafe());
+
 	cmdb.bindSampler(ANKI_MATERIAL_REGISTER_NEAREST_CLAMP_SAMPLER, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 	if(args.m_legacy.m_perDrawBuffer)
 	{
@@ -129,6 +130,8 @@ void RenderableDrawer::drawMdi(const RenderableDrawerArguments& args, CommandBuf
 			return;
 		}
 
+		cmdb.pushDebugMarker(state.m_program->getName(), Vec3(0.0f, 1.0f, 0.0f));
+
 		cmdb.bindShaderProgram(state.m_program.get());
 
 		const Bool bMeshlets = meshletCount > 0;
@@ -169,6 +172,8 @@ void RenderableDrawer::drawMdi(const RenderableDrawerArguments& args, CommandBuf
 			cmdb.drawIndexedIndirectCount(state.m_primitiveTopology, indirectArgsBuffView, sizeof(DrawIndexedIndirectArgs), mdiCountBuffView,
 										  maxDrawCount);
 		}
+
+		cmdb.popDebugMarker();
 	});
 
 #if ANKI_STATS_ENABLED

+ 2 - 2
AnKi/Scene/RenderStateBucket.cpp

@@ -24,9 +24,9 @@ RenderStateBucketContainer::~RenderStateBucketContainer()
 RenderStateBucketIndex RenderStateBucketContainer::addUser(const RenderStateInfo& state, RenderingTechnique technique, U32 lod0MeshletCount)
 {
 	// Compute state gash
-	Array<U64, 2> toHash;
+	Array<U32, 2> toHash;
 	toHash[0] = state.m_program->getUuid();
-	toHash[1] = U64(state.m_primitiveTopology);
+	toHash[1] = U32(state.m_primitiveTopology);
 	const U64 hash = computeHash(toHash.getBegin(), toHash.getSizeInBytes());
 
 	SceneDynamicArray<ExtendedBucket>& buckets = m_buckets[technique];

+ 98 - 0
AnKi/Shaders/ForwardShadingParticlesGass.ankiprog

@@ -0,0 +1,98 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki 16bit
+
+#pragma anki mutator ANIMATED_TEXTURE 0 1
+#pragma anki mutator LIGHT 0 1
+
+#pragma anki technique ForwardLegacy vert pixel
+
+#include <AnKi/Shaders/ForwardShadingCommon.hlsl>
+
+struct VertIn
+{
+	U32 m_svVertexId : SV_VERTEXID;
+	U32 m_svInstanceId : SV_INSTANCEID;
+};
+
+struct VertOut
+{
+	nointerpolation U32 m_constantsOffset : UNIS_OFFSET;
+	nointerpolation F32 m_alpha : ALPHA;
+	Vec2 m_uv : TEXCOORD;
+	Vec3 m_worldPos : WORLD_POS;
+	Vec4 m_svPosition : SV_POSITION;
+};
+
+#pragma anki struct AnKiLocalConstants
+#pragma anki member F32 m_textureAnimationPeriod 0.0
+#pragma anki member Vec4 m_colorScale 1.0 1.0 1.0 1.0
+#pragma anki member Vec4 m_colorBias 0.0 0.0 0.0 0.0
+#pragma anki member U32 m_diffuseTex 0
+#pragma anki struct_end
+
+#if ANKI_VERTEX_SHADER
+VertOut main(VertIn input)
+{
+	const GpuScenePerDraw instance = getGpuScenePerDraw();
+	const GpuSceneParticleEmitter2 particles = SBUFF(g_particleEmitters2, instance.m_particleEmitterIndex);
+	const GpuSceneMeshLod meshLod = SBUFF(g_meshLods, instance.m_meshLodIndex);
+
+	const U32 particleId = input.m_svInstanceId;
+
+	U32 offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kPosition] + particleId * sizeof(Vec3);
+	const Vec3 particlePos = BAB_LOAD(g_gpuScene, Vec3, offset);
+
+	offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kScale] + particleId * sizeof(Vec3);
+	const F32 particleScale = BAB_LOAD(g_gpuScene, Vec3, offset).x;
+
+	offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kUserDefined1] + particleId * sizeof(Vec4);
+	const F32 particleAlpha = BAB_LOAD(g_gpuScene, Vec4, offset).z;
+
+	VertOut output;
+
+	output.m_uv = g_unifiedGeom_R32G32_Sfloat[meshLod.m_vertexOffsets[(U32)VertexStreamId::kUv] + input.m_svVertexId];
+
+	const Vec3 localPos =
+		g_unifiedGeom_R16G16B16A16_Unorm[meshLod.m_vertexOffsets[(U32)VertexStreamId::kPosition] + input.m_svVertexId] * meshLod.m_positionScale
+		+ meshLod.m_positionTranslation;
+
+	// Apply the particle scale, rotate the mesh to face the camera (billboard) and finally apply the particle position
+	output.m_worldPos = mul(g_globalConstants.m_cameraTransform, Vec4(localPos * particleScale, 0.0)) + particlePos;
+
+	output.m_svPosition = mul(g_globalConstants.m_viewProjectionMatrix, Vec4(output.m_worldPos, 1.0));
+
+	output.m_alpha = particleAlpha;
+	output.m_constantsOffset = instance.m_constantsOffset;
+
+	return output;
+}
+#endif // ANKI_VERTEX_SHADER
+
+#if ANKI_PIXEL_SHADER
+PixelOut main(VertOut input)
+{
+	PixelOut output = (PixelOut)0;
+	const AnKiLocalConstants localConstants = loadAnKiLocalConstants(g_gpuScene, WaveReadLaneFirst(input.m_constantsOffset));
+
+#	if ANIMATED_TEXTURE == 1
+	Vec4 texCol = readAnimatedTextureRgba(getBindlessTexture2DArrayVec4(localConstants.m_diffuseTex), g_globalSampler,
+										  localConstants.m_textureAnimationPeriod, input.m_uv, g_globalRendererConstants.m_time);
+#	else
+	Vec4 texCol = getBindlessTexture2DVec4(localConstants.m_diffuseTex).Sample(g_globalSampler, input.m_uv);
+#	endif
+
+#	if LIGHT
+	texCol.rgb = computeLightColorLow(texCol.rgb, input.m_worldPos, input.m_svPosition);
+#	endif
+
+	Vec4 colScale = localConstants.m_colorScale;
+	colScale.a *= input.m_alpha;
+	particleAlpha(texCol, colScale, localConstants.m_colorBias, output);
+
+	return output;
+}
+#endif // ANKI_PIXEL_SHADER

+ 1 - 1
AnKi/Shaders/GpuParticlesGass.ankiprog

@@ -201,7 +201,7 @@ void initializeParticle(AnKiParticleEmitterProperties props, GpuSceneParticleEmi
 		{
 			// Inform about the bounding volume
 			const F32 toMeters = 1.0 / 100.0;
-			ParticleSimulationCpuFeedback feedback;
+			ParticleSimulationCpuFeedback feedback = (ParticleSimulationCpuFeedback)0;
 			feedback.m_aabbMin = g_scratch[0].m_aabbMin * toMeters;
 			feedback.m_aabbMax = g_scratch[0].m_aabbMax * toMeters;
 			feedback.m_uuid = emitter.m_uuid;

+ 2 - 1
AnKi/Shaders/GpuVisibilityStage2And3.ankiprog

@@ -118,7 +118,8 @@ RWStructuredBuffer<U32> g_outOfMemoryBuffer : register(u3);
 		GpuScenePerDraw perDraw;
 		perDraw.m_worldTransformsIndex = renderable.m_worldTransformsIndex;
 		perDraw.m_isParticleEmitter = isParticleEmitter;
-		perDraw.m_particleEmitterIndex = renderable.m_particleEmitterIndex;
+		perDraw.m_particleEmitterIndex =
+			(renderable.m_particleEmitterIndex < kMaxU32) ? renderable.m_particleEmitterIndex : renderable.m_particleEmitterIndex2;
 		perDraw.m_constantsOffset = renderable.m_constantsOffset;
 		perDraw.m_meshLodIndex = meshLodIndex;
 		perDraw.m_boneTransformsOffset = renderable.m_boneTransformsOffset;

+ 1 - 1
Tests/Util/BuddyAllocatorBuilder.cpp

@@ -56,7 +56,7 @@ ANKI_TEST(Util, BuddyAllocatorBuilder)
 			{
 				// Do an allocation
 				U32 addr;
-				const U32 size = max<U32>(getRandom() % 256_MB, 1);
+				const U32 size = U32(max<U64>(getRandom() % 256_MB, 1));
 				const U32 alignment = max<U32>(getRandom() % 24, 1);
 				const Bool success = buddy.allocate(size, alignment, addr);
 				// printf("al %u %u\n", size, alignment);