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

60 lines
2.3 KiB
HLSL

#ifndef UNITY_FULLSCREEN_DEBUG_INCLUDED
#define UNITY_FULLSCREEN_DEBUG_INCLUDED
// For quad overdraw, we need two halfscreen UAV (because a quad is 2x2 pixels). For vertex density, we need one fullscreen UAV.
// These modes are exclusive so we make only one fullscreen allocation for both.
// For vertex density, it stores the number of vertex projected in each pixel.
// For quad overdraw, each 2x2 quad of the UAV contains the overdraw count in top-left pixel and the locked quad id in the top-right pixel. The two other pixels of the quad are unused.
// Because metal doesn't support atomics on textures, this is actually a buffer
RWStructuredBuffer<uint> _FullScreenDebugBuffer : register(u1);
void IncrementVertexDensityCounter(float4 positionCS)
{
positionCS.xyz /= positionCS.w;
float3 ndc = float3(positionCS.xy * float2(0.5, (_ProjectionParams.x > 0) ? 0.5 : -0.5) + 0.5, positionCS.z);
// If vertex is in viewport
if (all(ndc == saturate(ndc)))
{
uint2 pixel = (uint2)(ndc.xy * _ScreenSize.xy);
InterlockedAdd(_FullScreenDebugBuffer[_ScreenSize.x * (_ScreenSize.y * SLICE_ARRAY_INDEX + pixel.y) + pixel.x], 1);
}
}
// https://blog.selfshadow.com/2012/11/12/counting-quads/
void IncrementQuadOverdrawCounter(uint2 positionSS, uint primitiveID)
{
#if defined(PLATFORM_SUPPORTS_BUFFER_ATOMICS_IN_PIXEL_SHADER)
uint prevID, thisID = primitiveID + 1;
uint2 quad = positionSS & ~1;
uint quad0_idx = _ScreenSize.x * (_ScreenSize.y * SLICE_ARRAY_INDEX + quad.y) + quad.x;
uint quad1_idx = _ScreenSize.x * (_ScreenSize.y * SLICE_ARRAY_INDEX + quad.y) + quad.x + 1;
bool processed = false;
int lockCount = 0;
for (int i = 0; i < 16; i++)
{
if (!processed)
InterlockedCompareExchange(_FullScreenDebugBuffer[quad1_idx], 0, thisID, prevID);
[branch]
if (prevID == 0)
{
// Wait a bit, then unlock for other quads
if (++lockCount == 2)
InterlockedExchange(_FullScreenDebugBuffer[quad1_idx], 0, prevID);
processed = true;
}
if (prevID == thisID)
processed = true;
}
if (lockCount)
InterlockedAdd(_FullScreenDebugBuffer[quad0_idx], 1);
#endif
}
#endif // UNITY_FULLSCREEN_DEBUG_INCLUDED