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

81 lines
2.6 KiB
Plaintext

#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DepthOfFieldCommon.hlsl"
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
#pragma kernel KMain
#pragma multi_compile _ NEAR
#pragma multi_compile _ FAR
// Indirect arguments have to be in a RWBuffer
// The first three uints are near threadgroups, the last three are far threadgroups
RWBuffer<uint> _IndirectBuffer;
CBUFFER_START(cb0)
float4 _Params;
CBUFFER_END
#define Size uint2(_Params.xy)
#define TILE_SIZE 8u
#define INDIRECT_NEAR_OFFSET 0u
#define INDIRECT_FAR_OFFSET 3u
TEXTURE2D_X(_InputNearCoCTexture);
TEXTURE2D_X(_InputFarCoCTexture);
AppendStructuredBuffer<TileData> _NearTileList;
AppendStructuredBuffer<TileData> _FarTileList;
groupshared float gs_cacheNear[TILE_SIZE * TILE_SIZE];
groupshared float gs_cacheFar[TILE_SIZE * TILE_SIZE];
[numthreads(TILE_SIZE, TILE_SIZE, 1)]
void KMain(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID)
{
uint threadIdx = groupThreadId.y * TILE_SIZE + groupThreadId.x;
gs_cacheNear[threadIdx] = _InputNearCoCTexture[COORD_TEXTURE2D_X(min(dispatchThreadId, Size))].x;
gs_cacheFar[threadIdx] = _InputFarCoCTexture[COORD_TEXTURE2D_X(min(dispatchThreadId, Size))].x;
GroupMemoryBarrierWithGroupSync();
// Parallel reduction - find the max value for this tile
UNITY_UNROLL
for(uint s = (TILE_SIZE * TILE_SIZE) / 2u; s > 0u; s >>= 1u)
{
if (threadIdx < s)
{
gs_cacheNear[threadIdx] = max(gs_cacheNear[threadIdx], gs_cacheNear[threadIdx + s]);
gs_cacheFar[threadIdx] = max(gs_cacheFar[threadIdx], gs_cacheFar[threadIdx + s]);
}
GroupMemoryBarrierWithGroupSync();
}
// Evaluate on group thread 0
if (threadIdx == 0u)
{
#if NEAR
if (gs_cacheNear[threadIdx] > 0.0)
{
// Near tile detected
TileData tileData = { PackTileCoord(dispatchThreadId) };
_NearTileList.Append(tileData);
InterlockedAdd(_IndirectBuffer[INDIRECT_NEAR_OFFSET], 1);
}
#endif
#if FAR
if (gs_cacheFar[threadIdx] > 0.0)
{
// Far tile detected
TileData tileData = { PackTileCoord(dispatchThreadId) };
_FarTileList.Append(tileData);
InterlockedAdd(_IndirectBuffer[INDIRECT_FAR_OFFSET], 1);
}
#endif
}
}