terrain: block compressed writed with sparse aliasing
This commit is contained in:
@@ -1098,8 +1098,8 @@ struct TerrainVirtualTexturePush
|
||||
uint2 offset;
|
||||
float2 resolution_rcp;
|
||||
uint2 write_size;
|
||||
uint write_offset;
|
||||
int region_weights_textureRO;
|
||||
int output_textureRW;
|
||||
};
|
||||
struct VirtualTextureResidencyUpdatePush
|
||||
{
|
||||
|
||||
@@ -13,11 +13,11 @@ struct Terrain
|
||||
};
|
||||
ConstantBuffer<Terrain> terrain : register(b0);
|
||||
|
||||
#if defined(UPDATE_NORMALMAP) || defined(UPDATE_SURFACEMAP)
|
||||
RWTexture2D<uint4> output : register(u0); // BC3, BC5
|
||||
#else
|
||||
#if !defined(UPDATE_NORMALMAP) && !defined(UPDATE_SURFACEMAP)
|
||||
#define UPDATE_BASECOLORMAP
|
||||
RWTexture2D<uint2> output : register(u0); // BC1
|
||||
RWTexture2D<uint2> bindless_rwtextures_uint2[] : register(space19);
|
||||
#else
|
||||
RWTexture2D<uint4> bindless_rwtextures_uint4[] : register(space19);
|
||||
#endif // UPDATE_NORMALMAP
|
||||
|
||||
static const uint2 block_offsets[BLOCK_SIZE_4X4] = {
|
||||
@@ -27,6 +27,17 @@ static const uint2 block_offsets[BLOCK_SIZE_4X4] = {
|
||||
uint2(0, 3), uint2(1, 3), uint2(2, 3), uint2(3, 3),
|
||||
};
|
||||
|
||||
#undef WICKED_ENGINE_DEFAULT_ROOTSIGNATURE // don't use auto root signature!
|
||||
[RootSignature(
|
||||
"RootConstants(num32BitConstants=8, b999), "
|
||||
"CBV(b0), "
|
||||
"DescriptorTable( "
|
||||
"SRV(t0, space = 2, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE),"
|
||||
"UAV(u0, space = 19, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)"
|
||||
"), "
|
||||
"StaticSampler(s100, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_MIN_MAG_MIP_LINEAR),"
|
||||
"StaticSampler(s101, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_MIN_MAG_MIP_LINEAR),"
|
||||
)]
|
||||
[numthreads(8, 8, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
@@ -35,10 +46,22 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
|
||||
Texture2D<float4> region_weights_texture = bindless_textures[push.region_weights_textureRO];
|
||||
|
||||
#ifdef UPDATE_BASECOLORMAP
|
||||
RWTexture2D<uint2> output = bindless_rwtextures_uint2[push.output_textureRW];
|
||||
float3 block_rgb[BLOCK_SIZE_4X4];
|
||||
float block_a[BLOCK_SIZE_4X4];
|
||||
#endif // UPDATE_BASECOLORMAP
|
||||
|
||||
#ifdef UPDATE_NORMALMAP
|
||||
RWTexture2D<uint4> output = bindless_rwtextures_uint4[push.output_textureRW];
|
||||
float block_x[BLOCK_SIZE_4X4];
|
||||
float block_y[BLOCK_SIZE_4X4];
|
||||
#endif // UPDATE_NORMALMAP
|
||||
|
||||
#ifdef UPDATE_SURFACEMAP
|
||||
RWTexture2D<uint4> output = bindless_rwtextures_uint4[push.output_textureRW];
|
||||
float3 block_rgb[BLOCK_SIZE_4X4];
|
||||
float block_a[BLOCK_SIZE_4X4];
|
||||
#endif // UPDATE_SURFACEMAP
|
||||
|
||||
for(uint o = 0; o < BLOCK_SIZE_4X4; ++o)
|
||||
{
|
||||
@@ -128,7 +151,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
#endif // UPDATE_SURFACEMAP
|
||||
}
|
||||
|
||||
const uint2 write_coord = DTid.xy + uint2(push.write_offset, 0);
|
||||
const uint2 write_coord = push.offset / 4 + DTid.xy;
|
||||
|
||||
#ifdef UPDATE_BASECOLORMAP
|
||||
output[write_coord] = CompressBlockBC1_UNORM(block_rgb, CMP_QUALITY0, /*isSRGB =*/ true);
|
||||
|
||||
@@ -2633,7 +2633,7 @@ using namespace vulkan_internal;
|
||||
capabilities |= GraphicsDeviceCapability::DEPTH_BOUNDS_TEST;
|
||||
}
|
||||
|
||||
if (features2.features.sparseBinding == VK_TRUE)
|
||||
if (features2.features.sparseBinding == VK_TRUE && features2.features.sparseResidencyAliased == VK_TRUE)
|
||||
{
|
||||
if (properties2.properties.sparseProperties.residencyNonResidentStrict == VK_TRUE)
|
||||
{
|
||||
@@ -3592,6 +3592,7 @@ using namespace vulkan_internal;
|
||||
{
|
||||
bufferInfo.flags |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
|
||||
bufferInfo.flags |= VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT;
|
||||
bufferInfo.flags |= VK_BUFFER_CREATE_SPARSE_ALIASED_BIT;
|
||||
|
||||
res = vkCreateBuffer(device, &bufferInfo, nullptr, &internal_state->resource);
|
||||
assert(res == VK_SUCCESS);
|
||||
@@ -3841,6 +3842,7 @@ using namespace vulkan_internal;
|
||||
{
|
||||
imageInfo.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
|
||||
imageInfo.flags |= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
|
||||
imageInfo.flags |= VK_IMAGE_CREATE_SPARSE_ALIASED_BIT;
|
||||
|
||||
res = vkCreateImage(device, &imageInfo, nullptr, &internal_state->resource);
|
||||
assert(res == VK_SUCCESS);
|
||||
|
||||
+59
-114
@@ -233,6 +233,44 @@ namespace wi::terrain
|
||||
bool success = device->CreateTexture(&desc, nullptr, &texture);
|
||||
assert(success);
|
||||
|
||||
locker.lock();
|
||||
if (page_allocator.blocks.empty())
|
||||
{
|
||||
page_allocator.init(64ull * 1024ull * 1024ull, texture.sparse_page_size);
|
||||
}
|
||||
locker.unlock();
|
||||
|
||||
// For writing the block compressed texture, create an aliased raw block texture:
|
||||
if(IsFormatBlockCompressed(desc.format))
|
||||
{
|
||||
TextureDesc desc_raw_block = desc;
|
||||
desc_raw_block.width /= 4;
|
||||
desc_raw_block.height /= 4;
|
||||
desc_raw_block.bind_flags = BindFlag::UNORDERED_ACCESS;
|
||||
desc_raw_block.layout = ResourceState::UNORDERED_ACCESS;
|
||||
switch (desc_raw_block.format)
|
||||
{
|
||||
default:
|
||||
case Format::BC1_UNORM:
|
||||
case Format::BC1_UNORM_SRGB:
|
||||
desc_raw_block.format = Format::R32G32_UINT;
|
||||
break;
|
||||
case Format::BC3_UNORM:
|
||||
case Format::BC3_UNORM_SRGB:
|
||||
case Format::BC5_UNORM:
|
||||
desc_raw_block.format = Format::R32G32B32A32_UINT;
|
||||
break;
|
||||
}
|
||||
success = device->CreateTexture(&desc_raw_block, nullptr, &texture_raw_block);
|
||||
assert(success);
|
||||
|
||||
for (uint32_t i = 0; i < texture_raw_block.desc.mip_levels; ++i)
|
||||
{
|
||||
int subresource_index = device->CreateSubresource(&texture_raw_block, SubresourceType::UAV, 0, 1, i, 1);
|
||||
assert(subresource_index == i);
|
||||
}
|
||||
}
|
||||
|
||||
residencyMap = {};
|
||||
feedbackMap = {};
|
||||
requestBuffer = {};
|
||||
@@ -381,13 +419,6 @@ namespace wi::terrain
|
||||
}
|
||||
}
|
||||
|
||||
locker.lock();
|
||||
if (page_allocator.blocks.empty())
|
||||
{
|
||||
page_allocator.init(64ull * 1024ull * 1024ull, texture.sparse_page_size);
|
||||
}
|
||||
locker.unlock();
|
||||
|
||||
if (feedbackMap.IsValid())
|
||||
{
|
||||
// Allocate least detailed mip level up front:
|
||||
@@ -726,16 +757,23 @@ namespace wi::terrain
|
||||
{
|
||||
if (sparse_coordinate.empty())
|
||||
return;
|
||||
SparseUpdateCommand command;
|
||||
command.sparse_resource = &texture;
|
||||
command.num_resource_regions = (uint32_t)sparse_coordinate.size();
|
||||
command.coordinates = sparse_coordinate.data();
|
||||
command.sizes = sparse_size.data();
|
||||
command.tile_pool = &allocator.blocks[last_block];
|
||||
command.range_flags = tile_range_flags.data();
|
||||
command.range_start_offsets = tile_range_offset.data();
|
||||
command.range_tile_counts = tile_range_count.data();
|
||||
GetDevice()->SparseUpdate(QUEUE_COPY, &command, 1);
|
||||
|
||||
locker.lock();
|
||||
SparseUpdateCommand commands[2];
|
||||
commands[0].sparse_resource = &texture;
|
||||
commands[0].num_resource_regions = (uint32_t)sparse_coordinate.size();
|
||||
commands[0].coordinates = sparse_coordinate.data();
|
||||
commands[0].sizes = sparse_size.data();
|
||||
commands[0].tile_pool = &allocator.blocks[last_block];
|
||||
commands[0].range_flags = tile_range_flags.data();
|
||||
commands[0].range_start_offsets = tile_range_offset.data();
|
||||
commands[0].range_tile_counts = tile_range_count.data();
|
||||
|
||||
commands[1] = commands[0];
|
||||
commands[1].sparse_resource = &texture_raw_block;
|
||||
|
||||
GetDevice()->SparseUpdate(QUEUE_COPY, commands, arraysize(commands));
|
||||
locker.unlock();
|
||||
sparse_coordinate.clear();
|
||||
sparse_size.clear();
|
||||
tile_range_flags.clear();
|
||||
@@ -1514,8 +1552,9 @@ namespace wi::terrain
|
||||
|
||||
material->textures[map_type].lod_clamp = (float)vt.lod_count - 1;
|
||||
virtual_textures_in_use.push_back(&vt);
|
||||
virtual_texture_barriers_before_update.push_back(GPUBarrier::Image(&vt.texture, vt.texture.desc.layout, ResourceState::COPY_DST));
|
||||
virtual_texture_barriers_after_update.push_back(GPUBarrier::Image(&vt.texture, ResourceState::COPY_DST, vt.texture.desc.layout));
|
||||
virtual_texture_barriers_before_update.push_back(GPUBarrier::Memory(&vt.texture_raw_block));
|
||||
virtual_texture_barriers_after_update.push_back(GPUBarrier::Memory(&vt.texture_raw_block));
|
||||
|
||||
|
||||
if (!vt.residencyMap.IsValid())
|
||||
continue;
|
||||
@@ -1678,85 +1717,8 @@ namespace wi::terrain
|
||||
material_HighAltitude.WriteShaderMaterial(&materials[3]);
|
||||
device->BindDynamicConstantBuffer(materials, 0, cmd);
|
||||
|
||||
static const uint32_t raw_tiles_max = 16u;
|
||||
static Texture bc1_raw;
|
||||
if (!bc1_raw.IsValid())
|
||||
{
|
||||
TextureDesc td;
|
||||
td.width = 512 / 4 * raw_tiles_max;
|
||||
td.height = 256 / 4;
|
||||
td.format = Format::R32G32_UINT;
|
||||
td.bind_flags = BindFlag::UNORDERED_ACCESS;
|
||||
td.layout = ResourceState::UNORDERED_ACCESS;
|
||||
bool success = device->CreateTexture(&td, nullptr, &bc1_raw);
|
||||
assert(success);
|
||||
}
|
||||
static Texture bc3_bc5_raw;
|
||||
if (!bc3_bc5_raw.IsValid())
|
||||
{
|
||||
TextureDesc td;
|
||||
td.width = 256 / 4 * raw_tiles_max;
|
||||
td.height = 256 / 4;
|
||||
td.format = Format::R32G32B32A32_UINT;
|
||||
td.bind_flags = BindFlag::UNORDERED_ACCESS;
|
||||
td.layout = ResourceState::UNORDERED_ACCESS;
|
||||
bool success = device->CreateTexture(&td, nullptr, &bc3_bc5_raw);
|
||||
assert(success);
|
||||
}
|
||||
|
||||
struct PendingRawTile
|
||||
{
|
||||
const Texture* dst;
|
||||
uint32_t dstX;
|
||||
uint32_t dstY;
|
||||
uint32_t dstMip;
|
||||
uint2 bc_size;
|
||||
uint32_t srcX;
|
||||
};
|
||||
static wi::vector<PendingRawTile> pending_raw_tiles;
|
||||
const Texture* bc_raw[] = {
|
||||
&bc1_raw,
|
||||
&bc3_bc5_raw,
|
||||
&bc3_bc5_raw,
|
||||
};
|
||||
|
||||
auto bc_raw_flush = [&](uint32_t map_type) {
|
||||
if (pending_raw_tiles.empty())
|
||||
return;
|
||||
|
||||
GPUBarrier barriers[] = {
|
||||
GPUBarrier::Image(bc_raw[map_type], bc_raw[map_type]->desc.layout, ResourceState::COPY_SRC),
|
||||
};
|
||||
device->Barrier(barriers, arraysize(barriers), cmd);
|
||||
|
||||
for (auto& pending : pending_raw_tiles)
|
||||
{
|
||||
Box srcbox;
|
||||
srcbox.left = pending.srcX;
|
||||
srcbox.right = pending.srcX + pending.bc_size.x;
|
||||
srcbox.top = 0;
|
||||
srcbox.bottom = pending.bc_size.y;
|
||||
srcbox.front = 0;
|
||||
srcbox.back = 1;
|
||||
device->CopyTexture(
|
||||
pending.dst, pending.dstX, pending.dstY, 0, pending.dstMip, 0,
|
||||
bc_raw[map_type], 0, 0, cmd, &srcbox
|
||||
);
|
||||
}
|
||||
|
||||
for (uint32_t map_type = 0; map_type < arraysize(barriers); ++map_type)
|
||||
{
|
||||
std::swap(barriers[map_type].image.layout_before, barriers[map_type].image.layout_after);
|
||||
}
|
||||
device->Barrier(barriers, arraysize(barriers), cmd);
|
||||
|
||||
pending_raw_tiles.clear();
|
||||
};
|
||||
|
||||
for (uint32_t map_type = 0; map_type < 3; map_type++)
|
||||
{
|
||||
uint32_t pending_raw_tile_offset = 0;
|
||||
|
||||
switch (map_type)
|
||||
{
|
||||
case MaterialComponent::BASECOLORMAP:
|
||||
@@ -1772,7 +1734,6 @@ namespace wi::terrain
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
device->BindUAV(bc_raw[map_type], 0, cmd);
|
||||
|
||||
for (const VirtualTexture* vt : virtual_textures_in_use)
|
||||
{
|
||||
@@ -1807,12 +1768,6 @@ namespace wi::terrain
|
||||
(size.y + 3u) / 4u
|
||||
);
|
||||
|
||||
if ((pending_raw_tile_offset + bc_size.x) >= bc_raw[map_type]->desc.width)
|
||||
{
|
||||
bc_raw_flush(map_type);
|
||||
pending_raw_tile_offset = 0;
|
||||
}
|
||||
|
||||
TerrainVirtualTexturePush push;
|
||||
push.offset = uint2(
|
||||
request.tile_x * size.x,
|
||||
@@ -1821,25 +1776,15 @@ namespace wi::terrain
|
||||
push.resolution_rcp.x = 1.0f / request_lod_resolution.x;
|
||||
push.resolution_rcp.y = 1.0f / request_lod_resolution.y;
|
||||
push.write_size = bc_size;
|
||||
push.write_offset = pending_raw_tile_offset;
|
||||
push.region_weights_textureRO = device->GetDescriptorIndex(&vt->region_weights_texture, SubresourceType::SRV);
|
||||
push.output_textureRW = device->GetDescriptorIndex(&vt->texture_raw_block, SubresourceType::UAV, (int)mip);
|
||||
device->PushConstants(&push, sizeof(push), cmd);
|
||||
|
||||
device->Dispatch((bc_size.x + 7u) / 8u, (bc_size.y + 7u) / 8u, 1, cmd);
|
||||
|
||||
PendingRawTile& pending_raw_tile = pending_raw_tiles.emplace_back();
|
||||
pending_raw_tile.dst = &vt->texture;
|
||||
pending_raw_tile.dstX = push.offset.x;
|
||||
pending_raw_tile.dstY = push.offset.y;
|
||||
pending_raw_tile.dstMip = mip;
|
||||
pending_raw_tile.bc_size = bc_size;
|
||||
pending_raw_tile.srcX = push.write_offset;
|
||||
pending_raw_tile_offset += bc_size.x;
|
||||
}
|
||||
}
|
||||
vt->update_requests.clear();
|
||||
}
|
||||
bc_raw_flush(map_type);
|
||||
}
|
||||
device->EventEnd(cmd);
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace wi::terrain
|
||||
struct VirtualTexture
|
||||
{
|
||||
wi::graphics::Texture texture;
|
||||
wi::graphics::Texture texture_raw_block;
|
||||
wi::graphics::Texture residencyMap;
|
||||
wi::graphics::Texture feedbackMap;
|
||||
wi::graphics::GPUBuffer requestBuffer;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wi::version
|
||||
// minor features, major updates, breaking compatibility changes
|
||||
const int minor = 71;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 83;
|
||||
const int revision = 84;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user