#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 _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 _NearTileList; AppendStructuredBuffer _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 } }