From 084a1b1f1f7998be22a42d58dd67cda485901097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Thu, 18 Aug 2022 11:50:09 +0200 Subject: [PATCH] DDGI updates (#514) DDGI updates: - allow 0 raycount to keep static DDGI - DDGI serialization for saving and loading with scene - grid dimensions configurable - refactors --- Editor/ObjectWindow.cpp | 2 +- Editor/OptionsWindow.cpp | 1 + Editor/RendererWindow.cpp | 60 ++++++++- Editor/RendererWindow.h | 4 + WickedEngine/ArchiveVersionHistory.txt | 1 + WickedEngine/shaders/ShaderInterop_DDGI.h | 22 ++-- WickedEngine/shaders/ShaderInterop_Renderer.h | 9 ++ WickedEngine/wiArchive.cpp | 2 +- WickedEngine/wiRenderer.cpp | 41 +++--- WickedEngine/wiScene.cpp | 87 +++++++----- WickedEngine/wiScene.h | 16 ++- WickedEngine/wiScene_Serializers.cpp | 124 ++++++++++++++++++ WickedEngine/wiVersion.cpp | 2 +- 13 files changed, 290 insertions(+), 81 deletions(-) diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 77cdad1c7..cc42335ce 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -747,7 +747,7 @@ void ObjectWindow::Create(EditorComponent* _editor) AddWidget(&generateLightmapButton); stopLightmapGenButton.Create("Stop Lightmap Gen"); - stopLightmapGenButton.SetTooltip("Stop the lightmap rendering and save the lightmap."); + stopLightmapGenButton.SetTooltip("Stop the lightmap rendering and save the lightmap.\nIf denoiser is enabled, this is the point at which lightmap will be denoised, which could take a while."); stopLightmapGenButton.SetPos(XMFLOAT2(x, y += step)); stopLightmapGenButton.SetSize(XMFLOAT2(wid, hei)); stopLightmapGenButton.OnClick([&](wi::gui::EventArgs args) { diff --git a/Editor/OptionsWindow.cpp b/Editor/OptionsWindow.cpp index e20d343c4..73b7d436f 100644 --- a/Editor/OptionsWindow.cpp +++ b/Editor/OptionsWindow.cpp @@ -656,6 +656,7 @@ void OptionsWindow::Update(float dt) { cameraWnd.Update(); paintToolWnd.Update(dt); + rendererWnd.Update(); } void OptionsWindow::ResizeLayout() diff --git a/Editor/RendererWindow.cpp b/Editor/RendererWindow.cpp index 6060cb958..dcfef672f 100644 --- a/Editor/RendererWindow.cpp +++ b/Editor/RendererWindow.cpp @@ -12,9 +12,9 @@ void RendererWindow::Create(EditorComponent* _editor) wi::renderer::SetToDrawGridHelper(true); wi::renderer::SetToDrawDebugCameras(true); - SetSize(XMFLOAT2(580, 1120)); + SetSize(XMFLOAT2(580, 1180)); - float step = 20; + float step = 21; float itemheight = 18; float x = 160; float y = 0; @@ -118,7 +118,7 @@ void RendererWindow::Create(EditorComponent* _editor) AddWidget(&surfelGIDebugComboBox); ddgiCheckBox.Create("DDGI: "); - ddgiCheckBox.SetTooltip("Toggle Dynamic Diffuse Global Illumination (DDGI)."); + ddgiCheckBox.SetTooltip("Toggle Dynamic Diffuse Global Illumination (DDGI).\nNote that DDGI probes that were loaded with the scene will still be active if this is turned off, but they won't be updated."); ddgiCheckBox.SetPos(XMFLOAT2(x, y += step)); ddgiCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); ddgiCheckBox.OnClick([](wi::gui::EventArgs args) { @@ -137,7 +137,7 @@ void RendererWindow::Create(EditorComponent* _editor) ddgiDebugCheckBox.SetCheck(wi::renderer::GetDDGIDebugEnabled()); AddWidget(&ddgiDebugCheckBox); - ddgiRayCountSlider.Create(32, DDGI_MAX_RAYCOUNT, 64, DDGI_MAX_RAYCOUNT - 32, "DDGI RayCount: "); + ddgiRayCountSlider.Create(0, DDGI_MAX_RAYCOUNT, 64, DDGI_MAX_RAYCOUNT, "DDGI RayCount: "); ddgiRayCountSlider.SetTooltip("Adjust the ray count per DDGI probe."); ddgiRayCountSlider.SetSize(XMFLOAT2(wid, itemheight)); ddgiRayCountSlider.SetPos(XMFLOAT2(x, y += step)); @@ -147,6 +147,46 @@ void RendererWindow::Create(EditorComponent* _editor) }); AddWidget(&ddgiRayCountSlider); + ddgiX.Create(""); + ddgiX.SetTooltip("Probe count in X dimension."); + ddgiX.SetDescription("DDGI Probes: "); + ddgiX.SetPos(XMFLOAT2(x, y += step)); + ddgiX.SetSize(XMFLOAT2(40, itemheight)); + ddgiX.OnInputAccepted([=](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + auto grid_dimensions = scene.ddgi.grid_dimensions; + grid_dimensions.x = (uint32_t)args.iValue; + scene.ddgi = {}; // reset ddgi + scene.ddgi.grid_dimensions = grid_dimensions; + }); + AddWidget(&ddgiX); + + ddgiY.Create(""); + ddgiY.SetTooltip("Probe count in Y dimension."); + ddgiY.SetPos(XMFLOAT2(x + 45, y)); + ddgiY.SetSize(XMFLOAT2(40, itemheight)); + ddgiY.OnInputAccepted([=](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + auto grid_dimensions = scene.ddgi.grid_dimensions; + grid_dimensions.y = (uint32_t)args.iValue; + scene.ddgi = {}; // reset ddgi + scene.ddgi.grid_dimensions = grid_dimensions; + }); + AddWidget(&ddgiY); + + ddgiZ.Create(""); + ddgiZ.SetTooltip("Probe count in Z dimension."); + ddgiZ.SetPos(XMFLOAT2(x + 45 * 2, y)); + ddgiZ.SetSize(XMFLOAT2(40, itemheight)); + ddgiZ.OnInputAccepted([=](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + auto grid_dimensions = scene.ddgi.grid_dimensions; + grid_dimensions.z = (uint32_t)args.iValue; + scene.ddgi = {}; // reset ddgi + scene.ddgi.grid_dimensions = grid_dimensions; + }); + AddWidget(&ddgiZ); + voxelRadianceCheckBox.Create("Voxel GI: "); voxelRadianceCheckBox.SetTooltip("Toggle voxel Global Illumination computation."); voxelRadianceCheckBox.SetPos(XMFLOAT2(x, y += step)); @@ -865,3 +905,15 @@ void RendererWindow::UpdateSwapChainFormats(wi::graphics::SwapChain* swapChain) assert(success); }); } + +void RendererWindow::Update() +{ + if (IsCollapsed()) + return; + + const wi::scene::Scene& scene = editor->GetCurrentScene(); + + ddgiX.SetValue(std::to_string(scene.ddgi.grid_dimensions.x)); + ddgiY.SetValue(std::to_string(scene.ddgi.grid_dimensions.y)); + ddgiZ.SetValue(std::to_string(scene.ddgi.grid_dimensions.z)); +} diff --git a/Editor/RendererWindow.h b/Editor/RendererWindow.h index 3ca245e9e..5e304f0e7 100644 --- a/Editor/RendererWindow.h +++ b/Editor/RendererWindow.h @@ -35,6 +35,9 @@ public: wi::gui::ComboBox surfelGIDebugComboBox; wi::gui::CheckBox ddgiCheckBox; wi::gui::CheckBox ddgiDebugCheckBox; + wi::gui::TextInputField ddgiX; + wi::gui::TextInputField ddgiY; + wi::gui::TextInputField ddgiZ; wi::gui::Slider ddgiRayCountSlider; wi::gui::CheckBox voxelRadianceCheckBox; wi::gui::CheckBox voxelRadianceDebugCheckBox; @@ -89,5 +92,6 @@ public: uint32_t GetPickType() const; void UpdateSwapChainFormats(wi::graphics::SwapChain* swapChain); + void Update(); }; diff --git a/WickedEngine/ArchiveVersionHistory.txt b/WickedEngine/ArchiveVersionHistory.txt index 49059e020..34a660ce7 100644 --- a/WickedEngine/ArchiveVersionHistory.txt +++ b/WickedEngine/ArchiveVersionHistory.txt @@ -1,5 +1,6 @@ This file contains changelog of wi::Archive versions +85: DDGI serialization 84: component library serialization 83: physical light units 82: serialized LightComponent::fov_inner diff --git a/WickedEngine/shaders/ShaderInterop_DDGI.h b/WickedEngine/shaders/ShaderInterop_DDGI.h index 82acfa95c..2bc27c824 100644 --- a/WickedEngine/shaders/ShaderInterop_DDGI.h +++ b/WickedEngine/shaders/ShaderInterop_DDGI.h @@ -3,17 +3,11 @@ #include "ShaderInterop.h" #include "ShaderInterop_Renderer.h" -static const uint3 DDGI_GRID_DIMENSIONS = uint3(32, 8, 32); // The scene extents will be subdivided into a grid of this resolution, each grid cell will have one probe -static const uint DDGI_PROBE_COUNT = DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y * DDGI_GRID_DIMENSIONS.z; static const uint DDGI_MAX_RAYCOUNT = 512; // affects global ray buffer size static const uint DDGI_COLOR_RESOLUTION = 8; // this should not be modified, border update code is fixed static const uint DDGI_COLOR_TEXELS = 1 + DDGI_COLOR_RESOLUTION + 1; // with border static const uint DDGI_DEPTH_RESOLUTION = 16; // this should not be modified, border update code is fixed static const uint DDGI_DEPTH_TEXELS = 1 + DDGI_DEPTH_RESOLUTION + 1; // with border -static const uint DDGI_COLOR_TEXTURE_WIDTH = DDGI_COLOR_TEXELS * DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y; -static const uint DDGI_COLOR_TEXTURE_HEIGHT = DDGI_COLOR_TEXELS * DDGI_GRID_DIMENSIONS.z; -static const uint DDGI_DEPTH_TEXTURE_WIDTH = DDGI_DEPTH_TEXELS * DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y; -static const uint DDGI_DEPTH_TEXTURE_HEIGHT = DDGI_DEPTH_TEXELS * DDGI_GRID_DIMENSIONS.z; static const float DDGI_KEEP_DISTANCE = 0.1f; // how much distance should probes keep from surfaces #define DDGI_LINEAR_BLENDING @@ -86,15 +80,15 @@ inline float ddgi_max_distance() inline uint3 ddgi_base_probe_coord(float3 P) { float3 normalized_pos = (P - GetScene().ddgi.grid_min) * GetScene().ddgi.grid_extents_rcp; - return floor(normalized_pos * (DDGI_GRID_DIMENSIONS - 1)); + return floor(normalized_pos * (GetScene().ddgi.grid_dimensions - 1)); } inline uint3 ddgi_probe_coord(uint probeIndex) { - return unflatten3D(probeIndex, DDGI_GRID_DIMENSIONS); + return unflatten3D(probeIndex, GetScene().ddgi.grid_dimensions); } inline uint ddgi_probe_index(uint3 probeCoord) { - return flatten3D(probeCoord, DDGI_GRID_DIMENSIONS); + return flatten3D(probeCoord, GetScene().ddgi.grid_dimensions); } inline float3 ddgi_probe_position(uint3 probeCoord) { @@ -108,23 +102,23 @@ inline float3 ddgi_probe_position(uint3 probeCoord) } inline uint2 ddgi_probe_color_pixel(uint3 probeCoord) { - return probeCoord.xz * DDGI_COLOR_TEXELS + uint2(probeCoord.y * DDGI_GRID_DIMENSIONS.x * DDGI_COLOR_TEXELS, 0) + 1; + return probeCoord.xz * DDGI_COLOR_TEXELS + uint2(probeCoord.y * GetScene().ddgi.grid_dimensions.x * DDGI_COLOR_TEXELS, 0) + 1; } inline float2 ddgi_probe_color_uv(uint3 probeCoord, float3 direction) { float2 pixel = ddgi_probe_color_pixel(probeCoord); pixel += (encode_oct(normalize(direction)) * 0.5 + 0.5) * DDGI_COLOR_RESOLUTION; - return pixel / float2(DDGI_COLOR_TEXTURE_WIDTH, DDGI_COLOR_TEXTURE_HEIGHT); + return pixel * GetScene().ddgi.color_texture_resolution_rcp; } inline uint2 ddgi_probe_depth_pixel(uint3 probeCoord) { - return probeCoord.xz * DDGI_DEPTH_TEXELS + uint2(probeCoord.y * DDGI_GRID_DIMENSIONS.x * DDGI_DEPTH_TEXELS, 0) + 1; + return probeCoord.xz * DDGI_DEPTH_TEXELS + uint2(probeCoord.y * GetScene().ddgi.grid_dimensions.x * DDGI_DEPTH_TEXELS, 0) + 1; } inline float2 ddgi_probe_depth_uv(uint3 probeCoord, float3 direction) { float2 pixel = ddgi_probe_depth_pixel(probeCoord); pixel += (encode_oct(normalize(direction)) * 0.5 + 0.5) * DDGI_DEPTH_RESOLUTION; - return pixel / float2(DDGI_DEPTH_TEXTURE_WIDTH, DDGI_DEPTH_TEXTURE_HEIGHT); + return pixel * GetScene().ddgi.depth_texture_resolution_rcp; } @@ -146,7 +140,7 @@ float3 ddgi_sample_irradiance(float3 P, float3 N) // Compute the offset grid coord and clamp to the probe grid boundary // Offset = 0 or 1 along each axis uint3 offset = uint3(i, i >> 1, i >> 2) & 1; - uint3 probe_grid_coord = clamp(base_grid_coord + offset, 0, DDGI_GRID_DIMENSIONS - 1); + uint3 probe_grid_coord = clamp(base_grid_coord + offset, 0, GetScene().ddgi.grid_dimensions - 1); //int p = ddgi_probe_index(probe_grid_coord); // Make cosine falloff in tangent plane with respect to the angle from the surface to the probe so that we never diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index fb2c4218e..f73fa73b2 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -33,6 +33,15 @@ struct ShaderScene struct DDGI { + uint3 grid_dimensions; + uint probe_count; + + uint2 color_texture_resolution; + float2 color_texture_resolution_rcp; + + uint2 depth_texture_resolution; + float2 depth_texture_resolution_rcp; + float3 grid_min; int color_texture; diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 951257a12..3ef926409 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -5,7 +5,7 @@ namespace wi { // this should always be only INCREMENTED and only if a new serialization is implemeted somewhere! - static constexpr uint64_t __archiveVersion = 84; + static constexpr uint64_t __archiveVersion = 85; // this is the version number of which below the archive is not compatible with the current version static constexpr uint64_t __archiveVersionBarrier = 22; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 6006fa589..4e2918596 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -5818,12 +5818,12 @@ void DrawDebugWorld( } - if (GetDDGIDebugEnabled() && GetDDGIEnabled()) + if (GetDDGIDebugEnabled() && scene.ddgi.color_texture[0].IsValid()) { device->EventBegin("Debug DDGI", cmd); device->BindPipelineState(&PSO_debug[DEBUGRENDERING_DDGI], cmd); - device->DrawInstanced(2880, DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y * DDGI_GRID_DIMENSIONS.z, 0, 0, cmd); // uv-sphere + device->DrawInstanced(2880, scene.shaderscene.ddgi.probe_count, 0, 0, cmd); // uv-sphere device->EventEnd(cmd); } @@ -8513,6 +8513,9 @@ void DDGI( if (!scene.TLAS.IsValid() && !scene.BVH.IsValid()) return; + if (GetDDGIRayCount() == 0) + return; + auto prof_range = wi::profiler::BeginRangeGPU("DDGI", cmd); device->EventBegin("DDGI", cmd); @@ -8520,7 +8523,7 @@ void DDGI( DDGIPushConstants push; push.instanceInclusionMask = instanceInclusionMask; - push.frameIndex = scene.ddgi_frameIndex; + push.frameIndex = scene.ddgi.frame_index; push.rayCount = std::min(GetDDGIRayCount(), DDGI_MAX_RAYCOUNT); // Raytracing: @@ -8543,11 +8546,11 @@ void DDGI( device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(MiscCB), cmd); const GPUResource* uavs[] = { - &scene.ddgiRayBuffer + &scene.ddgi.ray_buffer }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->Dispatch(DDGI_PROBE_COUNT, 1, 1, cmd); + device->Dispatch(scene.shaderscene.ddgi.probe_count, 1, 1, cmd); device->EventEnd(cmd); } @@ -8555,10 +8558,10 @@ void DDGI( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&scene.ddgiRayBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), - GPUBarrier::Image(&scene.ddgiColorTexture[1], ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), - GPUBarrier::Image(&scene.ddgiDepthTexture[1], ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), - GPUBarrier::Buffer(&scene.ddgiOffsetBuffer, ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), + GPUBarrier::Buffer(&scene.ddgi.ray_buffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), + GPUBarrier::Image(&scene.ddgi.color_texture[1], ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), + GPUBarrier::Image(&scene.ddgi.depth_texture[1], ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), + GPUBarrier::Buffer(&scene.ddgi.offset_buffer, ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8571,16 +8574,16 @@ void DDGI( device->PushConstants(&push, sizeof(push), cmd); const GPUResource* res[] = { - &scene.ddgiRayBuffer, + &scene.ddgi.ray_buffer, }; device->BindResources(res, 0, arraysize(res), cmd); const GPUResource* uavs[] = { - &scene.ddgiColorTexture[1], + &scene.ddgi.color_texture[1], }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->Dispatch(DDGI_PROBE_COUNT, 1, 1, cmd); + device->Dispatch(scene.shaderscene.ddgi.probe_count, 1, 1, cmd); device->EventEnd(cmd); } @@ -8593,26 +8596,26 @@ void DDGI( device->PushConstants(&push, sizeof(push), cmd); const GPUResource* res[] = { - &scene.ddgiRayBuffer, + &scene.ddgi.ray_buffer, }; device->BindResources(res, 0, arraysize(res), cmd); const GPUResource* uavs[] = { - &scene.ddgiDepthTexture[1], - &scene.ddgiOffsetBuffer, + &scene.ddgi.depth_texture[1], + &scene.ddgi.offset_buffer, }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->Dispatch(DDGI_PROBE_COUNT, 1, 1, cmd); + device->Dispatch(scene.shaderscene.ddgi.probe_count, 1, 1, cmd); device->EventEnd(cmd); } { GPUBarrier barriers[] = { - GPUBarrier::Image(&scene.ddgiColorTexture[1], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), - GPUBarrier::Image(&scene.ddgiDepthTexture[1], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), - GPUBarrier::Buffer(&scene.ddgiOffsetBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), + GPUBarrier::Image(&scene.ddgi.color_texture[1], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), + GPUBarrier::Image(&scene.ddgi.depth_texture[1], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), + GPUBarrier::Buffer(&scene.ddgi.offset_buffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), }; device->Barrier(barriers, arraysize(barriers), cmd); } diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 49d2f5cf1..5be1dd53c 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -1837,57 +1837,59 @@ namespace wi::scene if (wi::renderer::GetDDGIEnabled()) { - ddgi_frameIndex++; - if (!ddgiColorTexture[0].IsValid()) + ddgi.frame_index++; + if (!ddgi.color_texture[1].IsValid()) // if just color_texture[0] is valid, it could be that ddgi was serialized, that's why we check color_texture[1] here { - ddgi_frameIndex = 0; + ddgi.frame_index = 0; + + const uint32_t probe_count = ddgi.grid_dimensions.x * ddgi.grid_dimensions.y * ddgi.grid_dimensions.z; GPUBufferDesc buf; buf.stride = sizeof(DDGIRayDataPacked); - buf.size = buf.stride * DDGI_PROBE_COUNT * DDGI_MAX_RAYCOUNT; + buf.size = buf.stride * probe_count * DDGI_MAX_RAYCOUNT; buf.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; buf.misc_flags = ResourceMiscFlag::BUFFER_STRUCTURED; - device->CreateBuffer(&buf, nullptr, &ddgiRayBuffer); - device->SetName(&ddgiRayBuffer, "ddgiRayBuffer"); + device->CreateBuffer(&buf, nullptr, &ddgi.ray_buffer); + device->SetName(&ddgi.ray_buffer, "ddgi.ray_buffer"); buf.stride = sizeof(DDGIProbeOffset); - buf.size = buf.stride * DDGI_PROBE_COUNT; + buf.size = buf.stride * probe_count; buf.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; buf.misc_flags = ResourceMiscFlag::BUFFER_RAW; - device->CreateBuffer(&buf, nullptr, &ddgiOffsetBuffer); - device->SetName(&ddgiOffsetBuffer, "ddgiOffsetBuffer"); + device->CreateBuffer(&buf, nullptr, &ddgi.offset_buffer); + device->SetName(&ddgi.offset_buffer, "ddgi.offset_buffer"); TextureDesc tex; - tex.width = DDGI_COLOR_TEXTURE_WIDTH; - tex.height = DDGI_COLOR_TEXTURE_HEIGHT; + tex.width = DDGI_COLOR_TEXELS * ddgi.grid_dimensions.x * ddgi.grid_dimensions.y; + tex.height = DDGI_COLOR_TEXELS * ddgi.grid_dimensions.z; //tex.format = Format::R11G11B10_FLOAT; // not enough precision with this format, causes green hue in GI tex.format = Format::R16G16B16A16_FLOAT; tex.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; - device->CreateTexture(&tex, nullptr, &ddgiColorTexture[0]); - device->SetName(&ddgiColorTexture[0], "ddgiColorTexture[0]"); - device->CreateTexture(&tex, nullptr, &ddgiColorTexture[1]); - device->SetName(&ddgiColorTexture[1], "ddgiColorTexture[1]"); + device->CreateTexture(&tex, nullptr, &ddgi.color_texture[0]); + device->SetName(&ddgi.color_texture[0], "ddgi.color_texture[0]"); + device->CreateTexture(&tex, nullptr, &ddgi.color_texture[1]); + device->SetName(&ddgi.color_texture[1], "ddgi.color_texture[1]"); - tex.width = DDGI_DEPTH_TEXTURE_WIDTH; - tex.height = DDGI_DEPTH_TEXTURE_HEIGHT; + tex.width = DDGI_DEPTH_TEXELS * ddgi.grid_dimensions.x * ddgi.grid_dimensions.y; + tex.height = DDGI_DEPTH_TEXELS * ddgi.grid_dimensions.z; tex.format = Format::R16G16_FLOAT; tex.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; - device->CreateTexture(&tex, nullptr, &ddgiDepthTexture[0]); - device->SetName(&ddgiDepthTexture[0], "ddgiDepthTexture[0]"); - device->CreateTexture(&tex, nullptr, &ddgiDepthTexture[1]); - device->SetName(&ddgiDepthTexture[1], "ddgiDepthTexture[1]"); + device->CreateTexture(&tex, nullptr, &ddgi.depth_texture[0]); + device->SetName(&ddgi.depth_texture[0], "ddgi.depth_texture[0]"); + device->CreateTexture(&tex, nullptr, &ddgi.depth_texture[1]); + device->SetName(&ddgi.depth_texture[1], "ddgi.depth_texture[1]"); } - std::swap(ddgiColorTexture[0], ddgiColorTexture[1]); - std::swap(ddgiDepthTexture[0], ddgiDepthTexture[1]); + std::swap(ddgi.color_texture[0], ddgi.color_texture[1]); + std::swap(ddgi.depth_texture[0], ddgi.depth_texture[1]); } - else if (ddgiColorTexture[0].IsValid()) + else if (ddgi.color_texture[1].IsValid()) // if just color_texture[0] is valid, it could be that ddgi was serialized, that's why we check color_texture[1] here { - ddgiRayBuffer = {}; - ddgiOffsetBuffer = {}; - ddgiColorTexture[0] = {}; - ddgiColorTexture[1] = {}; - ddgiDepthTexture[0] = {}; - ddgiDepthTexture[1] = {}; + ddgi.ray_buffer = {}; + ddgi.offset_buffer = {}; + ddgi.color_texture[0] = {}; + ddgi.color_texture[1] = {}; + ddgi.depth_texture[0] = {}; + ddgi.depth_texture[1] = {}; } impostor_ib_format = (((objects.GetCount() * 4) < 655536) ? Format::R16_UINT : Format::R32_UINT); @@ -1999,9 +2001,15 @@ namespace wi::scene shaderscene.weather.stars = weather.stars; XMStoreFloat4x4(&shaderscene.weather.stars_rotation, XMMatrixRotationQuaternion(XMLoadFloat4(&weather.stars_rotation_quaternion))); - shaderscene.ddgi.color_texture = device->GetDescriptorIndex(&ddgiColorTexture[0], SubresourceType::SRV); - shaderscene.ddgi.depth_texture = device->GetDescriptorIndex(&ddgiDepthTexture[0], SubresourceType::SRV); - shaderscene.ddgi.offset_buffer = device->GetDescriptorIndex(&ddgiOffsetBuffer, SubresourceType::SRV); + shaderscene.ddgi.grid_dimensions = ddgi.grid_dimensions; + shaderscene.ddgi.probe_count = ddgi.grid_dimensions.x * ddgi.grid_dimensions.y * ddgi.grid_dimensions.z; + shaderscene.ddgi.color_texture_resolution = uint2(ddgi.color_texture[0].desc.width, ddgi.color_texture[0].desc.height); + shaderscene.ddgi.color_texture_resolution_rcp = float2(1.0f / shaderscene.ddgi.color_texture_resolution.x, 1.0f / shaderscene.ddgi.color_texture_resolution.y); + shaderscene.ddgi.depth_texture_resolution = uint2(ddgi.depth_texture[0].desc.width, ddgi.depth_texture[0].desc.height); + shaderscene.ddgi.depth_texture_resolution_rcp = float2(1.0f / shaderscene.ddgi.depth_texture_resolution.x, 1.0f / shaderscene.ddgi.depth_texture_resolution.y); + shaderscene.ddgi.color_texture = device->GetDescriptorIndex(&ddgi.color_texture[0], SubresourceType::SRV); + shaderscene.ddgi.depth_texture = device->GetDescriptorIndex(&ddgi.depth_texture[0], SubresourceType::SRV); + shaderscene.ddgi.offset_buffer = device->GetDescriptorIndex(&ddgi.offset_buffer, SubresourceType::SRV); shaderscene.ddgi.grid_min.x = shaderscene.aabb_min.x - 1; shaderscene.ddgi.grid_min.y = shaderscene.aabb_min.y - 1; shaderscene.ddgi.grid_min.z = shaderscene.aabb_min.z - 1; @@ -2015,9 +2023,9 @@ namespace wi::scene shaderscene.ddgi.grid_extents_rcp.x = 1.0f / shaderscene.ddgi.grid_extents.x; shaderscene.ddgi.grid_extents_rcp.y = 1.0f / shaderscene.ddgi.grid_extents.y; shaderscene.ddgi.grid_extents_rcp.z = 1.0f / shaderscene.ddgi.grid_extents.z; - shaderscene.ddgi.cell_size.x = shaderscene.ddgi.grid_extents.x / (DDGI_GRID_DIMENSIONS.x - 1); - shaderscene.ddgi.cell_size.y = shaderscene.ddgi.grid_extents.y / (DDGI_GRID_DIMENSIONS.y - 1); - shaderscene.ddgi.cell_size.z = shaderscene.ddgi.grid_extents.z / (DDGI_GRID_DIMENSIONS.z - 1); + shaderscene.ddgi.cell_size.x = shaderscene.ddgi.grid_extents.x / (ddgi.grid_dimensions.x - 1); + shaderscene.ddgi.cell_size.y = shaderscene.ddgi.grid_extents.y / (ddgi.grid_dimensions.y - 1); + shaderscene.ddgi.cell_size.z = shaderscene.ddgi.grid_extents.z / (ddgi.grid_dimensions.z - 1); shaderscene.ddgi.cell_size_rcp.x = 1.0f / shaderscene.ddgi.cell_size.x; shaderscene.ddgi.cell_size_rcp.y = 1.0f / shaderscene.ddgi.cell_size.y; shaderscene.ddgi.cell_size_rcp.z = 1.0f / shaderscene.ddgi.cell_size.z; @@ -2042,6 +2050,8 @@ namespace wi::scene surfelStatsBuffer = {}; surfelGridBuffer = {}; surfelCellBuffer = {}; + + ddgi = {}; } void Scene::Merge(Scene& other) { @@ -2051,6 +2061,11 @@ namespace wi::scene } bounds = AABB::Merge(bounds, other.bounds); + + if (!ddgi.color_texture[0].IsValid() && other.ddgi.color_texture[0].IsValid()) + { + ddgi = std::move(other.ddgi); + } } void Scene::FindAllEntities(wi::unordered_set& entities) const { diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index daa563863..51f1e9d57 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -1450,11 +1450,17 @@ namespace wi::scene wi::graphics::Texture surfelMomentsTexture[2]; // DDGI resources: - uint ddgi_frameIndex = 0; - wi::graphics::GPUBuffer ddgiRayBuffer; - wi::graphics::GPUBuffer ddgiOffsetBuffer; - wi::graphics::Texture ddgiColorTexture[2]; - wi::graphics::Texture ddgiDepthTexture[2]; + struct DDGI + { + uint frame_index = 0; + uint3 grid_dimensions = uint3(32, 8, 32); // The scene extents will be subdivided into a grid of this resolution, each grid cell will have one probe + wi::graphics::GPUBuffer ray_buffer; + wi::graphics::GPUBuffer offset_buffer; + wi::graphics::Texture color_texture[2]; + wi::graphics::Texture depth_texture[2]; + + void Serialize(wi::Archive& archive); + } ddgi; // Environment probe cubemap array state: static constexpr uint32_t envmapCount = 16; diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 70b768352..e821d2bcc 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -6,6 +6,7 @@ #include "wiBacklog.h" #include "wiTimer.h" #include "wiVector.h" +#include "shaders/ShaderInterop_DDGI.h" using namespace wi::ecs; @@ -1520,9 +1521,132 @@ namespace wi::scene } } + // Additional data serializations: + if (archive.GetVersion() >= 85) + { + ddgi.Serialize(archive); + } + wi::backlog::post("Scene serialize took " + std::to_string(timer.elapsed_seconds()) + " sec"); } + void Scene::DDGI::Serialize(wi::Archive& archive) + { + using namespace wi::graphics; + GraphicsDevice* device = GetDevice(); + + if (archive.IsReadMode()) + { + archive >> frame_index; + archive >> grid_dimensions; + + wi::vector data; + + // color texture: + { + archive >> data; + + TextureDesc desc; + desc.width = DDGI_COLOR_TEXELS * grid_dimensions.x * grid_dimensions.y; + desc.height = DDGI_COLOR_TEXELS * grid_dimensions.z; + desc.format = Format::R16G16B16A16_FLOAT; + desc.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; + + SubresourceData initdata; + initdata.data_ptr = data.data(); + initdata.row_pitch = desc.width * GetFormatStride(desc.format); + + device->CreateTexture(&desc, &initdata, &color_texture[0]); + device->SetName(&color_texture[0], "ddgi.color_texture[serialized]"); + } + + // depth texture: + { + archive >> data; + + TextureDesc desc; + desc.width = DDGI_DEPTH_TEXELS * grid_dimensions.x * grid_dimensions.y; + desc.height = DDGI_DEPTH_TEXELS * grid_dimensions.z; + desc.format = Format::R16G16_FLOAT; + desc.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; + + SubresourceData initdata; + initdata.data_ptr = data.data(); + initdata.row_pitch = desc.width * GetFormatStride(desc.format); + + device->CreateTexture(&desc, &initdata, &depth_texture[0]); + device->SetName(&depth_texture[0], "ddgi.depth_texture[seriaized]"); + } + + // offset buffer: + { + archive >> data; + + GPUBufferDesc desc; + desc.stride = sizeof(DDGIProbeOffset); + desc.size = desc.stride * grid_dimensions.x * grid_dimensions.y * grid_dimensions.z; + desc.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; + desc.misc_flags = ResourceMiscFlag::BUFFER_RAW; + device->CreateBuffer(&desc, data.data(), &offset_buffer); + device->SetName(&offset_buffer, "ddgi.offset_buffer[serialized]"); + } + } + else + { + archive << frame_index; + archive << grid_dimensions; + + wi::vector data; + bool success = wi::helper::saveTextureToMemory(color_texture[0], data); + assert(success); + archive << data; + + data.clear(); + success = wi::helper::saveTextureToMemory(depth_texture[0], data); + assert(success); + archive << data; + + // Download and serialize offset buffer: + { + GPUBufferDesc desc = offset_buffer.desc; + desc.usage = wi::graphics::Usage::READBACK; + desc.bind_flags = {}; + desc.misc_flags = {}; + GPUBuffer staging; + success = device->CreateBuffer(&desc, nullptr, &staging); + assert(success); + + CommandList cmd = device->BeginCommandList(); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&offset_buffer,ResourceState::SHADER_RESOURCE,ResourceState::COPY_SRC), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->CopyResource(&staging, &offset_buffer, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&offset_buffer,ResourceState::COPY_SRC,ResourceState::SHADER_RESOURCE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->SubmitCommandLists(); + device->WaitForGPU(); + + // serialize like vector: + archive << staging.mapped_size; + for (size_t i = 0; i < staging.mapped_size; ++i) + { + archive << ((uint8_t*)staging.mapped_data)[i]; + } + } + } + } + Entity Scene::Entity_Serialize( wi::Archive& archive, EntitySerializer& seri, diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index b0c3e9d38..0f5fc4dcd 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 = 14; + const int revision = 15; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);