2021-09-09 20:42:29 -04:00

139 lines
3.9 KiB
Plaintext

#pragma kernel CSMain
${VFXGlobalInclude}
${VFXGlobalDeclaration}
#define USE_DEAD_LIST (VFX_USE_ALIVE_CURRENT && !HAS_STRIPS)
RWByteAddressBuffer attributeBuffer;
ByteAddressBuffer sourceAttributeBuffer;
CBUFFER_START(initParams)
#if !VFX_USE_SPAWNER_FROM_GPU
uint nbSpawned; // Numbers of particle spawned
uint spawnIndex; // Index of the first particle spawned
uint dispatchWidth;
#else
uint offsetInAdditionalOutput;
uint nbMax;
#endif
uint systemSeed;
CBUFFER_END
#if USE_DEAD_LIST
RWStructuredBuffer<uint> deadListIn;
ByteAddressBuffer deadListCount; // This is bad to use a SRV to fetch deadList count but Unity API currently prevent from copying to CB
#endif
#if VFX_USE_SPAWNER_FROM_GPU
StructuredBuffer<uint> eventList;
ByteAddressBuffer inputAdditional;
#endif
#if HAS_STRIPS
RWStructuredBuffer<uint> stripDataBuffer;
#endif
${VFXPerPassInclude}
${VFXGeneratedBlockFunction}
// Due to a bug in HLSL compiler, disable spurious "unitialized variable" due to mid function return statement
#pragma warning(push)
#pragma warning(disable : 4000)
#if HAS_STRIPS
bool GetParticleIndex(inout uint particleIndex, uint stripIndex)
{
uint relativeIndex;
InterlockedAdd(STRIP_DATA(STRIP_NEXT_INDEX, stripIndex), 1, relativeIndex);
if (relativeIndex >= PARTICLE_PER_STRIP_COUNT) // strip is full
{
InterlockedAdd(STRIP_DATA(STRIP_NEXT_INDEX, stripIndex), -1); // Remove previous increment
return false;
}
particleIndex = stripIndex * PARTICLE_PER_STRIP_COUNT + ((STRIP_DATA(STRIP_FIRST_INDEX, stripIndex) + relativeIndex) % PARTICLE_PER_STRIP_COUNT);
return true;
}
#endif
#pragma warning(pop)
[numthreads(NB_THREADS_PER_GROUP,1,1)]
void CSMain(uint3 groupId : SV_GroupID,
uint3 groupThreadId : SV_GroupThreadID)
{
uint id = groupThreadId.x + groupId.x * NB_THREADS_PER_GROUP;
#if !VFX_USE_SPAWNER_FROM_GPU
id += groupId.y * dispatchWidth * NB_THREADS_PER_GROUP;
#endif
#if VFX_USE_SPAWNER_FROM_GPU
uint maxThreadId = inputAdditional.Load((offsetInAdditionalOutput * 2 + 0) << 2);
uint currentSpawnIndex = inputAdditional.Load((offsetInAdditionalOutput * 2 + 1) << 2) - maxThreadId;
#else
uint maxThreadId = nbSpawned;
uint currentSpawnIndex = spawnIndex;
#endif
#if USE_DEAD_LIST
maxThreadId = min(maxThreadId, deadListCount.Load(0x0));
#elif VFX_USE_SPAWNER_FROM_GPU
maxThreadId = min(maxThreadId, nbMax); //otherwise, nbSpawned already clamped on CPU
#endif
if (id < maxThreadId)
{
#if VFX_USE_SPAWNER_FROM_GPU
int sourceIndex = eventList[id];
#endif
uint particleIndex = id + currentSpawnIndex;
#if !VFX_USE_SPAWNER_FROM_GPU
${VFXComputeSourceIndex}
#endif
Attributes attributes = (Attributes)0;
SourceAttributes sourceAttributes = (SourceAttributes)0;
${VFXLoadAttributes}
#if VFX_USE_PARTICLEID_CURRENT
attributes.particleId = particleIndex;
#endif
#if VFX_USE_SEED_CURRENT
attributes.seed = WangHash(particleIndex ^ systemSeed);
#endif
#if VFX_USE_SPAWNINDEX_CURRENT
attributes.spawnIndex = id;
#endif
#if HAS_STRIPS
#if !VFX_USE_SPAWNER_FROM_GPU
${VFXLoadParameter:{stripIndex}}
#else
uint stripIndex = sourceIndex;
#endif
stripIndex = min(stripIndex, STRIP_COUNT);
if (!GetParticleIndex(particleIndex, stripIndex))
return;
const StripData stripData = GetStripDataFromStripIndex(stripIndex, PARTICLE_PER_STRIP_COUNT);
InitStripAttributesWithSpawn(maxThreadId, particleIndex, attributes, stripData);
// TODO Change seed to be sure we're deterministic on random with strip
#endif
${VFXProcessBlocks}
#if VFX_USE_ALIVE_CURRENT
if (attributes.alive)
#endif
{
#if USE_DEAD_LIST
uint deadIndex = deadListIn.DecrementCounter();
uint index = deadListIn[deadIndex];
#else
uint index = particleIndex;
#endif
${VFXStoreAttributes}
}
}
}