terrain: virtual texture update on async compute
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+71
-69
@@ -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)
|
||||
|
||||
@@ -119,6 +119,7 @@ namespace wi::terrain
|
||||
wi::vector<Chunk> virtual_texture_updates;
|
||||
wi::vector<wi::graphics::GPUBarrier> virtual_texture_barriers_begin;
|
||||
wi::vector<wi::graphics::GPUBarrier> 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user