WuhuIslandTesting/Library/PackageCache/com.unity.render-pipelines.universal@8148.0.7-4/Shaders/Utils/DepthPyramid.compute
2025-01-07 02:06:59 +01:00

262 lines
9 KiB
Text

#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel MipMin KERNEL_SIZE=8
#pragma kernel MipMin2 KERNEL_SIZE=8
#pragma kernel MipMinOdd KERNEL_SIZE=8
#pragma multi_compile _ STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile_local _ SRV_SOURCE
#pragma multi_compile_local _ MIN_AND_MAX
#if defined(STEREO_INSTANCING_ON)
#define UNITY_STEREO_INSTANCING_ENABLED
#endif
#if defined(STEREO_MULTIVIEW_ON)
#define UNITY_STEREO_MULTIVIEW_ENABLED
#endif
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
#if defined(MIN_AND_MAX)
#define float1or2 float2
#else
#define float1or2 float
#endif
#if defined(SRV_SOURCE)
TEXTURE2D_X_FLOAT(_MipSource);
#else
RW_TEXTURE2D_X(float1or2, _MipSource);
#endif
RW_TEXTURE2D_X(float1or2, _MipDest);
RW_TEXTURE2D_X(float1or2, _MipDest2);
#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON)
#define COORD_DEPTH(uv) (uv).xyz
#else
#define COORD_DEPTH(uv) (uv).xy
#endif
#if defined(SRV_SOURCE)
#if UNITY_REVERSED_Z
#if defined(MIN_AND_MAX)
#define XR_MESH_CORRECTION(d) float2(d.x == 1 ? 0 : d.x, d.y == 1 ? 1 : d.y)
#else
#define XR_MESH_CORRECTION(d) (d.x == 1 ? 0 : d.x)
#endif
#else
#if defined(MIN_AND_MAX)
#define XR_MESH_CORRECTION(d) float2(d.x == 0 ? 1 : d.x, d.y == 0 ? 0 : d.y)
#else
#define XR_MESH_CORRECTION(d) (d.x == 0 ? 1 : d.x)
#endif
#endif
#else
#define XR_MESH_CORRECTION(d) d
#endif
#if !defined(MIN_AND_MAX)
#if defined(SRV_SOURCE)
#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON)
#define MIPSOURCE(uv) XR_MESH_CORRECTION((_MipSource.Load(int4(uv.xyz, 0)).r))
#else
#define MIPSOURCE(uv) _MipSource.Load(int3(uv.xy, 0)).r
#endif
#else
#define MIPSOURCE(uv) _MipSource[uv].r
#endif
#else
#if defined(SRV_SOURCE)
#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON)
#define MIPSOURCE(uv) XR_MESH_CORRECTION((_MipSource.Load(int4(uv.xyz, 0)).rr))
#else
#define MIPSOURCE(uv) _MipSource.Load(int3(uv.xy, 0)).rr
#endif
#else
#define MIPSOURCE(uv) _MipSource[uv].rg
#endif
#endif
//CBUFFER_START(cb)
int4 data1; //current mip width, current mip height, lower mip width, lower mip height
int4 data2; // number of mips to process at once, is U odd, is V odd, are both odd
//CBUFFER_END
groupshared uint minLevel1[4][4];
//groupshared uint maxLevel1[4][4];
#if UNITY_REVERSED_Z
// #define MIN_DEPTH 1
#define MIN_DEPTH(l, r) max(l, r)
#define MAX_DEPTH(l, r) min(l, r)
#define INIT_DEPTH 0xFFFF0000u
#define INTERLOCKED_MIN(a, b) InterlockedMax(a, b)
#define INTERLOCKED_MAX(a, b) InterlockedMin(a, b)
#else
// #define MIN_DEPTH 0
#define MIN_DEPTH(l, r) min(l, r)
#define MAX_DEPTH(l, r) max(l, r)
#define INIT_DEPTH 0x0000FFFFu
#define INTERLOCKED_MIN(a, b) InterlockedMin(a, b)
#define INTERLOCKED_MAX(a, b) InterlockedMax(a, b)
#endif
[numthreads(KERNEL_SIZE, KERNEL_SIZE,1)]
void MipMin(uint3 id : SV_DispatchThreadID)
{
//if (id.x < data1.x && id.y < data1.y)
//{
uint2 srcPixelUV = id.xy << 1;
uint3 uv00 = uint3(min(srcPixelUV + uint2(0u, 0u), data1.zw), id.z);
float1or2 p00 = MIPSOURCE(COORD_DEPTH(uv00));
uint3 uv10 = uint3(min(srcPixelUV + uint2(1u, 0u), data1.zw), id.z);
float1or2 p10 = MIPSOURCE(COORD_DEPTH(uv10));
uint3 uv01 = uint3(min(srcPixelUV + uint2(0u, 1u), data1.zw), id.z);
float1or2 p01 = MIPSOURCE(COORD_DEPTH(uv01));
uint3 uv11 = uint3(min(srcPixelUV + uint2(1u, 1u), data1.zw), id.z);
float1or2 p11 = MIPSOURCE(COORD_DEPTH(uv11));
float min4 = MIN_DEPTH(MIN_DEPTH(p00.r, p01.r), MIN_DEPTH(p10.r, p11.r));
#if defined(MIN_AND_MAX)
float max4 = MAX_DEPTH(MAX_DEPTH(p00.g, p01.g), MAX_DEPTH(p10.g, p11.g));
#else
float max4 = 0.0;
#endif
_MipDest[COORD_DEPTH(id)] = (float1or2)float4(min4,max4,0,0);
}
[numthreads(KERNEL_SIZE, KERNEL_SIZE, 1)]
void MipMin2(uint3 id : SV_DispatchThreadID, uint3 groupID : SV_GroupThreadID, uint groupIndex : SV_GroupIndex)
{
//uint2 id2D = id.xy + uint2((groupID.z & 1u) ? 4u : 0u, groupID.z > 1 ? 4u : 0u);
if (groupID.x < 4 && groupID.y < 4)
{
minLevel1[groupID.x][groupID.y] = INIT_DEPTH;
//maxLevel1[groupID.x][groupID.y] = INIT_DEPTH;
}
GroupMemoryBarrierWithGroupSync();
//if (id.x < data1.x && id.y < data1.y)
//{
uint2 srcPixelUV = id.xy << 1;
uint3 uv00 = uint3(min(srcPixelUV + uint2(0u, 0u), data1.zw), id.z);
float1or2 p00 = MIPSOURCE(COORD_DEPTH(uv00));
uint3 uv10 = uint3(min(srcPixelUV + uint2(1u, 0u), data1.zw), id.z);
float1or2 p10 = MIPSOURCE(COORD_DEPTH(uv10));
uint3 uv01 = uint3(min(srcPixelUV + uint2(0u, 1u), data1.zw), id.z);
float1or2 p01 = MIPSOURCE(COORD_DEPTH(uv01));
uint3 uv11 = uint3(min(srcPixelUV + uint2(1u, 1u), data1.zw), id.z);
float1or2 p11 = MIPSOURCE(COORD_DEPTH(uv11));
float minLevel0 = MIN_DEPTH(MIN_DEPTH(p00.r, p01.r), MIN_DEPTH(p10.r, p11.r));
#if defined(MIN_AND_MAX)
float maxLevel0 = MAX_DEPTH(MAX_DEPTH(p00.g, p01.g), MAX_DEPTH(p10.g, p11.g));
#else
float maxLevel0 = 0.0;
#endif
_MipDest[COORD_DEPTH(id)] = (float1or2)float4(minLevel0, maxLevel0, 0, 0);
uint2 miniGroupId = uint2(0u,0u);
[branch] if (data2.x > 1)
{
miniGroupId = groupID.xy >> 1;
uint minLevel0U = f32tof16(minLevel0) | (minLevel1[miniGroupId.x][miniGroupId.y] & 0xFFFF0000u);
INTERLOCKED_MIN(minLevel1[miniGroupId.x][miniGroupId.y], minLevel0U);
}
GroupMemoryBarrierWithGroupSync();
#if defined(MIN_AND_MAX)
[branch] if (data2.x > 1)
{
uint maxLevel0U = (f32tof16(maxLevel0) << 16) | (minLevel1[miniGroupId.x][miniGroupId.y] & 0x0000FFFFu);
INTERLOCKED_MAX(minLevel1[miniGroupId.x][miniGroupId.y], maxLevel0U);
}
GroupMemoryBarrierWithGroupSync();
#endif
[branch] if (data2.x > 1)
{
uint3 uv2 = uint3(id.xy >> 1u, id.z);
[branch] if (((groupID.x & 1u) == 0u) && ((groupID.y & 1u) == 0u))
{
float r0 = f16tof32(minLevel1[miniGroupId.x][miniGroupId.y] & 0x0000FFFFu);
#if defined(MIN_AND_MAX)
float r1 = f16tof32(minLevel1[miniGroupId.x][miniGroupId.y] >> 16u);
#else
float r1 = 0;
#endif
_MipDest2[COORD_DEPTH(uv2)] = (float1or2)float4(r0,r1,0,0);
}
}
}
[numthreads(KERNEL_SIZE, KERNEL_SIZE, 1)]
void MipMinOdd(uint3 id : SV_DispatchThreadID)
{
//if (id.x < data1.x && id.y < data1.y)
uint2 srcPixelUV = id.xy << 1;
uint3 uv00 = uint3(min(srcPixelUV + uint2(0u, 0u), data1.zw), id.z);
float1or2 p00 = MIPSOURCE(COORD_DEPTH(uv00));
uint3 uv10 = uint3(min(srcPixelUV + uint2(1u, 0u), data1.zw), id.z);
float1or2 p10 = MIPSOURCE(COORD_DEPTH(uv10));
uint3 uv01 = uint3(min(srcPixelUV + uint2(0u, 1u), data1.zw), id.z);
float1or2 p01 = MIPSOURCE(COORD_DEPTH(uv01));
uint3 uv11 = uint3(min(srcPixelUV + uint2(1u, 1u), data1.zw), id.z);
float1or2 p11 = MIPSOURCE(COORD_DEPTH(uv11));
float minLevel0 = MIN_DEPTH(MIN_DEPTH(p00.r, p01.r), MIN_DEPTH(p10.r, p11.r));
#if defined(MIN_AND_MAX)
float maxLevel0 = MAX_DEPTH(MAX_DEPTH(p00.g, p01.g), MAX_DEPTH(p10.g, p11.g));
#else
float maxLevel0 = 0.0f;
#endif
if (data2.y == 1)
{
uint3 uv20 = uint3(min(srcPixelUV + uint2(2u, 0u), data1.zw), id.z);
float2 p20 = MIPSOURCE(COORD_DEPTH(uv20));
uint3 uv21 = uint3(min(srcPixelUV + uint2(2u, 1u), data1.zw), id.z);
float2 p21 = MIPSOURCE(COORD_DEPTH(uv21));
minLevel0 = MIN_DEPTH(MIN_DEPTH(p20.r, p21.r), minLevel0);
#if defined(MIN_AND_MAX)
maxLevel0 = MAX_DEPTH(MAX_DEPTH(p20.g, p21.g), maxLevel0);
#endif
}
if (data2.z == 1)
{
uint3 uv02 = uint3(min(srcPixelUV + uint2(0u, 2u), data1.zw), id.z);
float2 p02 = MIPSOURCE(COORD_DEPTH(uv02));
uint3 uv12 = uint3(min(srcPixelUV + uint2(1u, 2u), data1.zw), id.z);
float2 p12 = MIPSOURCE(COORD_DEPTH(uv12));
minLevel0 = MIN_DEPTH(MIN_DEPTH(p02.r, p12.r), minLevel0);
#if defined(MIN_AND_MAX)
maxLevel0 = MAX_DEPTH(MAX_DEPTH(p02.g, p12.g), maxLevel0);
#endif
}
if (data2.z == 1 && data2.y == 1)
{
uint3 uv22 = uint3(min(srcPixelUV + uint2(2u, 2u), data1.zw), id.z);
float2 p22 = MIPSOURCE(COORD_DEPTH(uv22));
minLevel0 = MIN_DEPTH(p22.r, minLevel0);
#if defined(MIN_AND_MAX)
maxLevel0 = MAX_DEPTH(p22.g, maxLevel0);
#endif
}
_MipDest[COORD_DEPTH(id)] = (float1or2)float4(minLevel0, maxLevel0, 0,0);
//}
}