You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

167 lines
7.6 KiB

#pragma kernel BilateralUpSampleColorHalf
#pragma kernel BilateralUpSampleColor
//#pragma enable_d3d11_debug_symbols
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
#define BILATERAL_UPSAMPLE_TILE_SIZE 8
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/BilateralUpsample.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/BilateralUpsampleDef.cs.hlsl"
// Mip chain depth buffer
TEXTURE2D_X(_DepthTexture);
// The half resolution texture that needs to be upscaled
TEXTURE2D_X(_LowResolutionTexture);
// LDS that store the half resolution data
groupshared float3 gs_cacheLighting[36];
groupshared float gs_cacheDepth[36];
float _RayMarchingLowResPercentage;
void FillUpsampleDataLDS(uint groupIndex, uint2 groupOrigin)
{
// Define which value we will be acessing with this worker thread
int acessCoordX = groupIndex % 6;
int acessCoordY = groupIndex / 6;
// Everything we are accessing is in intermediate res (half rez).
uint2 traceGroupOrigin = groupOrigin / 2;
// The initial position of the access
int2 originXY = traceGroupOrigin - int2(1, 1);
// Compute the sample position
int2 sampleCoord = int2(clamp(originXY.x + acessCoordX, 0, _HalfScreenSize.x - 1), clamp(originXY.y + acessCoordY, 0, _HalfScreenSize.y - 1));
// Sample and store into the LDS
gs_cacheLighting[groupIndex] = LOAD_TEXTURE2D_X(_LowResolutionTexture, sampleCoord).xyz;
// As an input we are not using the depth pyramid, but the full resolution depth (so we need to make sure to read from there for the upsample aswell).
gs_cacheDepth[groupIndex] = LOAD_TEXTURE2D_X(_DepthTexture, sampleCoord * 2).x;
}
uint OffsetToLDSAdress(uint2 groupThreadId, int2 offset)
{
// Compute the tap coordinate in the 6x6 grid
uint2 tapAddress = (uint2)((int2)(groupThreadId / 2 + 1) + offset);
return clamp((uint)(tapAddress.x) % 6 + tapAddress.y * 6, 0, 35);
}
// Function that fills the struct as we cannot use arrays
void FillUpsampleNeighborhoodData_2x2(int2 groupThreadId, int subRegionIdx, out NeighborhoodUpsampleData2x2_RGB neighborhoodData)
{
// Fill the sample data
int tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx].x, (int)_TapOffsets[2 * subRegionIdx].y));
neighborhoodData.lowValue0 = max(0, (gs_cacheLighting[tapIdx]));
neighborhoodData.lowDepth.x = gs_cacheDepth[tapIdx];
neighborhoodData.lowWeight.x = _DistanceBasedWeights[subRegionIdx].x;
tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx].z, (int)_TapOffsets[2 * subRegionIdx].w));
neighborhoodData.lowValue1 = max(0, (gs_cacheLighting[tapIdx]));
neighborhoodData.lowDepth.y = gs_cacheDepth[tapIdx];
neighborhoodData.lowWeight.y = _DistanceBasedWeights[subRegionIdx].y;
tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx + 1].x, (int)_TapOffsets[2 * subRegionIdx + 1].y));
neighborhoodData.lowValue2 = max(0, (gs_cacheLighting[tapIdx]));
neighborhoodData.lowDepth.z = gs_cacheDepth[tapIdx];
neighborhoodData.lowWeight.z = _DistanceBasedWeights[subRegionIdx].z;
tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx + 1].z, (int)_TapOffsets[2 * subRegionIdx + 1].w));
neighborhoodData.lowValue3 = max(0, (gs_cacheLighting[tapIdx]));
neighborhoodData.lowDepth.w = gs_cacheDepth[tapIdx];
neighborhoodData.lowWeight.w = _DistanceBasedWeights[subRegionIdx].w;
}
// The output of our upscaling pass
RW_TEXTURE2D_X(float3, _OutputUpscaledTexture);
[numthreads(BILATERAL_UPSAMPLE_TILE_SIZE, BILATERAL_UPSAMPLE_TILE_SIZE, 1)]
void BilateralUpSampleColorHalf(uint3 currentCoord : SV_DispatchThreadID,
int groupIndex : SV_GroupIndex,
uint2 groupThreadId : SV_GroupThreadID,
uint2 groupId : SV_GroupID)
{
UNITY_XR_ASSIGN_VIEW_INDEX(currentCoord.z);
// Only 36 workers of the 64 region do the pre-fetching
if (groupIndex < 36)
{
// Load 1 value per thread
FillUpsampleDataLDS(groupIndex, groupId * 8);
}
// Make sure all values are loaded in LDS by now.
GroupMemoryBarrierWithGroupSync();
// If out of bounds, discard
if (any(currentCoord.xy > uint2(_ScreenSize.xy)))
return;
// Read the depth value as early as possible and use it as late as possible
float hiResDepth = LOAD_TEXTURE2D_X(_DepthTexture, currentCoord.xy).x;
// Tap the neighborhood data from
NeighborhoodUpsampleData2x2_RGB upsampleData;
int localIndex = (currentCoord.x & 1) + (currentCoord.y & 1) * 2;
FillUpsampleNeighborhoodData_2x2(groupThreadId, localIndex, upsampleData);
// Upscale and return the result
_OutputUpscaledTexture[COORD_TEXTURE2D_X(currentCoord.xy)] = BilUpColor2x2_RGB(hiResDepth, upsampleData);
}
SAMPLER(sampler_LinearClamp);
SAMPLER(sampler_PointClamp);
[numthreads(BILATERAL_UPSAMPLE_TILE_SIZE, BILATERAL_UPSAMPLE_TILE_SIZE, 1)]
void BilateralUpSampleColor(uint3 currentCoord : SV_DispatchThreadID)
{
UNITY_XR_ASSIGN_VIEW_INDEX(currentCoord.z);
// Only 36 workers of the 64 region do the pre-fetching
// If out of bounds, discard
if (any(currentCoord.xy >= uint2(_ScreenSize.xy)))
return;
// Read the depth value as early as possible and use it as late as possible
// TODO: do a gather here.
float4 depthNeighborhood = float4(
LOAD_TEXTURE2D_X(_DepthTexture, currentCoord.xy + uint2(0,1)).x,
LOAD_TEXTURE2D_X(_DepthTexture, currentCoord.xy + uint2(1,1)).x,
LOAD_TEXTURE2D_X(_DepthTexture, currentCoord.xy + uint2(1,0)).x,
LOAD_TEXTURE2D_X(_DepthTexture, currentCoord.xy + uint2(0,0)).x);
float closestDepth = max(depthNeighborhood.x, max(depthNeighborhood.y, max(depthNeighborhood.z, depthNeighborhood.w)));
float2 uvAtLowRes = min((currentCoord.xy) * _RayMarchingLowResPercentage + 0.5, _HalfScreenSize.xy - 1) * _ScreenSize.zw;
float2 sampleUV = ClampAndScaleUVForBilinear(uvAtLowRes);
float2 samplePixel = sampleUV * _ScreenSize.xy;
float2 bottomRight = frac(samplePixel + 0.5);
float2 topLeft = 1.0 - bottomRight;
float4 linearWeights = float4(
topLeft.x * bottomRight.y,
bottomRight.x * bottomRight.y,
bottomRight.x * topLeft.y,
topLeft.x * topLeft.y);
float4 reds = GATHER_RED_TEXTURE2D_X(_LowResolutionTexture, sampler_LinearClamp, sampleUV);
float4 greens = GATHER_GREEN_TEXTURE2D_X(_LowResolutionTexture, sampler_LinearClamp, sampleUV);
float4 blues = GATHER_BLUE_TEXTURE2D_X(_LowResolutionTexture, sampler_LinearClamp, sampleUV);
float3 trueCol = SAMPLE_TEXTURE2D_X_LOD(_LowResolutionTexture, sampler_LinearClamp, sampleUV, 0.0).rgb;
float3 s0 = float3(reds.x, greens.x, blues.x);
float3 s1 = float3(reds.y, greens.y, blues.y);
float3 s2 = float3(reds.z, greens.z, blues.z);
float3 s3 = float3(reds.w, greens.w, blues.w);
float3 bilCol = BilUpColor3WithWeight(closestDepth, depthNeighborhood, s0, s1, s2, s3, linearWeights);
// Upscale and return the result
_OutputUpscaledTexture[COORD_TEXTURE2D_X(currentCoord.xy)] = bilCol;
}