NLDClient-yudde/ProjectNLD/Assets/Code/Shaders/builtin_shaders-2022.3.17f1/DefaultResources/Internal-VT-TranslationTabl...

238 lines
7.5 KiB
Plaintext

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
#pragma kernel Main NUM_LAYERS=1
#pragma kernel Main NUM_LAYERS=1 WITH_REPLACEMENT
#pragma kernel Main NUM_LAYERS=1 HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=1 WITH_REPLACEMENT HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=2
#pragma kernel Main NUM_LAYERS=2 WITH_REPLACEMENT
#pragma kernel Main NUM_LAYERS=2 HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=2 WITH_REPLACEMENT HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=3
#pragma kernel Main NUM_LAYERS=3 WITH_REPLACEMENT
#pragma kernel Main NUM_LAYERS=3 HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=3 WITH_REPLACEMENT HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=4
#pragma kernel Main NUM_LAYERS=4 WITH_REPLACEMENT
#pragma kernel Main NUM_LAYERS=4 HIGHEST_LEVEL
#pragma kernel Main NUM_LAYERS=4 WITH_REPLACEMENT HIGHEST_LEVEL
#pragma exclude_renderers gles3
static const uint TGSize = 32;
#define MAX_EVICTED_TILES 64
#define MAX_ADDED_TILES 64
#define INVALID_TILE 0x7FFFFFFF
#define DIRTY_INVALID_TILE 0xFFFFFFFF
#if (NUM_LAYERS == 1)
#define DATA_TYPE_UINT uint
#define DATA_TYPE_FLOAT float
#elif (NUM_LAYERS == 2)
#define DATA_TYPE_UINT uint2
#define DATA_TYPE_FLOAT float2
#elif (NUM_LAYERS == 3)
#define DATA_TYPE_UINT uint4
#define DATA_TYPE_FLOAT float4
#elif (NUM_LAYERS == 4)
#define DATA_TYPE_UINT uint4
#define DATA_TYPE_FLOAT float4
#endif
#if (NUM_LAYERS == 1)
#define SELECT_CHANNEL(x,c) x
#else
#define SELECT_CHANNEL(x,c) x[c]
#endif
RWByteAddressBuffer _output_buf : register(u0);
RWTexture2D<DATA_TYPE_FLOAT> translationTable : register(u1);
#if WITH_REPLACEMENT
Texture2D<DATA_TYPE_UINT> lookupTexture : register(t0);
#endif
cbuffer cbTranslationTableData
{
uint level;
uint invLevel;
uint width;
uint height;
uint bufferOffsetLevel;
uint bufferOffsetLevelAbove;
uint numEvictedTiles;
uint numAddedTiles;
uint4 addedTiles[(MAX_ADDED_TILES+1)/2];
uint4 evictedTiles[(MAX_EVICTED_TILES+3)/4];
};
// Returns true if the given FlatTileId should be evicted, else false
bool IsEvicted(uint tile)
{
// The tiles we have to evict are packed in a uint4, so a single uint4 can contain 4 tiles we need to evict.
// If the number of tiles we need to evict isn't a multiple of 4, the other channels can contain invalid values.
// We know how many tiles we need to evict so we can make sure we never read from those invalid channels.
// This way we don't depend on any magic value to skip those invalid channels.
for(uint i = 0; i < numEvictedTiles; i++)
{
uint tupleIdx = i/4;
uint channelIdx = i%4;
uint4 evictedTileTuple = evictedTiles[tupleIdx];
if(evictedTileTuple[channelIdx] == tile)
{
return true;
}
}
return false;
}
// Returns the new translation table data if the given FlatTileId was added, else returns 0xFFFFFFFF
uint IsAdded(uint tile)
{
// The tiles we have to add are packed in a uint4, a single uint4 contains 2 tiles we need to add (for every add we need the FlatTileId and the new payload).
// If the number of tiles we need to add isn't a multiple of 2, the other channels can contain invalid values.
// We know how many tiles we need to add so we can make sure we never read from those invalid channels.
// This way we don't depend on any magic value to skip those invalid channels.
for(uint i = 0; i < numAddedTiles; i++)
{
uint tupleIdx = i/2;
uint channelIdx = (i%2)*2;
uint4 addedTileTuple = addedTiles[tupleIdx];
if(addedTileTuple[channelIdx+0] == tile)
{
return addedTileTuple[channelIdx+1];
}
}
return 0xFFFFFFFF;
}
[numthreads(TGSize, TGSize, 1)]
void Main(in uint3 GroupID : SV_GroupID, in uint3 GroupThreadID : SV_GroupThreadID)
{
// The switch shader compiler has a feature that logs unnececarry warnings on the auto-translated hlsl.
// As the built-in resource compiling fails when output is non-empty, this logged warning then also causes the built-in resource build to fail.
// So, since we don't support switch for now we just ifdef it out for now.
#if !SHADER_API_SWITCH
const int strideLevel = width*height;
const int strideLevelAbove = strideLevel >> 2;
const uint2 tilePos = GroupID.xy * TGSize + GroupThreadID.xy;
const uint2 tilePosAbove = tilePos >> 1;
//
// Fetch data on level above
//
#if HIGHEST_LEVEL
DATA_TYPE_UINT dataAbove = INVALID_TILE;
#else
const int linearPosAbove = tilePosAbove.y * (width >> 1) + tilePosAbove.x;
const int linearPosLevelAbove = bufferOffsetLevelAbove + linearPosAbove;
// Coalesced reads
DATA_TYPE_UINT dataAbove;
[unroll]
for(int m = 0; m < NUM_LAYERS; m++)
{
SELECT_CHANNEL(dataAbove,m) = _output_buf.Load((strideLevelAbove*m + linearPosLevelAbove)*4);
}
#endif // HIGHEST_LEVEL
if(tilePos.x >= width || tilePos.y >= height)
{
return;
}
//
// Fetch data on current level
//
const int linearPos = tilePos.y * width + tilePos.x;
const int linearPosLevel = bufferOffsetLevel + linearPos;
// Coalesced reads
DATA_TYPE_UINT data = INVALID_TILE;
[unroll]
for(int j = 0; j < NUM_LAYERS; j++)
{
SELECT_CHANNEL(data,j) = _output_buf.Load((strideLevel*j + linearPosLevel)*4);
}
bool writeNeeded = false;
#if WITH_REPLACEMENT
// Fetch FlatTileID for current tile
DATA_TYPE_UINT flatTileIDs = lookupTexture.mips[level][tilePos];
[unroll]
for(int l = 0; l < NUM_LAYERS; l++)
{
// Check dirty flag
if(SELECT_CHANNEL(data,l) & 0x80000000)
{
// Strip the dirty flag
SELECT_CHANNEL(data,l) = SELECT_CHANNEL(data,l) & 0x7FFFFFFF;
writeNeeded = true;
}
bool resident = ((SELECT_CHANNEL(data,l) & 0xF) == invLevel);
[branch]
if(resident)
{
if(IsEvicted(SELECT_CHANNEL(flatTileIDs,l)))
{
SELECT_CHANNEL(data,l) = SELECT_CHANNEL(dataAbove,l);
writeNeeded = true;
}
}
else
{
uint newData = IsAdded(SELECT_CHANNEL(flatTileIDs,l));
if(newData != 0xFFFFFFFF)
{
// Strip the level and update if for the current level
SELECT_CHANNEL(data,l) = (newData & (~0xF)) | invLevel;
writeNeeded = true;
}
else if(SELECT_CHANNEL(data,l) != SELECT_CHANNEL(dataAbove,l))
{
SELECT_CHANNEL(data,l) = SELECT_CHANNEL(dataAbove,l);
writeNeeded = true;
}
}
}
#else
[unroll]
for(int l = 0; l < NUM_LAYERS; l++)
{
// Check dirty flag
if(SELECT_CHANNEL(data,l) & 0x80000000)
{
// Strip the dirty flag
SELECT_CHANNEL(data,l) = SELECT_CHANNEL(data,l) & 0x7FFFFFFF;
writeNeeded = true;
}
bool resident = ((SELECT_CHANNEL(data,l) & 0xF) == invLevel);
if ( !resident && SELECT_CHANNEL(data,l) != SELECT_CHANNEL(dataAbove,l))
{
SELECT_CHANNEL(data,l) = SELECT_CHANNEL(dataAbove,l);
writeNeeded = true;
}
}
#endif // WITH_REPLACEMENT
if(writeNeeded)
{
// Coalesced writes
[unroll]
for(int k = 0; k < NUM_LAYERS; k++)
{
_output_buf.Store((strideLevel*k + linearPosLevel)*4, SELECT_CHANNEL(data,k));
}
// Write to translation table texture
translationTable[tilePos] = asfloat(data);
}
#endif
}