#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal glcore ps5
#pragma kernel Scroll
#include "VectorLogic.hlsl"
#include "Common.hlsl"
#include "PatchUtil.hlsl"
RWStructuredBuffer<uint> _CellAllocationMarks;
RWStructuredBuffer<uint> _CellPatchIndices;
RWStructuredBuffer<uint> _PatchCellIndices;
StructuredBuffer<int3> _NewCascadeOffsets;
int4 _OldCascadeOffsets[cascadeMax];
uint _GridSize;
uint _CascadeCount;
[numthreads(8, 8, 8)]
void Scroll(uint3 threadId : SV_DispatchThreadID)
{
if (any(uint3(_GridSize, _GridSize, _GridSize * _CascadeCount) <= threadId))
return;
const uint3 positionStorageSpace = threadId % _GridSize;
const uint cascadeIdx = threadId.z / _GridSize;
const int3 newCascadeOffset = _NewCascadeOffsets[cascadeIdx];
const int3 oldCascadeOffset = _OldCascadeOffsets[cascadeIdx].xyz;
const int3 positionStorageSpaceInt = int3(positionStorageSpace);
const int3 oldPositionGridSpace = PatchUtil::ConvertStorageSpaceToGridSpace(positionStorageSpaceInt, _GridSize, oldCascadeOffset);
const int3 offsetDelta = newCascadeOffset - oldCascadeOffset;
const int3 offsettedOldPositionGridSpace = oldPositionGridSpace - offsetDelta;
// If the old position (in grid space) is outside [0, GridSize]^3 after the scroll (offsetDelta) has been applied, we know
// it will no longer be queried, so we can remove it.
if (any(VECTOR_LOGIC_OR(offsettedOldPositionGridSpace < 0, (int)_GridSize <= offsettedOldPositionGridSpace)))
{
for (uint directionIdx = 0; directionIdx < PatchUtil::gridCellAngularResolution * PatchUtil::gridCellAngularResolution; ++directionIdx)
{
const uint cellIdx = PatchUtil::GetCellIndex(cascadeIdx, positionStorageSpace, directionIdx, _GridSize, PatchUtil::gridCellAngularResolution);
const uint patchIdx = _CellPatchIndices[cellIdx];
if (patchIdx != PatchUtil::invalidCellIndex)
{
_CellAllocationMarks[cellIdx] = 0;
_PatchCellIndices[patchIdx] = PatchUtil::invalidCellIndex;
_CellPatchIndices[cellIdx] = PatchUtil::invalidPatchIndex;
}
}
}
}