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

71 lines
3.5 KiB
Plaintext

#pragma kernel ProbeVolumeAtlasOctahedralDepthBlitKernel PROBE_VOLUME_ATLAS_OCTAHEDRAL_DEPTH_BLIT_KERNEL=ProbeVolumeAtlasOctahedralDepthBlitKernel
#ifdef SHADER_API_PSSL
# pragma argument( scheduler=minpressure ) // instruct the shader compiler to prefer minimizing vgpr usage
#endif
#pragma only_renderers d3d11 playstation xboxone vulkan metal switch
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/ProbeVolumeLighting.cs.hlsl"
StructuredBuffer<float> _ProbeVolumeAtlasOctahedralDepthReadBuffer;
RWTexture2D<float2> _ProbeVolumeAtlasOctahedralDepthWriteTexture;
uint _ProbeVolumeAtlasOctahedralDepthReadBufferCount;
float3 _ProbeVolumeResolution;
float3 _ProbeVolumeResolutionInverse;
float4 _ProbeVolumeAtlasOctahedralDepthScaleBias;
float4 _ProbeVolumeAtlasOctahedralDepthResolutionAndInverse;
uint2 ComputeWriteIndexFromReadIndex(uint readIndex, float3 resolution, float3 resolutionInverse, float4 scaleBias, float4 atlasResolutionAndInverse)
{
// return uint2(readIndex % 1024u, readIndex >> 10);
// _ProbeVolumeAtlasOctahedralDepthReadBuffer[z * resolutionY * resolutionX + y * resolutionX + x]
// TODO: Could implement as floating point operations, which is likely faster.
// Would need to verify precision.
uint x = readIndex % (uint)resolution.x;
uint y = (readIndex / (uint)resolution.x) % (uint)resolution.y;
uint z = readIndex / ((uint)resolution.y * (uint)resolution.x);
// Atlas layout:
// int width = resolution.x * resolution.z;
// int height = resolution.y;
// scaleBias: x,y is width and height (scale) z,w offset into atlas (bias)
// Handle Z "vertical" flip, as in source, index z == 0 is "top" and index z == resolution.z - 1 is "bottom"
// but in destination atlas, z coordinate min is "bottom", and z coordinate max is "top".
uint atlasX = x + (resolution.z - 1 - z) * (uint)resolution.x;
uint atlasY = y;
float atlasU = (float)atlasX + scaleBias.z * atlasResolutionAndInverse.x;
float atlasV = (float)atlasY + scaleBias.w * atlasResolutionAndInverse.y;
return uint2((uint)atlasU, (uint)atlasV);
}
// Warning this needs to match with kBatchSize in ProbeVolumeLighting.cs
#define BATCH_SIZE 256
[numthreads(BATCH_SIZE, 1, 1)]
void PROBE_VOLUME_ATLAS_OCTAHEDRAL_DEPTH_BLIT_KERNEL(uint groupThreadId : SV_GroupThreadID, uint groupId : SV_GroupID, uint3 dispatchThreadId : SV_DispatchThreadID)
{
uint readIndex = groupId * BATCH_SIZE + groupThreadId;
if (readIndex >= _ProbeVolumeAtlasOctahedralDepthReadBufferCount) { return; }
uint readIndexProbe = readIndex / (8 * 8);
uint readIndexOctahedral = readIndex - (readIndexProbe * (8 * 8));
uint2 writeIndexProbe = ComputeWriteIndexFromReadIndex(
readIndexProbe,
_ProbeVolumeResolution,
_ProbeVolumeResolutionInverse,
_ProbeVolumeAtlasOctahedralDepthScaleBias,
_ProbeVolumeAtlasOctahedralDepthResolutionAndInverse * (1.0f / 8.0f) // TODO: Cleanup: since we are computing the probe, rather than the pixel we are in, we need to divide scale bias by octahedral map resolution.
);
uint2 writeIndexOctahedral = uint2(readIndexOctahedral % 8, readIndexOctahedral / 8);
uint2 writeIndex = writeIndexProbe * 8 + writeIndexOctahedral;
// Depth sample is placed in X component, in order to be filtered into a mean, variance distribution and stored into XY in a following pass.
_ProbeVolumeAtlasOctahedralDepthWriteTexture[uint2(writeIndex.x, writeIndex.y)] = float2(_ProbeVolumeAtlasOctahedralDepthReadBuffer[readIndex], 0.0f);
}