From b650bbc58ccab1393d6bb3415ce41f7aee3e867f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Tue, 8 Nov 2022 11:33:38 +0100 Subject: [PATCH] terrain: block compressed writed with sparse aliasing --- WickedEngine/shaders/ShaderInterop_Renderer.h | 2 +- .../terrainVirtualTextureUpdateCS.hlsl | 35 +++- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 4 +- WickedEngine/wiTerrain.cpp | 173 ++++++------------ WickedEngine/wiTerrain.h | 1 + WickedEngine/wiVersion.cpp | 2 +- 6 files changed, 94 insertions(+), 123 deletions(-) diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index c8ede5717..2f0f2b411 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -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 { diff --git a/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl b/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl index b7bc95454..22b929680 100644 --- a/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl +++ b/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl @@ -13,11 +13,11 @@ struct Terrain }; ConstantBuffer terrain : register(b0); -#if defined(UPDATE_NORMALMAP) || defined(UPDATE_SURFACEMAP) -RWTexture2D output : register(u0); // BC3, BC5 -#else +#if !defined(UPDATE_NORMALMAP) && !defined(UPDATE_SURFACEMAP) #define UPDATE_BASECOLORMAP -RWTexture2D output : register(u0); // BC1 +RWTexture2D bindless_rwtextures_uint2[] : register(space19); +#else +RWTexture2D 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 region_weights_texture = bindless_textures[push.region_weights_textureRO]; +#ifdef UPDATE_BASECOLORMAP + RWTexture2D 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 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 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); diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index a53676c9d..5478e6929 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -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); diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index 70144853f..1ca5ae1ee 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -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 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); diff --git a/WickedEngine/wiTerrain.h b/WickedEngine/wiTerrain.h index 0de2990ae..943028568 100644 --- a/WickedEngine/wiTerrain.h +++ b/WickedEngine/wiTerrain.h @@ -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; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 782886de3..ebdc30cde 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -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);