Files
WickedEngine/WickedEngine/shaders/virtualTextureResidencyUpdateCS.hlsl
2025-01-09 17:27:24 +01:00

85 lines
2.5 KiB
HLSL

#include "globals.hlsli"
#include "ShaderInterop_Renderer.h"
ConstantBuffer<VirtualTextureResidencyUpdateCB> cb : register(b0);
[numthreads(8, 8, 1)]
void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
{
if (DTid.x >= cb.width || DTid.y >= cb.height)
return;
Buffer<uint> pageBuffer = bindless_buffers_uint[descriptor_index(cb.pageBufferRO)];
uint minLod = 0xFF;
uint tile_x = 0;
uint tile_y = 0;
uint lod_offset = 0;
uint lod_pages[10];
uint lod = 0;
for (lod = 0; lod < cb.lodCount; ++lod)
{
const uint l_x = DTid.x >> lod;
const uint l_y = DTid.y >> lod;
const uint l_width = max(1u, cb.width >> lod);
const uint l_height = max(1u, cb.height >> lod);
const uint l_page_offset = lod_offset;
const uint l_index = l_page_offset + l_x + l_y * l_width;
const uint page = pageBuffer[l_index];
lod_pages[lod] = page;
if (page == 0xFFFF)
{
// invalid page
// normally this wouldn't happen after a resident mip was encountered, but
// it can happen on allocation failures, in this case reset the residency to invalid
// this will mean that while there was a higher res resident page, but we can't use that because lower levels might be non resident
minLod = 0xFF;
}
else if(lod < minLod)
{
// valid page
// normally this would be the highest lod and we could exit, but failed allocations can cause holes in the mip chain
minLod = lod;
tile_x = page & 0xFF;
tile_y = (page >> 8u) & 0xFF;
}
lod_offset += l_width * l_height;
}
// Update the mip chain:
for (lod = 0; lod < cb.lodCount; ++lod)
{
uint lod_check = 1u << lod;
if ((DTid.x % lod_check == 0) && (DTid.y % lod_check == 0))
{
uint page = lod_pages[lod];
uint2 write_coord = DTid.xy >> lod;
const bool packed_mips = lod == cb.lodCount - 1;
if (packed_mips)
{
RWTexture2D<uint4> residencyTexture = bindless_rwtextures_uint4[descriptor_index(cb.residencyTextureRW_mips[lod - 1].x)];
uint x = page & 0xFF;
uint y = (page >> 8u) & 0xFF;
residencyTexture[write_coord] = uint4(residencyTexture[write_coord].xy, x, y);
}
else
{
RWTexture2D<uint4> residencyTexture = bindless_rwtextures_uint4[descriptor_index(cb.residencyTextureRW_mips[lod].x)];
if (lod < minLod || page == 0xFFFF)
{
residencyTexture[write_coord] = uint4(tile_x, tile_y, minLod, 0);
}
else
{
uint x = page & 0xFF;
uint y = (page >> 8u) & 0xFF;
residencyTexture[write_coord] = uint4(x, y, lod, 0);
}
}
}
}
}