From 1eba681e74cc77ad2db2c1ae21c8dcc2fd6353ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Mon, 3 Oct 2022 15:50:54 +0200 Subject: [PATCH] terrain: virtual texture update on async compute --- WickedEngine/wiRenderer.cpp | 5 ++ WickedEngine/wiTerrain.cpp | 140 ++++++++++++++++++------------------ WickedEngine/wiTerrain.h | 3 + WickedEngine/wiVersion.cpp | 2 +- 4 files changed, 80 insertions(+), 70 deletions(-) diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 57ed1ea50..730a9af05 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -4221,6 +4221,11 @@ void UpdateRenderDataAsync( } } + for (size_t i = 0; i < vis.scene->terrains.GetCount(); ++i) + { + vis.scene->terrains[i].UpdateVirtualTextures(cmd); + } + device->EventEnd(cmd); } diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index 462d4bac2..a9dbe7259 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -311,8 +311,7 @@ namespace wi::terrain // Check whether there are any materials that would write to virtual textures: bool virtual_texture_any = false; - bool virtual_texture_available[MaterialComponent::TEXTURESLOT_COUNT] = {}; - virtual_texture_available[MaterialComponent::SURFACEMAP] = true; // this is always needed to bake individual material properties + virtual_texture_available[MaterialComponent::TEXTURESLOT_COUNT] = {}; MaterialComponent* virtual_materials[4] = { &material_Base, &material_Slope, @@ -323,6 +322,7 @@ namespace wi::terrain { for (int i = 0; i < MaterialComponent::TEXTURESLOT_COUNT; ++i) { + virtual_texture_available[i] = false; switch (i) { case MaterialComponent::BASECOLORMAP: @@ -339,6 +339,7 @@ namespace wi::terrain } } } + virtual_texture_available[MaterialComponent::SURFACEMAP] = true; // this is always needed to bake individual material properties for (auto it = chunks.begin(); it != chunks.end();) { @@ -552,6 +553,13 @@ namespace wi::terrain if (need_update) { + // Shrink the uvs to avoid wrap sampling across edge by object rendering shaders: + float virtual_texture_resolution_rcp = 1.0f / float(chunk_data.required_texture_resolution); + material->texMulAdd.x = float(chunk_data.required_texture_resolution - 1) * virtual_texture_resolution_rcp; + material->texMulAdd.y = float(chunk_data.required_texture_resolution - 1) * virtual_texture_resolution_rcp; + material->texMulAdd.z = 0.5f * virtual_texture_resolution_rcp; + material->texMulAdd.w = 0.5f * virtual_texture_resolution_rcp; + virtual_texture_updates.push_back(chunk); } @@ -561,73 +569,6 @@ namespace wi::terrain it++; } - // Execute batched virtual texture updates: - if (!virtual_texture_updates.empty()) - { - CommandList cmd = device->BeginCommandList(); - device->EventBegin("TerrainVirtualTextureUpdate", cmd); - auto range = wi::profiler::BeginRangeGPU("TerrainVirtualTextureUpdate", cmd); - device->Barrier(virtual_texture_barriers_begin.data(), (uint32_t)virtual_texture_barriers_begin.size(), cmd); - - device->BindComputeShader(wi::renderer::GetShader(wi::enums::CSTYPE_TERRAIN_VIRTUALTEXTURE_UPDATE), cmd); - - ShaderMaterial materials[4]; - material_Base.WriteShaderMaterial(&materials[0]); - material_Slope.WriteShaderMaterial(&materials[1]); - material_LowAltitude.WriteShaderMaterial(&materials[2]); - material_HighAltitude.WriteShaderMaterial(&materials[3]); - device->BindDynamicConstantBuffer(materials, 0, cmd); - - for (auto& chunk : virtual_texture_updates) - { - auto it = chunks.find(chunk); - if (it == chunks.end()) - continue; - ChunkData& chunk_data = it->second; - - const GPUResource* res[] = { - &chunk_data.region_weights_texture, - }; - device->BindResources(res, 0, arraysize(res), cmd); - - MaterialComponent* material = scene->materials.GetComponent(chunk_data.entity); - if (material != nullptr) - { - // Shrink the uvs to avoid wrap sampling across edge by object rendering shaders: - float virtual_texture_resolution_rcp = 1.0f / float(chunk_data.required_texture_resolution); - material->texMulAdd.x = float(chunk_data.required_texture_resolution - 1) * virtual_texture_resolution_rcp; - material->texMulAdd.y = float(chunk_data.required_texture_resolution - 1) * virtual_texture_resolution_rcp; - material->texMulAdd.z = 0.5f * virtual_texture_resolution_rcp; - material->texMulAdd.w = 0.5f * virtual_texture_resolution_rcp; - - for (int i = 0; i < MaterialComponent::TEXTURESLOT_COUNT; ++i) - { - if (virtual_texture_available[i]) - { - const Texture& texture = material->textures[i].resource.GetTexture(); - - device->BindUAV(&texture, i, cmd); - device->ClearUAV(&texture, 0, cmd); - - if (texture.GetDesc().mip_levels > 1) - { - wi::renderer::AddDeferredMIPGen(material->textures[i].resource.GetTexture()); - } - } - } - } - - device->Dispatch(chunk_data.required_texture_resolution / 8u, chunk_data.required_texture_resolution / 8u, 1, cmd); - } - - device->Barrier(virtual_texture_barriers_end.data(), (uint32_t)virtual_texture_barriers_end.size(), cmd); - - wi::renderer::ProcessDeferredMipGenRequests(cmd); - - wi::profiler::EndRange(range); - device->EventEnd(cmd); - } - // Start the generation on a background thread and keep it running until the next frame wi::jobsystem::Execute(generator->workload, [=](wi::jobsystem::JobArgs args) { @@ -974,6 +915,67 @@ namespace wi::terrain generator->cancelled.store(false); // the next generation can run } + void Terrain::UpdateVirtualTextures(CommandList cmd) const + { + if (virtual_texture_updates.empty()) + return; + + GraphicsDevice* device = GetDevice(); + device->EventBegin("TerrainVirtualTextureUpdate", cmd); + auto range = wi::profiler::BeginRangeGPU("TerrainVirtualTextureUpdate", cmd); + device->Barrier(virtual_texture_barriers_begin.data(), (uint32_t)virtual_texture_barriers_begin.size(), cmd); + + device->BindComputeShader(wi::renderer::GetShader(wi::enums::CSTYPE_TERRAIN_VIRTUALTEXTURE_UPDATE), cmd); + + ShaderMaterial materials[4]; + material_Base.WriteShaderMaterial(&materials[0]); + material_Slope.WriteShaderMaterial(&materials[1]); + material_LowAltitude.WriteShaderMaterial(&materials[2]); + material_HighAltitude.WriteShaderMaterial(&materials[3]); + device->BindDynamicConstantBuffer(materials, 0, cmd); + + for (auto& chunk : virtual_texture_updates) + { + auto it = chunks.find(chunk); + if (it == chunks.end()) + continue; + const ChunkData& chunk_data = it->second; + + const GPUResource* res[] = { + &chunk_data.region_weights_texture, + }; + device->BindResources(res, 0, arraysize(res), cmd); + + const MaterialComponent* material = scene->materials.GetComponent(chunk_data.entity); + if (material != nullptr) + { + for (int i = 0; i < MaterialComponent::TEXTURESLOT_COUNT; ++i) + { + if (virtual_texture_available[i]) + { + const Texture& texture = material->textures[i].resource.GetTexture(); + + device->BindUAV(&texture, i, cmd); + + if (texture.GetDesc().mip_levels > 1) + { + wi::renderer::AddDeferredMIPGen(material->textures[i].resource.GetTexture()); + } + } + } + } + + device->Dispatch(chunk_data.required_texture_resolution / 8u, chunk_data.required_texture_resolution / 8u, 1, cmd); + } + + device->Barrier(virtual_texture_barriers_end.data(), (uint32_t)virtual_texture_barriers_end.size(), cmd); + + wi::renderer::ProcessDeferredMipGenRequests(cmd); + + wi::profiler::EndRange(range); + device->EventEnd(cmd); + } + void Terrain::BakeVirtualTexturesToFiles() { if (terrainEntity == INVALID_ENTITY) diff --git a/WickedEngine/wiTerrain.h b/WickedEngine/wiTerrain.h index 3d07be50d..6df05d697 100644 --- a/WickedEngine/wiTerrain.h +++ b/WickedEngine/wiTerrain.h @@ -119,6 +119,7 @@ namespace wi::terrain wi::vector virtual_texture_updates; wi::vector virtual_texture_barriers_begin; wi::vector virtual_texture_barriers_end; + bool virtual_texture_available[wi::scene::MaterialComponent::TEXTURESLOT_COUNT] = {}; constexpr bool IsCenterToCamEnabled() const { return _flags & CENTER_TO_CAM; } constexpr bool IsRemovalEnabled() const { return _flags & REMOVAL; } @@ -161,6 +162,8 @@ namespace wi::terrain void Generation_Update(const wi::scene::CameraComponent& camera); // Tells the generation thread that it should be cancelled and blocks until that is confirmed void Generation_Cancel(); + // Updates the virtual textures on GPU by compute shaders + void UpdateVirtualTextures(wi::graphics::CommandList cmd) const; // The virtual textures will be compressed and saved into resources. They can be serialized from there void BakeVirtualTexturesToFiles(); // Creates the blend weight texture for a chunk data diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 9b55da1fa..f62a39a59 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 = 66; + const int revision = 67; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);