From 5226f07cf6036a5293472b566cf2020ccf32fb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Sat, 7 Feb 2026 13:00:10 +0100 Subject: [PATCH] emitter and surfelgi indirect arguments refactor --- WickedEngine/shaders/ShaderInterop.h | 16 +++++++----- .../shaders/ShaderInterop_EmittedParticle.h | 7 +++-- WickedEngine/shaders/ShaderInterop_SurfelGI.h | 11 +++++--- WickedEngine/shaders/emittedparticleMS.hlsl | 4 +-- .../emittedparticle_finishUpdateCS.hlsl | 8 +++--- .../emittedparticle_kickoffUpdateCS.hlsl | 6 +++-- .../shaders/surfel_indirectprepareCS.hlsl | 20 +++++++++++--- WickedEngine/wiEmittedParticle.cpp | 26 +++++++++---------- WickedEngine/wiRenderer.cpp | 8 +++--- WickedEngine/wiScene.cpp | 5 ++-- WickedEngine/wiVersion.cpp | 2 +- 11 files changed, 67 insertions(+), 46 deletions(-) diff --git a/WickedEngine/shaders/ShaderInterop.h b/WickedEngine/shaders/ShaderInterop.h index 95c34168f..f0de639c0 100644 --- a/WickedEngine/shaders/ShaderInterop.h +++ b/WickedEngine/shaders/ShaderInterop.h @@ -66,21 +66,23 @@ struct IndirectDrawArgsIndexedInstanced uint StartIndexLocation; int BaseVertexLocation; uint StartInstanceLocation; +#if defined(__SCE__) || defined(__PSSL__) + uint padding0; +#endif // __SCE__ || __PSSL__ }; struct IndirectDispatchArgs { uint ThreadGroupCountX; uint ThreadGroupCountY; uint ThreadGroupCountZ; -}; - #if defined(__SCE__) || defined(__PSSL__) -static const uint IndirectDrawArgsAlignment = 8u; -static const uint IndirectDispatchArgsAlignment = 32u; -#else -static const uint IndirectDrawArgsAlignment = 4u; -static const uint IndirectDispatchArgsAlignment = 4u; + uint padding0; + uint padding1; + uint padding2; + uint padding3; + uint padding4; #endif // __SCE__ || __PSSL__ +}; #if !defined(__PSSL__) && !defined(__SCE__) // Common buffers: diff --git a/WickedEngine/shaders/ShaderInterop_EmittedParticle.h b/WickedEngine/shaders/ShaderInterop_EmittedParticle.h index bc9060528..0eb738ef9 100644 --- a/WickedEngine/shaders/ShaderInterop_EmittedParticle.h +++ b/WickedEngine/shaders/ShaderInterop_EmittedParticle.h @@ -104,8 +104,11 @@ struct EmitLocation static const uint THREADCOUNT_MESH_SHADER = 32; -static const uint ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION = 0; -static const uint ARGUMENTBUFFER_OFFSET_DRAWPARTICLES = align(ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION + (3 * 4), IndirectDrawArgsAlignment); +struct EmitterIndirectArgs +{ + IndirectDispatchArgs dispatch; + IndirectDrawArgsInstanced draw; +}; // If this is not defined, SPH will be resolved as N-body simulation (O(n^2) complexity) diff --git a/WickedEngine/shaders/ShaderInterop_SurfelGI.h b/WickedEngine/shaders/ShaderInterop_SurfelGI.h index 93cce189b..2ad0d6245 100644 --- a/WickedEngine/shaders/ShaderInterop_SurfelGI.h +++ b/WickedEngine/shaders/ShaderInterop_SurfelGI.h @@ -19,10 +19,6 @@ static const uint SURFEL_STATS_OFFSET_CELLALLOCATOR = SURFEL_STATS_OFFSET_DEADCO static const uint SURFEL_STATS_OFFSET_RAYCOUNT = SURFEL_STATS_OFFSET_CELLALLOCATOR + 4; static const uint SURFEL_STATS_OFFSET_SHORTAGE = SURFEL_STATS_OFFSET_RAYCOUNT + 4; static const uint SURFEL_STATS_SIZE = SURFEL_STATS_OFFSET_SHORTAGE + 4; -static const uint SURFEL_INDIRECT_OFFSET_ITERATE = 0; -static const uint SURFEL_INDIRECT_OFFSET_RAYTRACE = align(SURFEL_INDIRECT_OFFSET_ITERATE + 4 * 3, IndirectDispatchArgsAlignment); -static const uint SURFEL_INDIRECT_OFFSET_INTEGRATE = align(SURFEL_INDIRECT_OFFSET_RAYTRACE + 4 * 3, IndirectDispatchArgsAlignment); -static const uint SURFEL_INDIRECT_SIZE = SURFEL_INDIRECT_OFFSET_INTEGRATE + 4 * 3; static const uint SURFEL_INDIRECT_NUMTHREADS = 32; static const float SURFEL_TARGET_COVERAGE = 0.8f; // how many surfels should affect a pixel fully, higher values will increase quality and cost static const uint SURFEL_CELL_LIMIT = ~0; // limit the amount of allocated surfels in a cell @@ -32,6 +28,13 @@ static const uint SURFEL_RAY_BOOST_MAX = 64; // max amount of rays per surfel #define SURFEL_USE_HASHING // if defined, hashing will be used to retrieve surfels, hashing is good because it supports infinite world trivially, but slower due to hash collisions #define SURFEL_ENABLE_INFINITE_BOUNCES // if defined, previous frame's surfel data will be sampled at ray tracing hit points +struct SurfelIndirectArgs +{ + IndirectDispatchArgs iterate; + IndirectDispatchArgs raytrace; + IndirectDispatchArgs integrate; +}; + #ifdef __cplusplus static_assert(SURFEL_RECYCLE_TIME < 256, "Must be < 256 because it is packed at 8 bits!"); static_assert(SURFEL_RAY_BOOST_MAX < 256, "Must be < 256 because it is packed at 8 bits!"); diff --git a/WickedEngine/shaders/emittedparticleMS.hlsl b/WickedEngine/shaders/emittedparticleMS.hlsl index 2468ba156..b4ee31775 100644 --- a/WickedEngine/shaders/emittedparticleMS.hlsl +++ b/WickedEngine/shaders/emittedparticleMS.hlsl @@ -22,9 +22,9 @@ static const uint PRIMITIVECOUNT = THREADCOUNT_MESH_SHADER * 2; struct VertextoPixel_MS { float4 pos : SV_POSITION; - float clip : SV_ClipDistance0; - half4 tex : TEXCOORD0; + float4 tex : TEXCOORD0; half2 unrotated_uv : UNROTATED_UV; + float clip : SV_ClipDistance0; }; struct VertextoPixel_MS_PRIM { diff --git a/WickedEngine/shaders/emittedparticle_finishUpdateCS.hlsl b/WickedEngine/shaders/emittedparticle_finishUpdateCS.hlsl index 0ca06bb32..0a96517d8 100644 --- a/WickedEngine/shaders/emittedparticle_finishUpdateCS.hlsl +++ b/WickedEngine/shaders/emittedparticle_finishUpdateCS.hlsl @@ -3,7 +3,7 @@ ByteAddressBuffer counterBuffer : register(t0); -RWByteAddressBuffer indirectBuffers : register(u0); +RWStructuredBuffer indirectBuffer : register(u0); [numthreads(1, 1, 1)] void main( uint3 DTid : SV_DispatchThreadID ) @@ -14,10 +14,10 @@ void main( uint3 DTid : SV_DispatchThreadID ) { // Create DispatchMesh argument buffer: IndirectDispatchArgs args; - args.ThreadGroupCountX = (particleCount + 31) / 32; + args.ThreadGroupCountX = (particleCount + THREADCOUNT_MESH_SHADER - 1) / THREADCOUNT_MESH_SHADER; args.ThreadGroupCountY = 1; args.ThreadGroupCountZ = 1; - indirectBuffers.Store(ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, args); + indirectBuffer[0].dispatch = args; } else { @@ -27,6 +27,6 @@ void main( uint3 DTid : SV_DispatchThreadID ) args.InstanceCount = particleCount; args.StartVertexLocation = 0; args.StartInstanceLocation = 0; - indirectBuffers.Store(ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, args); + indirectBuffer[0].draw = args; } } diff --git a/WickedEngine/shaders/emittedparticle_kickoffUpdateCS.hlsl b/WickedEngine/shaders/emittedparticle_kickoffUpdateCS.hlsl index 812c710be..1f6b901f4 100644 --- a/WickedEngine/shaders/emittedparticle_kickoffUpdateCS.hlsl +++ b/WickedEngine/shaders/emittedparticle_kickoffUpdateCS.hlsl @@ -2,7 +2,7 @@ #include "ShaderInterop_EmittedParticle.h" RWByteAddressBuffer counterBuffer : register(u4); -RWByteAddressBuffer indirectBuffers : register(u5); +RWStructuredBuffer indirectBuffer : register(u5); [numthreads(1, 1, 1)] void main(uint3 DTid : SV_DispatchThreadID) @@ -10,7 +10,9 @@ void main(uint3 DTid : SV_DispatchThreadID) uint aliveCount = counterBuffer.Load(PARTICLECOUNTER_OFFSET_ALIVECOUNT_AFTERSIMULATION); int deadCount = counterBuffer.Load(PARTICLECOUNTER_OFFSET_DEADCOUNT); - indirectBuffers.Store3(ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, uint3((aliveCount + THREADCOUNT_SIMULATION - 1) / THREADCOUNT_SIMULATION, 1, 1)); + indirectBuffer[0].dispatch.ThreadGroupCountX = (aliveCount + THREADCOUNT_SIMULATION - 1) / THREADCOUNT_SIMULATION; + indirectBuffer[0].dispatch.ThreadGroupCountY = 1; + indirectBuffer[0].dispatch.ThreadGroupCountZ = 1; counterBuffer.Store(PARTICLECOUNTER_OFFSET_ALIVECOUNT, aliveCount); counterBuffer.Store(PARTICLECOUNTER_OFFSET_ALIVECOUNT_AFTERSIMULATION, 0); diff --git a/WickedEngine/shaders/surfel_indirectprepareCS.hlsl b/WickedEngine/shaders/surfel_indirectprepareCS.hlsl index d6e8ebc6a..d13c82cc5 100644 --- a/WickedEngine/shaders/surfel_indirectprepareCS.hlsl +++ b/WickedEngine/shaders/surfel_indirectprepareCS.hlsl @@ -2,7 +2,7 @@ #include "ShaderInterop_SurfelGI.h" RWByteAddressBuffer surfelStatsBuffer : register(u0); -RWByteAddressBuffer surfelIndirectBuffer : register(u1); +RWStructuredBuffer surfelIndirectBuffer : register(u1); [numthreads(1, 1, 1)] void main(uint3 DTid : SV_DispatchThreadID) @@ -23,7 +23,19 @@ void main(uint3 DTid : SV_DispatchThreadID) surfelStatsBuffer.Store(SURFEL_STATS_OFFSET_RAYCOUNT, 0); surfelStatsBuffer.Store(SURFEL_STATS_OFFSET_SHORTAGE, shortage); - surfelIndirectBuffer.Store3(SURFEL_INDIRECT_OFFSET_ITERATE, uint3((surfel_count + SURFEL_INDIRECT_NUMTHREADS - 1) / SURFEL_INDIRECT_NUMTHREADS, 1, 1)); - surfelIndirectBuffer.Store3(SURFEL_INDIRECT_OFFSET_RAYTRACE, uint3((ray_count + SURFEL_INDIRECT_NUMTHREADS - 1) / SURFEL_INDIRECT_NUMTHREADS, 1, 1)); - surfelIndirectBuffer.Store3(SURFEL_INDIRECT_OFFSET_INTEGRATE, uint3(surfel_count, 1, 1)); + SurfelIndirectArgs args; + + args.iterate.ThreadGroupCountX = (surfel_count + SURFEL_INDIRECT_NUMTHREADS - 1) / SURFEL_INDIRECT_NUMTHREADS; + args.iterate.ThreadGroupCountY = 1; + args.iterate.ThreadGroupCountZ = 1; + + args.raytrace.ThreadGroupCountX = (ray_count + SURFEL_INDIRECT_NUMTHREADS - 1) / SURFEL_INDIRECT_NUMTHREADS; + args.raytrace.ThreadGroupCountY = 1; + args.raytrace.ThreadGroupCountZ = 1; + + args.integrate.ThreadGroupCountX = surfel_count; + args.integrate.ThreadGroupCountY = 1; + args.integrate.ThreadGroupCountZ = 1; + + surfelIndirectBuffer[0] = args; } diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index d124ba5a8..9abc0b320 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -240,11 +240,9 @@ namespace wi // Indirect Execution buffer: bd.usage = Usage::DEFAULT; bd.bind_flags = BindFlag::UNORDERED_ACCESS; - bd.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; - bd.size = - align((uint64_t)sizeof(IndirectDispatchArgs), (uint64_t)IndirectDispatchArgsAlignment) + - align((uint64_t)sizeof(IndirectDispatchArgs), (uint64_t)IndirectDispatchArgsAlignment) + - align((uint64_t)sizeof(IndirectDrawArgsInstanced), (uint64_t)IndirectDrawArgsAlignment); + bd.misc_flags = ResourceMiscFlag::BUFFER_STRUCTURED | ResourceMiscFlag::INDIRECT_ARGS; + bd.stride = sizeof(EmitterIndirectArgs); + bd.size = bd.stride; device->CreateBufferZeroed(&bd, &indirectBuffers); device->SetName(&indirectBuffers, "EmittedParticleSystem::indirectBuffers"); @@ -618,7 +616,7 @@ namespace wi &sphGridCells, }; device->BindUAVs(uav_partition, 0, arraysize(uav_partition), cmd); - device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); + device->DispatchIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(&sphGridCells), @@ -663,7 +661,7 @@ namespace wi &sphParticleCells, }; device->BindUAVs(uav_binning, 0, arraysize(uav_binning), cmd); - device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); + device->DispatchIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); { GPUBarrier barriers[] = { GPUBarrier::Buffer(&sphGridCells, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), @@ -690,7 +688,7 @@ namespace wi &densityBuffer }; device->BindUAVs(uav_density, 0, arraysize(uav_density), cmd); - device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); + device->DispatchIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); device->Barrier(GPUBarrier::Memory(), cmd); device->EventEnd(cmd); @@ -709,7 +707,7 @@ namespace wi &particleBuffer, }; device->BindUAVs(uav_force, 0, arraysize(uav_force), cmd); - device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); + device->DispatchIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); device->Barrier(GPUBarrier::Memory(), cmd); device->EventEnd(cmd); @@ -760,7 +758,7 @@ namespace wi device->BindComputeShader(&simulateCS, cmd); } } - device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); + device->DispatchIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), @@ -868,11 +866,11 @@ namespace wi if (ALLOW_MESH_SHADER && device->CheckCapability(GraphicsDeviceCapability::MESH_SHADER)) { - device->DispatchMeshIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, cmd); + device->DispatchMeshIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); } else { - device->DrawInstancedIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, cmd); + device->DrawInstancedIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, draw), cmd); } if (wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_OVERLAY) @@ -880,11 +878,11 @@ namespace wi device->BindPipelineState(&PSO_wire, cmd); if (ALLOW_MESH_SHADER && device->CheckCapability(GraphicsDeviceCapability::MESH_SHADER)) { - device->DispatchMeshIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, cmd); + device->DispatchMeshIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, dispatch), cmd); } else { - device->DrawInstancedIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, cmd); + device->DrawInstancedIndirect(&indirectBuffers, offsetof(EmitterIndirectArgs, draw), cmd); } } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 312bf6961..e87b9b883 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -12046,7 +12046,7 @@ void SurfelGI( }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->DispatchIndirect(&scene.surfelgi.indirectBuffer, SURFEL_INDIRECT_OFFSET_ITERATE, cmd); + device->DispatchIndirect(&scene.surfelgi.indirectBuffer, offsetof(SurfelIndirectArgs, iterate), cmd); { GPUBarrier barriers[] = { @@ -12110,7 +12110,7 @@ void SurfelGI( }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->DispatchIndirect(&scene.surfelgi.indirectBuffer, SURFEL_INDIRECT_OFFSET_ITERATE, cmd); + device->DispatchIndirect(&scene.surfelgi.indirectBuffer, offsetof(SurfelIndirectArgs, iterate), cmd); { GPUBarrier barriers[] = { @@ -12146,7 +12146,7 @@ void SurfelGI( }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->DispatchIndirect(&scene.surfelgi.indirectBuffer, SURFEL_INDIRECT_OFFSET_RAYTRACE, cmd); + device->DispatchIndirect(&scene.surfelgi.indirectBuffer, offsetof(SurfelIndirectArgs, raytrace), cmd); { GPUBarrier barriers[] = { @@ -12187,7 +12187,7 @@ void SurfelGI( device->Barrier(barriers, arraysize(barriers), cmd); } - device->DispatchIndirect(&scene.surfelgi.indirectBuffer, SURFEL_INDIRECT_OFFSET_INTEGRATE, cmd); + device->DispatchIndirect(&scene.surfelgi.indirectBuffer, offsetof(SurfelIndirectArgs, integrate), cmd); { GPUBarrier barriers[] = { diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 3b835d84e..b4bad3b62 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -537,8 +537,9 @@ namespace wi::scene device->SetName(&surfelgi.statsBuffer, "surfelgi.statsBuffer"); buf.stride = sizeof(uint); - buf.size = SURFEL_INDIRECT_SIZE; - buf.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; + buf.stride = sizeof(SurfelIndirectArgs); + buf.size = buf.stride; + buf.misc_flags = ResourceMiscFlag::BUFFER_STRUCTURED | ResourceMiscFlag::INDIRECT_ARGS; device->CreateBufferZeroed(&buf, &surfelgi.indirectBuffer); device->SetName(&surfelgi.indirectBuffer, "surfelgi.indirectBuffer"); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 4570e10e3..803bff55f 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 72; // minor bug fixes, alterations, refactors, updates - const int revision = 28; + const int revision = 29; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);