emitter and surfelgi indirect arguments refactor

This commit is contained in:
Turánszki János
2026-02-07 13:00:10 +01:00
parent 81f4973313
commit 5226f07cf6
11 changed files with 67 additions and 46 deletions
+9 -7
View File
@@ -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:
@@ -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)
@@ -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!");
+2 -2
View File
@@ -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
{
@@ -3,7 +3,7 @@
ByteAddressBuffer counterBuffer : register(t0);
RWByteAddressBuffer indirectBuffers : register(u0);
RWStructuredBuffer<EmitterIndirectArgs> 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<IndirectDispatchArgs>(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<IndirectDrawArgsInstanced>(ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, args);
indirectBuffer[0].draw = args;
}
}
@@ -2,7 +2,7 @@
#include "ShaderInterop_EmittedParticle.h"
RWByteAddressBuffer counterBuffer : register(u4);
RWByteAddressBuffer indirectBuffers : register(u5);
RWStructuredBuffer<EmitterIndirectArgs> 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<int>(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);
@@ -2,7 +2,7 @@
#include "ShaderInterop_SurfelGI.h"
RWByteAddressBuffer surfelStatsBuffer : register(u0);
RWByteAddressBuffer surfelIndirectBuffer : register(u1);
RWStructuredBuffer<SurfelIndirectArgs> 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;
}
+12 -14
View File
@@ -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);
}
}
+4 -4
View File
@@ -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[] = {
+3 -2
View File
@@ -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");
+1 -1
View File
@@ -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);