67 lines
3.2 KiB
Plaintext
67 lines
3.2 KiB
Plaintext
#pragma kernel BuildIndirect
|
|
|
|
#pragma multi_compile _ IS_DRAWPROCEDURALINDIRECT
|
|
|
|
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
|
|
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs.hlsl"
|
|
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
|
|
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl"
|
|
|
|
#ifdef PLATFORM_LANE_COUNT // We can infer the size of a wave. This is currently not possible on non-consoles, so we have to fallback to a sensible default in those cases.
|
|
#define NR_THREADS PLATFORM_LANE_COUNT
|
|
#else
|
|
#define NR_THREADS 64 // default to 64 threads per group on other platforms..
|
|
#endif
|
|
|
|
RWBuffer<uint> g_DispatchIndirectBuffer : register( u0 ); // Indirect arguments have to be in a _buffer_, not a structured buffer
|
|
RWStructuredBuffer<uint> g_TileList;
|
|
StructuredBuffer<uint> g_TileFeatureFlags;
|
|
|
|
uniform uint g_NumTiles;
|
|
uniform uint g_NumTilesX;
|
|
|
|
[numthreads(NR_THREADS, 1, 1)]
|
|
void BuildIndirect(uint3 dispatchThreadId : SV_DispatchThreadID)
|
|
{
|
|
if (dispatchThreadId.x >= g_NumTiles)
|
|
return;
|
|
|
|
UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z);
|
|
|
|
uint featureFlags = g_TileFeatureFlags[dispatchThreadId.x + unity_StereoEyeIndex * g_NumTiles];
|
|
|
|
uint tileY = (dispatchThreadId.x + 0.5f) / (float)g_NumTilesX; // Integer division is extremely expensive, so we better avoid it
|
|
uint tileX = dispatchThreadId.x - tileY * g_NumTilesX;
|
|
|
|
// Check if there is no material (means it is a sky/background pixel).
|
|
// Note that we can have no lights, yet we still need to render geometry with precomputed illumination.
|
|
if ((featureFlags & MATERIAL_FEATURE_MASK_FLAGS) != 0)
|
|
{
|
|
uint variant = FeatureFlagsToTileVariant(featureFlags);
|
|
uint tileOffset;
|
|
|
|
#ifdef IS_DRAWPROCEDURALINDIRECT
|
|
// We are filling up an indirect argument buffer for DrawProceduralIndirect.
|
|
// The buffer contains {vertex count per instance, instance count, start vertex location, and start instance location} = {0, instance count, 0, 0, 0}
|
|
InterlockedAdd(g_DispatchIndirectBuffer[variant * 4 + 1], 1, tileOffset);
|
|
#else
|
|
uint prevGroupCnt;
|
|
|
|
// We are filling up an indirect argument buffer for DispatchIndirect.
|
|
// The buffer contains {groupCntX, groupCntY, groupCntZ} = {groupCnt, 0, 0}.
|
|
InterlockedAdd(g_DispatchIndirectBuffer[variant * 3 + 0], 4, prevGroupCnt);
|
|
tileOffset = prevGroupCnt / 4; // 4x 8x8 groups per a 16x16 tile
|
|
#endif
|
|
|
|
// See LightDefinitions class in LightLoop.cs
|
|
uint tileIndex = (unity_StereoEyeIndex << TILE_INDEX_SHIFT_EYE) | (tileY << TILE_INDEX_SHIFT_Y) | (tileX << TILE_INDEX_SHIFT_X);
|
|
// For g_TileList each VR eye is interlaced instead of one eye and then the other. Thus why we use _XRViewCount here
|
|
g_TileList[variant * g_NumTiles * _XRViewCount + tileOffset] = tileIndex;
|
|
}
|
|
}
|