|
1 | | -#pragma kernel BilateralUpSampleSingle BILATERAL_UPSAMPLE=BilateralUpSampleSingle SINGLE_CHANNEL |
2 | 1 | #pragma kernel BilateralUpSampleColor BILATERAL_UPSAMPLE=BilateralUpSampleColor |
3 | 2 |
|
4 | 3 | //#pragma enable_d3d11_debug_symbols |
|
10 | 9 | #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" |
11 | 10 | #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" |
12 | 11 | #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/BilateralUpsample.hlsl" |
| 12 | +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/BilateralUpsampleDef.cs.hlsl" |
13 | 13 |
|
14 | 14 | // Mip chain depth buffer |
15 | 15 | TEXTURE2D_X(_DepthTexture); |
16 | 16 | // The half resolution texture that needs to be upscaled |
17 | 17 | TEXTURE2D_X(_LowResolutionTexture); |
18 | 18 |
|
19 | | -// Constant buffer where all variables should land |
20 | | -CBUFFER_START(UnityScreenSpaceGlobalIllumination) |
21 | | - float4 _HalfScreenSize; |
22 | | - float2 _DepthPyramidFirstMipLevelOffset; |
23 | | -CBUFFER_END |
| 19 | +// LDS that store the half resolution data |
| 20 | +groupshared float3 gs_cacheLighting[36]; |
| 21 | +groupshared float gs_cacheDepth[36]; |
| 22 | + |
| 23 | +void FillUpsampleDataLDS(uint groupIndex, uint2 groupOrigin) |
| 24 | +{ |
| 25 | + // Define which value we will be acessing with this worker thread |
| 26 | + int acessCoordX = groupIndex % 6; |
| 27 | + int acessCoordY = groupIndex / 6; |
| 28 | + |
| 29 | + // Everything we are accessing is in intermediate res (half rez). |
| 30 | + uint2 traceGroupOrigin = groupOrigin / 2; |
| 31 | + |
| 32 | + // The initial position of the access |
| 33 | + int2 originXY = traceGroupOrigin - int2(1, 1); |
| 34 | + |
| 35 | + // Compute the sample position |
| 36 | + int2 sampleCoord = int2(clamp(originXY.x + acessCoordX, 0, _HalfScreenSize.x - 1), clamp(originXY.y + acessCoordY, 0, _HalfScreenSize.y - 1)); |
| 37 | + |
| 38 | + // Sample and store into the LDS |
| 39 | + gs_cacheLighting[groupIndex] = LOAD_TEXTURE2D_X(_LowResolutionTexture, sampleCoord).xyz; |
| 40 | + // 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). |
| 41 | + gs_cacheDepth[groupIndex] = LOAD_TEXTURE2D_X(_DepthTexture, sampleCoord * 2).x; |
| 42 | +} |
| 43 | + |
| 44 | +uint OffsetToLDSAdress(uint2 groupThreadId, int2 offset) |
| 45 | +{ |
| 46 | + // Compute the tap coordinate in the 6x6 grid |
| 47 | + uint2 tapAddress = (uint2)((int2)(groupThreadId / 2 + 1) + offset); |
| 48 | + return clamp((uint)(tapAddress.x) % 6 + tapAddress.y * 6, 0, 35); |
| 49 | +} |
| 50 | + |
| 51 | +// Function that fills the struct as we cannot use arrays |
| 52 | +void FillUpsampleNeighborhoodData_2x2(int2 groupThreadId, int subRegionIdx, out NeighborhoodUpsampleData2x2_RGB neighborhoodData) |
| 53 | +{ |
| 54 | + // Fill the sample data |
| 55 | + int tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx].x, (int)_TapOffsets[2 * subRegionIdx].y)); |
| 56 | + neighborhoodData.lowValue0 = max(0, (gs_cacheLighting[tapIdx])); |
| 57 | + neighborhoodData.lowDepth.x = gs_cacheDepth[tapIdx]; |
| 58 | + neighborhoodData.lowWeight.x = _DistanceBasedWeights[subRegionIdx].x; |
| 59 | + |
| 60 | + tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx].z, (int)_TapOffsets[2 * subRegionIdx].w)); |
| 61 | + neighborhoodData.lowValue1 = max(0, (gs_cacheLighting[tapIdx])); |
| 62 | + neighborhoodData.lowDepth.y = gs_cacheDepth[tapIdx]; |
| 63 | + neighborhoodData.lowWeight.y = _DistanceBasedWeights[subRegionIdx].y; |
| 64 | + |
| 65 | + tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx + 1].x, (int)_TapOffsets[2 * subRegionIdx + 1].y)); |
| 66 | + neighborhoodData.lowValue2 = max(0, (gs_cacheLighting[tapIdx])); |
| 67 | + neighborhoodData.lowDepth.z = gs_cacheDepth[tapIdx]; |
| 68 | + neighborhoodData.lowWeight.z = _DistanceBasedWeights[subRegionIdx].z; |
| 69 | + |
| 70 | + tapIdx = OffsetToLDSAdress(groupThreadId, int2((int)_TapOffsets[2 * subRegionIdx + 1].z, (int)_TapOffsets[2 * subRegionIdx + 1].w)); |
| 71 | + neighborhoodData.lowValue3 = max(0, (gs_cacheLighting[tapIdx])); |
| 72 | + neighborhoodData.lowDepth.w = gs_cacheDepth[tapIdx]; |
| 73 | + neighborhoodData.lowWeight.w = _DistanceBasedWeights[subRegionIdx].w; |
| 74 | +} |
24 | 75 |
|
25 | 76 | // The output of our upscaling pass |
26 | | -RW_TEXTURE2D_X(float4, _OutputUpscaledTexture); |
| 77 | +RW_TEXTURE2D_X(float3, _OutputUpscaledTexture); |
27 | 78 |
|
28 | 79 | [numthreads(BILATERAL_UPSAMPLE_TILE_SIZE, BILATERAL_UPSAMPLE_TILE_SIZE, 1)] |
29 | | -void BILATERAL_UPSAMPLE(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID) |
| 80 | +void BILATERAL_UPSAMPLE(uint3 currentCoord : SV_DispatchThreadID, |
| 81 | + int groupIndex : SV_GroupIndex, |
| 82 | + uint2 groupThreadId : SV_GroupThreadID, |
| 83 | + uint2 groupId : SV_GroupID) |
30 | 84 | { |
31 | | - UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z); |
| 85 | + UNITY_XR_ASSIGN_VIEW_INDEX(currentCoord.z); |
| 86 | + |
| 87 | + // Only 36 workers of the 64 region do the pre-fetching |
| 88 | + if (groupIndex < 36) |
| 89 | + { |
| 90 | + // Load 1 value per thread |
| 91 | + FillUpsampleDataLDS(groupIndex, groupId * 8); |
| 92 | + } |
| 93 | + |
| 94 | + // Make sure all values are loaded in LDS by now. |
| 95 | + GroupMemoryBarrierWithGroupSync(); |
32 | 96 |
|
33 | 97 | // If out of bounds, discard |
34 | | - if (any(dispatchThreadId.xy > uint2(_ScreenSize.xy))) |
| 98 | + if (any(currentCoord.xy > uint2(_ScreenSize.xy))) |
35 | 99 | return; |
36 | 100 |
|
37 | | - // The pixel position to process |
38 | | - const uint2 outputCoord = dispatchThreadId.xy; |
39 | | - |
40 | 101 | // Read the depth value as early as possible and use it as late as possible |
41 | | - float hiResDepth = LOAD_TEXTURE2D_X(_DepthTexture, outputCoord).x; |
42 | | - |
43 | | - // Define what is the half resolution of this pixel |
44 | | - int2 halfResolution = (int2)(outputCoord / 2); |
45 | | - |
46 | | - // Define what is the half resolution of this pixel |
47 | | - int2 coordRepresenatative = halfResolution * 2; |
48 | | - |
49 | | - // Compute the shift within the half res |
50 | | - int2 halfResShift = outputCoord - coordRepresenatative; |
51 | | - |
52 | | - // Compute the shift of the pixel in the group |
53 | | - int shiftIndex = halfResShift.y * 2 + halfResShift.x; |
54 | | - |
55 | | - // Compute the shift in the upscale table |
56 | | - int offsetInCoordTable = shiftIndex * 4; |
57 | | - |
58 | | - // Compute the half resolution coordinates we should tap from |
59 | | - int2 halfResTap0 = clamp(0, halfResolution + UpscaleBilateralPixels[offsetInCoordTable], _HalfScreenSize.xy - 1); |
60 | | - int2 halfResTap1 = clamp(0, halfResolution + UpscaleBilateralPixels[offsetInCoordTable + 1], _HalfScreenSize.xy - 1); |
61 | | - int2 halfResTap2 = clamp(0, halfResolution + UpscaleBilateralPixels[offsetInCoordTable + 2], _HalfScreenSize.xy - 1); |
62 | | - int2 halfResTap3 = clamp(0, halfResolution + UpscaleBilateralPixels[offsetInCoordTable + 3], _HalfScreenSize.xy - 1); |
63 | | - |
64 | | - // Grab the depth of all the half resolution pixels |
65 | | - float4 lowDepths = float4(LOAD_TEXTURE2D_X(_DepthTexture, asuint(_DepthPyramidFirstMipLevelOffset) + halfResTap0).x |
66 | | - , LOAD_TEXTURE2D_X(_DepthTexture, asuint(_DepthPyramidFirstMipLevelOffset) + halfResTap1).x |
67 | | - , LOAD_TEXTURE2D_X(_DepthTexture, asuint(_DepthPyramidFirstMipLevelOffset) + halfResTap2).x |
68 | | - , LOAD_TEXTURE2D_X(_DepthTexture, asuint(_DepthPyramidFirstMipLevelOffset) + halfResTap3).x); |
69 | | - |
70 | | -#if SINGLE_CHANNEL |
71 | | - // Grab all the scalar values required for upscale |
72 | | - float4 lowRes = float4(_LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap0)].x |
73 | | - , _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap1)].x |
74 | | - , _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap2)].x |
75 | | - , _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap3)].x); |
76 | | - // Upscale and output |
77 | | - _OutputUpscaledTexture[COORD_TEXTURE2D_X(outputCoord)] = BilUpSingle(hiResDepth, lowDepths, lowRes); |
78 | | -#else |
79 | | - // Grab all the color values required for upscale |
80 | | - float4 lowResCol0 = max(0, _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap0)]); |
81 | | - float4 lowResCol1 = max(0, _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap1)]); |
82 | | - float4 lowResCol2 = max(0, _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap2)]); |
83 | | - float4 lowResCol3 = max(0, _LowResolutionTexture[COORD_TEXTURE2D_X(halfResTap3)]); |
84 | | - |
85 | | - _OutputUpscaledTexture[COORD_TEXTURE2D_X(outputCoord)] = BilUpColor(hiResDepth, lowDepths, lowResCol0, lowResCol1, lowResCol2, lowResCol3); |
86 | | -#endif |
| 102 | + float hiResDepth = LOAD_TEXTURE2D_X(_DepthTexture, currentCoord.xy).x; |
| 103 | + |
| 104 | + // Tap the neighborhood data from |
| 105 | + NeighborhoodUpsampleData2x2_RGB upsampleData; |
| 106 | + int localIndex = (currentCoord.x & 1) + (currentCoord.y & 1) * 2; |
| 107 | + FillUpsampleNeighborhoodData_2x2(groupThreadId, localIndex, upsampleData); |
| 108 | + |
| 109 | + // Upscale and return the result |
| 110 | + _OutputUpscaledTexture[COORD_TEXTURE2D_X(currentCoord.xy)] = BilUpColor2x2_RGB(hiResDepth, upsampleData); |
87 | 111 | } |
0 commit comments