Rasagar/Library/PackageCache/com.unity.visualeffectgraph/Shaders/VFXInstancing.hlsl
2024-08-26 23:07:20 +03:00

185 lines
6.2 KiB
HLSL

// Number of instances in current drawcall/dispatch
#define instancingCurrentCount asuint(instancingConstants.x)
// Number of instances that are active at the time of the drawcall/dispatch
// ContextData
// instancingCurrentCount <= instancingActiveCount
#define instancingActiveCount asuint(instancingConstants.y)
// Number of instances that this batch can hold
// instancingActiveCount <= instancingBatchSize
#define instancingBatchSize asuint(instancingConstants.z)
// Current instance offset for rendering
#define instancingCurrentOffset asuint(instancingConstants.w)
#define instancingActiveIndirectOffset instancingBufferOffsets.x
#ifndef instancingPrefixSumOffset // Already defined in VFXInit.template because it is always 0 for Init.
#define instancingPrefixSumOffset instancingBufferOffsets.y
#endif
#if VFX_INSTANCING_VARIABLE_SIZE
// Prefix sum with particle counts for each active instance
StructuredBuffer<uint> instancingPrefixSum;
#endif
#if VFX_INSTANCING_BATCH_INDIRECTION
// Indirection buffer, the first section contains the active -> batch index indirection. One entry for each active instance, holding the instance index in the batch
// The next sections contains current -> active index indirection, for each split. One entry for each instance in current drawcall/dispatch, holding the index in the active instances
StructuredBuffer<uint> instancingIndirectAndActiveIndirect;
#endif
#define DEAD_LIST_COUNT_COPY_OFFSET instancingBatchSize
#define DEAD_LIST_OFFSET (2 * instancingBatchSize)
#if defined(VFX_INSTANCING_VARIABLE_SIZE)
// Get instance index in current drawcall/dispatch, for variable size instances
uint VFXGetVariableSizeInstanceIndex(inout uint index)
{
uint startIndex = instancingCurrentOffset + instancingPrefixSumOffset;
uint endIndex = instancingCurrentCount + instancingCurrentOffset + instancingPrefixSumOffset;
return BinarySearchPrefixSum(index, instancingPrefixSum, startIndex, endIndex, index) - instancingPrefixSumOffset;
}
#elif defined(VFX_INSTANCING_FIXED_SIZE)
// Get instance index in current drawcall/dispatch, for fixed size instances
uint VFXGetFixedSizeInstanceIndex(inout uint index)
{
uint instanceIndex = index / VFX_INSTANCING_FIXED_SIZE;
instanceIndex = min(instanceIndex, instancingCurrentCount - 1);
index -= instanceIndex * VFX_INSTANCING_FIXED_SIZE;
return instanceIndex + instancingCurrentOffset;
}
#endif
// Get instance index in current drawcall/dispatch, from particle index
uint VFXGetInstanceCurrentIndex(inout uint index)
{
#if defined(VFX_INSTANCING_VARIABLE_SIZE)
return VFXGetVariableSizeInstanceIndex(index);
#elif defined(VFX_INSTANCING_FIXED_SIZE)
return VFXGetFixedSizeInstanceIndex(index);
#else
return 0;
#endif
}
// Get instance index in the active instances, from instance index in current drawcall/dispatch
uint VFXGetInstanceActiveIndex(uint instanceCurrentIndex)
{
uint instanceActiveIndex = instanceCurrentIndex;
#if VFX_INSTANCING_ACTIVE_INDIRECTION
if (instancingCurrentCount < instancingActiveCount)
{
instanceActiveIndex = instancingIndirectAndActiveIndirect[instancingActiveIndirectOffset + instanceActiveIndex];
}
#endif
return instanceActiveIndex;
}
// Get instance index in the batch, from instance index in the active instances
uint VFXGetInstanceBatchIndex(uint instanceActiveIndex)
{
uint instanceBatchIndex = instanceActiveIndex;
#if VFX_INSTANCING_BATCH_INDIRECTION
if (instancingActiveCount < instancingBatchSize)
{
instanceBatchIndex = instancingIndirectAndActiveIndirect[instanceBatchIndex];
}
#endif
return instanceBatchIndex;
}
uint VFXInitInstancing(uint index, out uint instanceIndex, out uint instanceActiveIndex, out uint instanceCurrentIndex)
{
instanceIndex = instanceActiveIndex = instanceCurrentIndex = 0;
#if VFX_USE_INSTANCING
#if SHADER_STAGE_COMPUTE // In compute shaders
instanceCurrentIndex = VFXGetInstanceCurrentIndex(index);
instanceActiveIndex = VFXGetInstanceActiveIndex(instanceCurrentIndex);
instanceIndex = VFXGetInstanceBatchIndex(instanceActiveIndex);
#else // In VS shaders
#ifdef UNITY_INSTANCING_ENABLED
{
instanceCurrentIndex = VFXGetInstanceCurrentIndex(index);
unity_InstanceID = instanceCurrentIndex;
}
#endif
instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex));
instanceIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceIndex));
#endif
#endif
return index;
}
#if VFX_HAS_INDIRECT_DRAW
uint VFXGetIndirectBufferIndex(uint index, uint instanceActiveIndex)
{
return RAW_CAPACITY * instanceActiveIndex + instancingBatchSize + index;
}
#endif
#define VFX_GPU_EVENT_SUPPORT_INSTANCING 0
uint VFXGetEventListBufferIndex(uint index, uint instanceActiveIndex)
{
#if VFX_GPU_EVENT_SUPPORT_INSTANCING
return RAW_CAPACITY * instanceActiveIndex + instancingBatchSize * 2u + index;
#else
return 2u + index;
#endif
}
uint VFXGetEventListBufferElementCount(uint instanceActiveIndex)
{
#if VFX_GPU_EVENT_SUPPORT_INSTANCING
return instancingBatchSize * 0u + instanceActiveIndex;
#else
return 0u;
#endif
}
uint VFXGetEventListBufferAccumulatedCount(uint instanceActiveIndex)
{
#if VFX_GPU_EVENT_SUPPORT_INSTANCING
return instancingBatchSize * 1u + instanceActiveIndex;
#else
return 1u;
#endif
}
void AppendEventTotalCount(RWStructuredBuffer<uint> outputBuffer, uint totalCount, uint instanceActiveIndex)
{
uint localInstancingBatchSize = instancingBatchSize;
#if !VFX_GPU_EVENT_SUPPORT_INSTANCING
instanceActiveIndex = 0u;
localInstancingBatchSize = 1u;
#endif
InterlockedAdd(outputBuffer[localInstancingBatchSize + instanceActiveIndex], totalCount);
}
void AppendEventBuffer(RWStructuredBuffer<uint> outputBuffer, uint sourceIndex, uint outputCapacity, uint instanceActiveIndex)
{
uint eventIndex;
uint localInstancingBatchSize = instancingBatchSize;
#if !VFX_GPU_EVENT_SUPPORT_INSTANCING
instanceActiveIndex = 0u;
localInstancingBatchSize = 1u;
#endif
InterlockedAdd(outputBuffer[instanceActiveIndex], 1u, eventIndex);
[branch]
if (eventIndex < outputCapacity)
{
eventIndex += localInstancingBatchSize * 2u + instanceActiveIndex * outputCapacity;
outputBuffer[eventIndex] = sourceIndex;
}
}