#pragma kernel CSMain ${VFXPragmaOnlyRenderers} ${VFXPragmaRequire} ${VFXGlobalInclude} ${VFXGlobalDeclaration} #define IndirectOutputType uint ${VFXInclude("Shaders/VFXParticleCommon.template")} #ifdef VFX_IS_RAYTRACED #pragma multi_compile _ VFX_COMPUTE_AABBS #endif #define USE_DEAD_LIST (VFX_USE_ALIVE_CURRENT && !HAS_STRIPS) RWByteAddressBuffer attributeBuffer; #if USE_DEAD_LIST RWStructuredBuffer deadList; #endif #if VFX_HAS_INDIRECT_DRAW RWStructuredBuffer indirectBuffer; #endif #if HAS_STRIPS_DATA RWStructuredBuffer stripDataBuffer; #endif #if VFX_USE_STRIPALIVE_CURRENT StructuredBuffer attachedStripDataBuffer; #endif CBUFFER_START(updateParamsConst) uint dispatchWidth; ${VFXInstancingConstants} float3 cameraXRSettings; CBUFFER_END ${VFXPerPassInclude} #if VFX_HAS_INDIRECT_DRAW ${VFXDeclareAppendOutputIndirectBuffer} #endif ${VFXGeneratedBlockFunction} [numthreads(NB_THREADS_PER_GROUP,1,1)] void CSMain(uint3 groupId : SV_GroupID, uint3 groupThreadId : SV_GroupThreadID) { uint id = GetThreadId(groupId, groupThreadId, dispatchWidth); ${VFXInitInstancingCompute} ${VFXLoadContextData} uint systemSeed = contextData.systemSeed; uint nbMax = contextData.maxParticleCount; #if VFX_COMPUTE_BOUNDS uint tid = groupThreadId.x; #endif if (index < nbMax) { #if HAS_STRIPS if (index == 0) { STRIP_PARTICLE_COUNTER(instanceIndex) = 0; } #endif ${VFXLoadGraphValues} VFXAttributes attributes = (VFXAttributes)0; VFXSourceAttributes sourceAttributes = (VFXSourceAttributes)0; #if VFX_USE_ALIVE_CURRENT ${VFXLoadAttributes} if (attributes.alive) { #if VFX_USE_OLDVELOCITY_CURRENT && VFX_USE_VELOCITY_CURRENT attributes.oldVelocity = attributes.velocity; #endif #if HAS_STRIPS const StripData stripData = GetStripDataFromParticleIndex(index, instanceIndex); InitStripAttributes(index, attributes, stripData); #endif #if VFX_UPDATE_SKIP_ZERO_DELTA_TIME ${VFXLoadParameter:{deltaTime}} if (deltaTime != 0.0f) #endif { ${VFXProcessBlocks} } ${VFXStoreAttributes:{(?!(alive))(\b\w)}} if (attributes.alive) { #if VFX_HAS_INDIRECT_DRAW AppendOutputBuffer(indirectBuffer, index, instanceActiveIndex); #endif #if HAS_STRIPS uint bufferIndex = STRIP_DATA_INDEX(instanceIndex, stripData.stripIndex); uint relativeIndexInStrip = GetRelativeIndex(index, stripData); InterlockedMin(STRIP_DATA(STRIP_MIN_ALIVE, bufferIndex), relativeIndexInStrip); InterlockedMax(STRIP_DATA(STRIP_MAX_ALIVE, bufferIndex), relativeIndexInStrip); #endif } else { ${VFXStoreAttributes:{alive}} #if USE_DEAD_LIST && !VFX_USE_STRIPALIVE_CURRENT uint deadIndex; InterlockedAdd(deadList[instanceIndex], 1, deadIndex); deadIndex += DEAD_LIST_OFFSET + instanceIndex * RAW_CAPACITY; deadList[deadIndex] = index; #endif } } #if USE_DEAD_LIST && VFX_USE_STRIPALIVE_CURRENT else if (attributes.stripAlive) { uint bufferIndex = ((instanceIndex * ATTACHED_STRIP_COUNT) + index); if (index >= ATTACHED_STRIP_COUNT || STRIP_DATA_X(attachedStripDataBuffer, STRIP_MIN_ALIVE, bufferIndex) == ~1) // Attached strip is no longer alive, recycle the particle { uint deadIndex; InterlockedAdd(deadList[instanceIndex], 1, deadIndex); deadIndex += DEAD_LIST_OFFSET + instanceIndex * RAW_CAPACITY; deadList[deadIndex] = index; attributes.stripAlive = false; ${VFXStoreAttributes:{stripAlive}} } } #endif // For strips, we still need to render some dead particles if they are in the middle of the strip #if HAS_STRIPS && VFX_HAS_INDIRECT_DRAW if (!attributes.alive) { const StripData stripData = GetStripDataFromParticleIndex(index, instanceIndex); uint relativeIndexInStrip = GetRelativeIndex(index, stripData); if (relativeIndexInStrip > 0 && relativeIndexInStrip + 1 < stripData.nextIndex) { AppendOutputBuffer(indirectBuffer, index, instanceActiveIndex); } } #endif #else ${VFXLoadAttributes} #if VFX_USE_OLDVELOCITY_CURRENT && VFX_USE_VELOCITY_CURRENT attributes.oldVelocity = attributes.velocity; #endif #if VFX_USE_CONTINUOUSCOLLISIONCOUNT_CURRENT //attributes.continuousCollisionCount = 0; #endif #if HAS_STRIPS const StripData stripData = GetStripDataFromParticleIndex(index, instanceIndex); InitStripAttributes(index, attributes, stripData); #endif #if VFX_UPDATE_SKIP_ZERO_DELTA_TIME ${VFXLoadParameter:{deltaTime}} if (deltaTime != 0.0f) #endif { ${VFXProcessBlocks} } ${VFXStoreAttributes} #if VFX_HAS_INDIRECT_DRAW AppendOutputBuffer(indirectBuffer, index, instanceActiveIndex); #endif #endif #if VFX_COMPUTE_BOUNDS || VFX_COMPUTE_AABBS { #if VFX_COMPUTE_BOUNDS ${VFXLoadSize} #if VFX_WORLD_SPACE ${VFXLoadParameter:{worldToLocal}} #else float4x4 worldToLocal = (float4x4)0; #endif InitReduction(attributes, size3, tid, worldToLocal); #endif } #if VFX_COMPUTE_AABBS ${VFXLoadSizeRT} int rayTracingDecimationFactor = VFX_RT_DECIMATION_FACTOR; FillAabbBuffer(attributes, size3, index, instanceIndex, rayTracingDecimationFactor); #endif #endif } #if VFX_COMPUTE_BOUNDS PerformBoundsReduction(index, tid, instanceIndex, nbMax); #endif }