From 768ad1fdcaeb977acc9a47a445144352dc43ccf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Thu, 29 Sep 2022 17:15:03 +0200 Subject: [PATCH] reduced gpu memory usage --- Editor/TerrainWindow.cpp | 1 + WickedEngine/wiGraphicsDevice_DX12.cpp | 5 + WickedEngine/wiGraphicsDevice_Vulkan.cpp | 1 + WickedEngine/wiPrimitive.cpp | 5 +- WickedEngine/wiRenderPath3D.cpp | 627 +++++++++++++++-------- WickedEngine/wiRenderPath3D.h | 17 +- WickedEngine/wiRenderer.cpp | 126 +++-- WickedEngine/wiScene.cpp | 18 +- WickedEngine/wiScene.h | 18 +- WickedEngine/wiScene_Components.h | 13 - WickedEngine/wiTerrain.cpp | 35 +- WickedEngine/wiVersion.cpp | 2 +- 12 files changed, 542 insertions(+), 326 deletions(-) diff --git a/Editor/TerrainWindow.cpp b/Editor/TerrainWindow.cpp index af578a0aa..c63a8ff95 100644 --- a/Editor/TerrainWindow.cpp +++ b/Editor/TerrainWindow.cpp @@ -283,6 +283,7 @@ void TerrainWindow::Create(EditorComponent* _editor) archive << EditorComponent::HISTORYOP_COMPONENT_DATA; editor->RecordEntity(archive, entity); + terrain->BakeVirtualTexturesToFiles(); editor->GetCurrentScene().terrains.Remove(entity); editor->RecordEntity(archive, entity); diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index 97f3a77a9..c0d587af1 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -1667,6 +1667,7 @@ using namespace dx12_internal; uploadBufferDesc.usage = Usage::UPLOAD; bool upload_success = device->CreateBuffer(&uploadBufferDesc, nullptr, &cmd.uploadbuffer); assert(upload_success); + device->SetName(&cmd.uploadbuffer, "CopyAllocator::uploadBuffer"); } // begin command list in valid state: @@ -2417,6 +2418,10 @@ using namespace dx12_internal; D3D12MA::ALLOCATOR_DESC allocatorDesc = {}; allocatorDesc.pDevice = device.Get(); allocatorDesc.pAdapter = dxgiAdapter.Get(); + //allocatorDesc.PreferredBlockSize = 256 * 1024 * 1024; + //allocatorDesc.Flags |= D3D12MA::ALLOCATOR_FLAG_ALWAYS_COMMITTED; + allocatorDesc.Flags |= D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED; + allocatorDesc.Flags |= D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED; allocationhandler = std::make_shared(); allocationhandler->device = device; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 5211e25af..764ae0031 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -1417,6 +1417,7 @@ using namespace vulkan_internal; uploaddesc.usage = Usage::UPLOAD; bool upload_success = device->CreateBuffer(&uploaddesc, nullptr, &cmd.uploadbuffer); assert(upload_success); + device->SetName(&cmd.uploadbuffer, "CopyAllocator::uploadBuffer"); } // begin command list in valid state: diff --git a/WickedEngine/wiPrimitive.cpp b/WickedEngine/wiPrimitive.cpp index 7d1e306b6..e90a89d9a 100644 --- a/WickedEngine/wiPrimitive.cpp +++ b/WickedEngine/wiPrimitive.cpp @@ -70,9 +70,10 @@ namespace wi::primitive XMFLOAT3 _max = getMax(); return (_max.x - _min.x) * (_max.y - _min.y) * (_max.z - _min.z); } - float AABB::getRadius() const { + float AABB::getRadius() const + { XMFLOAT3 abc = getHalfWidth(); - return std::max(std::max(abc.x, abc.y), abc.z); + return std::sqrt(std::pow(std::sqrt(std::pow(abc.x, 2.0f) + std::pow(abc.y, 2.0f)), 2.0f) + std::pow(abc.z, 2.0f)); } AABB::INTERSECTION_TYPE AABB::intersects(const AABB& b) const { diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index f2424ea59..2e1edc295 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -13,6 +13,76 @@ namespace wi void RenderPath3D::ResizeBuffers() { + rtMain = {}; + rtMain_render = {}; + rtPrimitiveID = {}; + rtPrimitiveID_render = {}; + rtVelocity = {}; + rtReflection = {}; + rtRaytracedDiffuse = {}; + rtSSR = {}; + rtSceneCopy = {}; + rtSceneCopy_tmp = {}; + rtWaterRipple = {}; + rtParticleDistortion = {}; + rtParticleDistortion_Resolved = {}; + rtVolumetricLights[0] = {}; + rtVolumetricLights[1] = {}; + rtBloom = {}; + rtBloom_tmp = {}; + rtAO = {}; + rtShadow = {}; + rtSun[0] = {}; + rtSun[1] = {}; + rtSun_resolved = {}; + rtGUIBlurredBackground[0] = {}; + rtGUIBlurredBackground[1] = {}; + rtGUIBlurredBackground[2] = {}; + rtShadingRate = {}; + rtFSR[0] = {}; + rtFSR[1] = {}; + rtOutlineSource = {}; + + rtPostprocess = {}; + + depthBuffer_Main = {}; + depthBuffer_Copy = {}; + depthBuffer_Copy1 = {}; + depthBuffer_Reflection = {}; + rtLinearDepth = {}; + + renderpass_depthprepass = {}; + renderpass_main = {}; + renderpass_transparent = {}; + renderpass_reflection_depthprepass = {}; + renderpass_reflection = {}; + renderpass_lightshafts = {}; + renderpass_volumetriclight = {}; + renderpass_particledistortion = {}; + renderpass_waterripples = {}; + renderpass_outline_source = {}; + + debugUAV = {}; + tiledLightResources = {}; + tiledLightResources_planarReflection = {}; + luminanceResources = {}; + ssaoResources = {}; + msaoResources = {}; + rtaoResources = {}; + rtdiffuseResources = {}; + rtreflectionResources = {}; + ssrResources = {}; + rtshadowResources = {}; + screenspaceshadowResources = {}; + depthoffieldResources = {}; + motionblurResources = {}; + volumetriccloudResources = {}; + volumetriccloudResources_reflection = {}; + bloomResources = {}; + surfelGIResources = {}; + temporalAAResources = {}; + visibilityResources = {}; + GraphicsDevice* device = wi::graphics::GetDevice(); XMUINT2 internalResolution = GetInternalResolution(); @@ -86,30 +156,10 @@ namespace wi } { TextureDesc desc; - desc.format = Format::R16G16B16A16_FLOAT; - desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.format = Format::R11G11B10_FLOAT; desc.width = internalResolution.x / 4; desc.height = internalResolution.y / 4; - device->CreateTexture(&desc, nullptr, &rtVolumetricLights[0]); - device->SetName(&rtVolumetricLights[0], "rtVolumetricLights[0]"); - device->CreateTexture(&desc, nullptr, &rtVolumetricLights[1]); - device->SetName(&rtVolumetricLights[1], "rtVolumetricLights[1]"); - } - { - TextureDesc desc; - desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; - desc.format = Format::R16G16_FLOAT; - desc.width = internalResolution.x / 8; - desc.height = internalResolution.y / 8; - device->CreateTexture(&desc, nullptr, &rtWaterRipple); - device->SetName(&rtWaterRipple, "rtWaterRipple"); - } - { - TextureDesc desc; - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS | BindFlag::RENDER_TARGET; - desc.format = Format::R11G11B10_FLOAT; - desc.width = internalResolution.x / 2; - desc.height = internalResolution.y / 2; desc.mip_levels = std::min(8u, (uint32_t)std::log2(std::max(desc.width, desc.height))); device->CreateTexture(&desc, nullptr, &rtSceneCopy); device->SetName(&rtSceneCopy, "rtSceneCopy"); @@ -130,41 +180,6 @@ namespace wi assert(subresource_index == i); } } - { - TextureDesc desc; - desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; - desc.format = Format::R11G11B10_FLOAT; - desc.width = internalResolution.x / 4; - desc.height = internalResolution.y / 4; - device->CreateTexture(&desc, nullptr, &rtReflection); - device->SetName(&rtReflection, "rtReflection"); - } - { - TextureDesc desc; - desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; - desc.format = Format::R11G11B10_FLOAT; - desc.width = internalResolution.x; - desc.height = internalResolution.y; - desc.sample_count = getMSAASampleCount(); - device->CreateTexture(&desc, nullptr, &rtSun[0]); - device->SetName(&rtSun[0], "rtSun[0]"); - - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.sample_count = 1; - desc.width = internalResolution.x / 2; - desc.height = internalResolution.y / 2; - device->CreateTexture(&desc, nullptr, &rtSun[1]); - device->SetName(&rtSun[1], "rtSun[1]"); - - if (getMSAASampleCount() > 1) - { - desc.width = internalResolution.x; - desc.height = internalResolution.y; - desc.sample_count = 1; - device->CreateTexture(&desc, nullptr, &rtSun_resolved); - device->SetName(&rtSun_resolved, "rtSun_resolved"); - } - } { TextureDesc desc; desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; @@ -206,11 +221,6 @@ namespace wi device->CreateTexture(&desc, nullptr, &rtShadingRate); device->SetName(&rtShadingRate, "rtShadingRate"); } - rtVelocity = {}; - rtAO = {}; - rtShadow = {}; - rtSSR = {}; - rtOutlineSource = {}; // Depth buffers: { @@ -248,16 +258,6 @@ namespace wi assert(subresource == i); } } - { - TextureDesc desc; - desc.bind_flags = BindFlag::DEPTH_STENCIL | BindFlag::SHADER_RESOURCE; - desc.format = Format::R32_TYPELESS; - desc.width = internalResolution.x / 4; - desc.height = internalResolution.y / 4; - desc.layout = ResourceState::DEPTHSTENCIL_READONLY; - device->CreateTexture(&desc, nullptr, &depthBuffer_Reflection); - device->SetName(&depthBuffer_Reflection, "depthBuffer_Reflection"); - } { TextureDesc desc; desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; @@ -352,79 +352,6 @@ namespace wi } device->CreateRenderPass(&desc, &renderpass_transparent); } - { - RenderPassDesc desc; - desc.attachments.push_back( - RenderPassAttachment::DepthStencil( - depthBuffer_Reflection, - RenderPassAttachment::LoadOp::CLEAR, - RenderPassAttachment::StoreOp::STORE, - ResourceState::DEPTHSTENCIL_READONLY, - ResourceState::DEPTHSTENCIL, - ResourceState::SHADER_RESOURCE - ) - ); - - device->CreateRenderPass(&desc, &renderpass_reflection_depthprepass); - } - { - RenderPassDesc desc; - desc.attachments.push_back( - RenderPassAttachment::RenderTarget( - rtReflection, - RenderPassAttachment::LoadOp::DONTCARE, - RenderPassAttachment::StoreOp::STORE, - ResourceState::SHADER_RESOURCE, - ResourceState::RENDERTARGET, - ResourceState::SHADER_RESOURCE - ) - ); - desc.attachments.push_back( - RenderPassAttachment::DepthStencil( - depthBuffer_Reflection, - RenderPassAttachment::LoadOp::LOAD, - RenderPassAttachment::StoreOp::DONTCARE, - ResourceState::SHADER_RESOURCE, - ResourceState::DEPTHSTENCIL_READONLY, - ResourceState::DEPTHSTENCIL_READONLY - ) - ); - - device->CreateRenderPass(&desc, &renderpass_reflection); - } - { - RenderPassDesc desc; - desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtSceneCopy, RenderPassAttachment::LoadOp::DONTCARE)); - - device->CreateRenderPass(&desc, &renderpass_downsamplescene); - } - { - RenderPassDesc desc; - desc.attachments.push_back( - RenderPassAttachment::DepthStencil( - depthBuffer_Main, - RenderPassAttachment::LoadOp::LOAD, - RenderPassAttachment::StoreOp::STORE, - ResourceState::DEPTHSTENCIL_READONLY, - ResourceState::DEPTHSTENCIL_READONLY, - ResourceState::DEPTHSTENCIL_READONLY - ) - ); - desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtSun[0], RenderPassAttachment::LoadOp::CLEAR)); - if (getMSAASampleCount() > 1) - { - desc.attachments.back().storeop = RenderPassAttachment::StoreOp::DONTCARE; - desc.attachments.push_back(RenderPassAttachment::Resolve(rtSun_resolved)); - } - - device->CreateRenderPass(&desc, &renderpass_lightshafts); - } - { - RenderPassDesc desc; - desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtVolumetricLights[0], RenderPassAttachment::LoadOp::CLEAR)); - - device->CreateRenderPass(&desc, &renderpass_volumetriclight); - } { RenderPassDesc desc; desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtParticleDistortion, RenderPassAttachment::LoadOp::CLEAR)); @@ -446,14 +373,6 @@ namespace wi device->CreateRenderPass(&desc, &renderpass_particledistortion); } - { - RenderPassDesc desc; - desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtWaterRipple, RenderPassAttachment::LoadOp::CLEAR)); - - device->CreateRenderPass(&desc, &renderpass_waterripples); - } - - renderpass_outline_source = {}; // Other resources: @@ -473,27 +392,22 @@ namespace wi } wi::renderer::CreateVisibilityResources(visibilityResources, internalResolution); wi::renderer::CreateTiledLightResources(tiledLightResources, internalResolution); - wi::renderer::CreateTiledLightResources(tiledLightResources_planarReflection, XMUINT2(depthBuffer_Reflection.desc.width, depthBuffer_Reflection.desc.height)); - wi::renderer::CreateLuminanceResources(luminanceResources, internalResolution); wi::renderer::CreateScreenSpaceShadowResources(screenspaceshadowResources, internalResolution); - wi::renderer::CreateDepthOfFieldResources(depthoffieldResources, internalResolution); - wi::renderer::CreateMotionBlurResources(motionblurResources, internalResolution); - wi::renderer::CreateVolumetricCloudResources(volumetriccloudResources, internalResolution); - wi::renderer::CreateVolumetricCloudResources(volumetriccloudResources_reflection, XMUINT2(depthBuffer_Reflection.desc.width, depthBuffer_Reflection.desc.height)); - wi::renderer::CreateBloomResources(bloomResources, internalResolution); - wi::renderer::CreateSurfelGIResources(surfelGIResources, internalResolution); - temporalAAResources = {}; - - if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) - { - wi::renderer::CreateRTShadowResources(rtshadowResources, internalResolution); - } + // These can trigger resource creations if needed: setAO(ao); setSSREnabled(ssrEnabled); setRaytracedReflectionsEnabled(raytracedReflectionsEnabled); setRaytracedDiffuseEnabled(raytracedDiffuseEnabled); setFSREnabled(fsrEnabled); + setMotionBlurEnabled(motionBlurEnabled); + setDepthOfFieldEnabled(depthOfFieldEnabled); + setEyeAdaptionEnabled(eyeAdaptionEnabled); + setReflectionsEnabled(reflectionsEnabled); + setBloomEnabled(bloomEnabled); + setVolumeLightsEnabled(volumeLightsEnabled); + setLightShaftsEnabled(lightShaftsEnabled); + setOutlineEnabled(outlineEnabled); RenderPath2D::ResizeBuffers(); } @@ -600,6 +514,70 @@ namespace wi rtAO = {}; } + if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) + { + if (!rtshadowResources.denoised.IsValid()) + { + wi::renderer::CreateRTShadowResources(rtshadowResources, internalResolution); + } + } + else + { + rtshadowResources = {}; + } + + if (scene->weather.IsVolumetricClouds()) + { + if (!volumetriccloudResources.texture_cloudRender.IsValid()) + { + wi::renderer::CreateVolumetricCloudResources(volumetriccloudResources, internalResolution); + } + if (getReflectionsEnabled()) + { + if (!volumetriccloudResources_reflection.texture_cloudRender.IsValid()) + { + wi::renderer::CreateVolumetricCloudResources(volumetriccloudResources_reflection, XMUINT2(depthBuffer_Reflection.desc.width, depthBuffer_Reflection.desc.height)); + } + } + else + { + volumetriccloudResources_reflection = {}; + } + } + + if (!scene->waterRipples.empty()) + { + if (!rtWaterRipple.IsValid()) + { + TextureDesc desc; + desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; + desc.format = Format::R16G16_FLOAT; + desc.width = internalResolution.x / 8; + desc.height = internalResolution.y / 8; + device->CreateTexture(&desc, nullptr, &rtWaterRipple); + device->SetName(&rtWaterRipple, "rtWaterRipple"); + { + RenderPassDesc desc; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtWaterRipple, RenderPassAttachment::LoadOp::CLEAR)); + + device->CreateRenderPass(&desc, &renderpass_waterripples); + } + } + } + else + { + rtWaterRipple = {}; + renderpass_waterripples = {}; + } + + if (wi::renderer::GetSurfelGIEnabled()) + { + if (!surfelGIResources.result.IsValid()) + { + wi::renderer::CreateSurfelGIResources(surfelGIResources, internalResolution); + } + } + // Check whether velocity buffer is required: if ( getMotionBlurEnabled() || @@ -649,33 +627,6 @@ namespace wi rtShadow = {}; } - if (getOutlineEnabled()) - { - if (!rtOutlineSource.IsValid()) - { - TextureDesc desc; - desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; - desc.format = Format::R32_FLOAT; - desc.width = internalResolution.x; - desc.height = internalResolution.y; - device->CreateTexture(&desc, nullptr, &rtOutlineSource); - device->SetName(&rtOutlineSource, "rtOutlineSource"); - } - if (!renderpass_outline_source.IsValid()) - { - RenderPassDesc desc; - desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtOutlineSource, RenderPassAttachment::LoadOp::CLEAR)); - desc.attachments.push_back(RenderPassAttachment::DepthStencil(depthBuffer_Main, RenderPassAttachment::LoadOp::LOAD)); - - device->CreateRenderPass(&desc, &renderpass_outline_source); - } - } - else - { - rtOutlineSource = {}; - renderpass_outline_source = {}; - } - // Keep a copy of last frame's depth buffer for temporal disocclusion checks, so swap with current one every frame: std::swap(depthBuffer_Copy, depthBuffer_Copy1); @@ -1458,21 +1409,7 @@ namespace wi auto range = wi::profiler::BeginRangeGPU("Scene MIP Chain", cmd); device->EventBegin("RenderSceneMIPChain", cmd); - device->RenderPassBegin(&renderpass_downsamplescene, cmd); - - Viewport vp; - vp.width = (float)rtSceneCopy.GetDesc().width; - vp.height = (float)rtSceneCopy.GetDesc().height; - device->BindViewports(1, &vp, cmd); - - wi::image::Params fx; - fx.enableFullScreen(); - fx.sampleFlag = wi::image::SAMPLEMODE_CLAMP; - fx.quality = wi::image::QUALITY_LINEAR; - fx.blendFlag = BLENDMODE_OPAQUE; - wi::image::Draw(&rtMain, fx, cmd); - - device->RenderPassEnd(cmd); + wi::renderer::Postprocess_Downsample4x(rtMain, rtSceneCopy, cmd); wi::renderer::MIPGEN_OPTIONS mipopt; mipopt.gaussian_temp = &rtSceneCopy_tmp; @@ -1486,17 +1423,17 @@ namespace wi GraphicsDevice* device = wi::graphics::GetDevice(); // Water ripple rendering: - device->RenderPassBegin(&renderpass_waterripples, cmd); // always clear the water ripple rt, because it will always be sampled, whether there were any ripples or not if (!scene->waterRipples.empty()) { + device->RenderPassBegin(&renderpass_waterripples, cmd); Viewport vp; vp.width = (float)rtWaterRipple.GetDesc().width; vp.height = (float)rtWaterRipple.GetDesc().height; device->BindViewports(1, &vp, cmd); wi::renderer::DrawWaterRipples(visibility_main, cmd); + device->RenderPassEnd(cmd); } - device->RenderPassEnd(cmd); device->RenderPassBegin(&renderpass_transparent, cmd); @@ -1771,7 +1708,6 @@ namespace wi device->CreateTexture(&desc, nullptr, &rtAO); device->SetName(&rtAO, "rtAO"); } - void RenderPath3D::setSSREnabled(bool value) { ssrEnabled = value; @@ -1799,7 +1735,6 @@ namespace wi ssrResources = {}; } } - void RenderPath3D::setRaytracedReflectionsEnabled(bool value) { raytracedReflectionsEnabled = value; @@ -1826,7 +1761,6 @@ namespace wi rtreflectionResources = {}; } } - void RenderPath3D::setRaytracedDiffuseEnabled(bool value) { raytracedDiffuseEnabled = value; @@ -1854,7 +1788,6 @@ namespace wi rtdiffuseResources = {}; } } - void RenderPath3D::setFSREnabled(bool value) { fsrEnabled = value; @@ -1881,5 +1814,269 @@ namespace wi rtFSR[1] = {}; } } + void RenderPath3D::setMotionBlurEnabled(bool value) + { + motionBlurEnabled = value; + + if (value) + { + wi::renderer::CreateMotionBlurResources(motionblurResources, GetInternalResolution()); + } + else + { + motionblurResources = {}; + } + } + void RenderPath3D::setDepthOfFieldEnabled(bool value) + { + depthOfFieldEnabled = value; + + if (value) + { + wi::renderer::CreateDepthOfFieldResources(depthoffieldResources, GetInternalResolution()); + } + else + { + depthoffieldResources = {}; + } + } + void RenderPath3D::setEyeAdaptionEnabled(bool value) + { + eyeAdaptionEnabled = value; + + if (value) + { + wi::renderer::CreateLuminanceResources(luminanceResources, GetInternalResolution()); + } + else + { + luminanceResources = {}; + } + } + void RenderPath3D::setReflectionsEnabled(bool value) + { + reflectionsEnabled = value; + + if (value) + { + GraphicsDevice* device = wi::graphics::GetDevice(); + XMUINT2 internalResolution = GetInternalResolution(); + if (internalResolution.x == 0 || internalResolution.y == 0) + return; + + TextureDesc desc; + desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; + desc.format = Format::R11G11B10_FLOAT; + desc.width = internalResolution.x / 4; + desc.height = internalResolution.y / 4; + device->CreateTexture(&desc, nullptr, &rtReflection); + device->SetName(&rtReflection, "rtReflection"); + + desc.bind_flags = BindFlag::DEPTH_STENCIL | BindFlag::SHADER_RESOURCE; + desc.format = Format::R32_TYPELESS; + desc.width = internalResolution.x / 4; + desc.height = internalResolution.y / 4; + desc.layout = ResourceState::DEPTHSTENCIL_READONLY; + device->CreateTexture(&desc, nullptr, &depthBuffer_Reflection); + device->SetName(&depthBuffer_Reflection, "depthBuffer_Reflection"); + + { + RenderPassDesc desc; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + depthBuffer_Reflection, + RenderPassAttachment::LoadOp::CLEAR, + RenderPassAttachment::StoreOp::STORE, + ResourceState::DEPTHSTENCIL_READONLY, + ResourceState::DEPTHSTENCIL, + ResourceState::SHADER_RESOURCE + ) + ); + + device->CreateRenderPass(&desc, &renderpass_reflection_depthprepass); + } + { + RenderPassDesc desc; + desc.attachments.push_back( + RenderPassAttachment::RenderTarget( + rtReflection, + RenderPassAttachment::LoadOp::DONTCARE, + RenderPassAttachment::StoreOp::STORE, + ResourceState::SHADER_RESOURCE, + ResourceState::RENDERTARGET, + ResourceState::SHADER_RESOURCE + ) + ); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + depthBuffer_Reflection, + RenderPassAttachment::LoadOp::LOAD, + RenderPassAttachment::StoreOp::DONTCARE, + ResourceState::SHADER_RESOURCE, + ResourceState::DEPTHSTENCIL_READONLY, + ResourceState::DEPTHSTENCIL_READONLY + ) + ); + + device->CreateRenderPass(&desc, &renderpass_reflection); + } + + wi::renderer::CreateTiledLightResources(tiledLightResources_planarReflection, XMUINT2(depthBuffer_Reflection.desc.width, depthBuffer_Reflection.desc.height)); + } + else + { + rtReflection = {}; + depthBuffer_Reflection = {}; + renderpass_reflection_depthprepass = {}; + renderpass_reflection = {}; + tiledLightResources_planarReflection = {}; + } + } + void RenderPath3D::setBloomEnabled(bool value) + { + bloomEnabled = value; + + if (value) + { + wi::renderer::CreateBloomResources(bloomResources, GetInternalResolution()); + } + else + { + bloomResources = {}; + } + } + void RenderPath3D::setVolumeLightsEnabled(bool value) + { + volumeLightsEnabled = value; + + if (value) + { + GraphicsDevice* device = wi::graphics::GetDevice(); + XMUINT2 internalResolution = GetInternalResolution(); + if (internalResolution.x == 0 || internalResolution.y == 0) + return; + + TextureDesc desc; + desc.format = Format::R16G16B16A16_FLOAT; + desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.width = internalResolution.x / 4; + desc.height = internalResolution.y / 4; + device->CreateTexture(&desc, nullptr, &rtVolumetricLights[0]); + device->SetName(&rtVolumetricLights[0], "rtVolumetricLights[0]"); + device->CreateTexture(&desc, nullptr, &rtVolumetricLights[1]); + device->SetName(&rtVolumetricLights[1], "rtVolumetricLights[1]"); + { + RenderPassDesc desc; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtVolumetricLights[0], RenderPassAttachment::LoadOp::CLEAR)); + + device->CreateRenderPass(&desc, &renderpass_volumetriclight); + } + } + else + { + rtVolumetricLights[0] = {}; + rtVolumetricLights[1] = {}; + renderpass_volumetriclight = {}; + } + } + void RenderPath3D::setLightShaftsEnabled(bool value) + { + lightShaftsEnabled = value; + + if (value) + { + GraphicsDevice* device = wi::graphics::GetDevice(); + XMUINT2 internalResolution = GetInternalResolution(); + if (internalResolution.x == 0 || internalResolution.y == 0) + return; + + TextureDesc desc; + desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; + desc.format = Format::R11G11B10_FLOAT; + desc.width = internalResolution.x; + desc.height = internalResolution.y; + desc.sample_count = getMSAASampleCount(); + device->CreateTexture(&desc, nullptr, &rtSun[0]); + device->SetName(&rtSun[0], "rtSun[0]"); + + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.sample_count = 1; + desc.width = internalResolution.x / 2; + desc.height = internalResolution.y / 2; + device->CreateTexture(&desc, nullptr, &rtSun[1]); + device->SetName(&rtSun[1], "rtSun[1]"); + + if (getMSAASampleCount() > 1) + { + desc.width = internalResolution.x; + desc.height = internalResolution.y; + desc.sample_count = 1; + device->CreateTexture(&desc, nullptr, &rtSun_resolved); + device->SetName(&rtSun_resolved, "rtSun_resolved"); + } + + { + RenderPassDesc desc; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + depthBuffer_Main, + RenderPassAttachment::LoadOp::LOAD, + RenderPassAttachment::StoreOp::STORE, + ResourceState::DEPTHSTENCIL_READONLY, + ResourceState::DEPTHSTENCIL_READONLY, + ResourceState::DEPTHSTENCIL_READONLY + ) + ); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtSun[0], RenderPassAttachment::LoadOp::CLEAR)); + if (getMSAASampleCount() > 1) + { + desc.attachments.back().storeop = RenderPassAttachment::StoreOp::DONTCARE; + desc.attachments.push_back(RenderPassAttachment::Resolve(rtSun_resolved)); + } + + device->CreateRenderPass(&desc, &renderpass_lightshafts); + } + } + else + { + rtSun[0] = {}; + rtSun[1] = {}; + rtSun_resolved = {}; + renderpass_lightshafts = {}; + } + } + void RenderPath3D::setOutlineEnabled(bool value) + { + outlineEnabled = value; + + if (value) + { + GraphicsDevice* device = wi::graphics::GetDevice(); + XMUINT2 internalResolution = GetInternalResolution(); + if (internalResolution.x == 0 || internalResolution.y == 0) + return; + + TextureDesc desc; + desc.bind_flags = BindFlag::RENDER_TARGET | BindFlag::SHADER_RESOURCE; + desc.format = Format::R32_FLOAT; + desc.width = internalResolution.x; + desc.height = internalResolution.y; + device->CreateTexture(&desc, nullptr, &rtOutlineSource); + device->SetName(&rtOutlineSource, "rtOutlineSource"); + + { + RenderPassDesc desc; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtOutlineSource, RenderPassAttachment::LoadOp::CLEAR)); + desc.attachments.push_back(RenderPassAttachment::DepthStencil(depthBuffer_Main, RenderPassAttachment::LoadOp::LOAD)); + + device->CreateRenderPass(&desc, &renderpass_outline_source); + } + } + else + { + rtOutlineSource = {}; + renderpass_outline_source = {}; + } + } } diff --git a/WickedEngine/wiRenderPath3D.h b/WickedEngine/wiRenderPath3D.h index 93d9ed35c..99c67ecfa 100644 --- a/WickedEngine/wiRenderPath3D.h +++ b/WickedEngine/wiRenderPath3D.h @@ -111,7 +111,6 @@ namespace wi wi::graphics::RenderPass renderpass_transparent; wi::graphics::RenderPass renderpass_reflection_depthprepass; wi::graphics::RenderPass renderpass_reflection; - wi::graphics::RenderPass renderpass_downsamplescene; wi::graphics::RenderPass renderpass_lightshafts; wi::graphics::RenderPass renderpass_volumetriclight; wi::graphics::RenderPass renderpass_particledistortion; @@ -261,19 +260,19 @@ namespace wi void setSSREnabled(bool value); void setRaytracedReflectionsEnabled(bool value); void setRaytracedDiffuseEnabled(bool value); + void setMotionBlurEnabled(bool value); + void setDepthOfFieldEnabled(bool value); + void setEyeAdaptionEnabled(bool value); + void setReflectionsEnabled(bool value); + void setBloomEnabled(bool value); + void setVolumeLightsEnabled(bool value); + void setLightShaftsEnabled(bool value); + void setOutlineEnabled(bool value); constexpr void setShadowsEnabled(bool value) { shadowsEnabled = value; } - constexpr void setReflectionsEnabled(bool value) { reflectionsEnabled = value; } constexpr void setFXAAEnabled(bool value) { fxaaEnabled = value; } - constexpr void setBloomEnabled(bool value) { bloomEnabled = value; } constexpr void setColorGradingEnabled(bool value) { colorGradingEnabled = value; } - constexpr void setVolumeLightsEnabled(bool value) { volumeLightsEnabled = value; } - constexpr void setLightShaftsEnabled(bool value) { lightShaftsEnabled = value; } constexpr void setLensFlareEnabled(bool value) { lensFlareEnabled = value; } - constexpr void setMotionBlurEnabled(bool value) { motionBlurEnabled = value; } - constexpr void setDepthOfFieldEnabled(bool value) { depthOfFieldEnabled = value; } - constexpr void setEyeAdaptionEnabled(bool value) { eyeAdaptionEnabled = value; } constexpr void setSharpenFilterEnabled(bool value) { sharpenFilterEnabled = value; } - constexpr void setOutlineEnabled(bool value) { outlineEnabled = value; } constexpr void setChromaticAberrationEnabled(bool value) { chromaticAberrationEnabled = value; } constexpr void setDitherEnabled(bool value) { ditherEnabled = value; } constexpr void setOcclusionCullingEnabled(bool value) { occlusionCullingEnabled = value; } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 42a52835d..7fe393be5 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1771,61 +1771,6 @@ void LoadBuffers() device->SetName(&textures[TEXTYPE_2D_SHEENLUT], "textures[TEXTYPE_2D_SHEENLUT]"); } - { - TextureDesc desc; - desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = 512; - desc.height = 512; - desc.format = Format::R11G11B10_FLOAT; - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; - device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW]); - device->SetName(&textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW], "textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW]"); - } - { - TextureDesc desc; - desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = 256; - desc.height = 64; - desc.format = Format::R16G16B16A16_FLOAT; - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; - device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT]); - device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT]"); - } - { - TextureDesc desc; - desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = 32; - desc.height = 32; - desc.format = Format::R16G16B16A16_FLOAT; - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; - device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT]); - device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT]"); - } - { - TextureDesc desc; - desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = 192; - desc.height = 104; - desc.format = Format::R16G16B16A16_FLOAT; - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; - device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT]); - device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT]"); - } - { - TextureDesc desc; - desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = 1; - desc.height = 1; - desc.format = Format::R16G16B16A16_FLOAT; - desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; - device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT]); - device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT]"); - } { // the dummy buffer is read-only so only the first 'exposure' value is needed, // not the luminance or histogram values in the full version of the buffer used @@ -2877,16 +2822,17 @@ void UpdateVisibility(Visibility& vis) if (vis.flags & Visibility::ALLOW_OCCLUSION_CULLING) { - if (object.IsRenderable() && object.occlusionQueries[vis.scene->queryheap_idx] < 0) + Scene::OcclusionResult& occlusion_result = vis.scene->occlusion_results_objects[args.jobIndex]; + if (object.IsRenderable() && occlusion_result.occlusionQueries[vis.scene->queryheap_idx] < 0) { if (aabb.intersects(vis.camera->Eye)) { // camera is inside the instance, mark it as visible in this frame: - object.occlusionHistory |= 1; + occlusion_result.occlusionHistory |= 1; } else { - object.occlusionQueries[vis.scene->queryheap_idx] = vis.scene->queryAllocator.fetch_add(1); // allocate new occlusion query from heap + occlusion_result.occlusionQueries[vis.scene->queryheap_idx] = vis.scene->queryAllocator.fetch_add(1); // allocate new occlusion query from heap } } } @@ -3213,6 +3159,19 @@ void UpdatePerFrameData( // Calculate volumetric cloud shadow data: if (vis.scene->weather.IsVolumetricClouds() && vis.scene->weather.IsVolumetricCloudsShadows()) { + if (!textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW].IsValid()) + { + TextureDesc desc; + desc.type = TextureDesc::Type::TEXTURE_2D; + desc.width = 512; + desc.height = 512; + desc.format = Format::R11G11B10_FLOAT; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; + device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW]); + device->SetName(&textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW], "textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW]"); + } + const float cloudShadowSnapLength = 5000.0f; const float cloudShadowExtent = 35000.0f; // The cloud shadow bounding box size const float cloudShadowNearPlane = 0.0f; @@ -3249,6 +3208,46 @@ void UpdatePerFrameData( frameCB.texture_volumetricclouds_shadow_index = device->GetDescriptorIndex(&textures[TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW], SubresourceType::SRV); } + if (scene.weather.IsRealisticSky() && !textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT].IsValid()) + { + TextureDesc desc; + desc.type = TextureDesc::Type::TEXTURE_2D; + desc.width = 256; + desc.height = 64; + desc.format = Format::R16G16B16A16_FLOAT; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; + device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT]); + device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT]"); + + desc.type = TextureDesc::Type::TEXTURE_2D; + desc.width = 32; + desc.height = 32; + desc.format = Format::R16G16B16A16_FLOAT; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; + device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT]); + device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT]"); + + desc.type = TextureDesc::Type::TEXTURE_2D; + desc.width = 192; + desc.height = 104; + desc.format = Format::R16G16B16A16_FLOAT; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; + device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT]); + device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT]"); + + desc.type = TextureDesc::Type::TEXTURE_2D; + desc.width = 1; + desc.height = 1; + desc.format = Format::R16G16B16A16_FLOAT; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; + device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT]); + device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT]"); + } + // Update CPU-side frame constant buffer: frameCB.delta_time = dt * GetGameSpeed(); frameCB.time_previous = frameCB.time; @@ -3400,7 +3399,6 @@ void UpdatePerFrameData( frameCB.shadow_atlas_resolution_rcp.x = 1.0f / frameCB.shadow_atlas_resolution.x; frameCB.shadow_atlas_resolution_rcp.y = 1.0f / frameCB.shadow_atlas_resolution.y; - // Create volumetric cloud static resources if needed: if (scene.weather.IsVolumetricClouds() && !texture_shapeNoise.IsValid()) { @@ -3461,6 +3459,7 @@ void UpdatePerFrameData( texture_desc.format = Format::R8G8B8A8_UNORM; device->CreateTexture(&texture_desc, nullptr, &texture_weatherMap); device->SetName(&texture_weatherMap, "texture_weatherMap"); + } } void UpdateRenderData( @@ -4377,9 +4376,9 @@ void OcclusionCulling_Render(const CameraComponent& camera, const Visibility& vi for (uint32_t instanceIndex : vis.visibleObjects) { - const ObjectComponent& object = vis.scene->objects[instanceIndex]; + const Scene::OcclusionResult& occlusion_result = vis.scene->occlusion_results_objects[instanceIndex]; - int queryIndex = object.occlusionQueries[query_write]; + int queryIndex = occlusion_result.occlusionQueries[query_write]; if (queryIndex >= 0) { const AABB& aabb = vis.scene->aabb_objects[instanceIndex]; @@ -5132,11 +5131,10 @@ void DrawScene( renderQueue.init(); for (uint32_t instanceIndex : vis.visibleObjects) { - const ObjectComponent& object = vis.scene->objects[instanceIndex]; - - if (occlusion && object.IsOccluded()) + if (occlusion && vis.scene->occlusion_results_objects[instanceIndex].IsOccluded()) continue; + const ObjectComponent& object = vis.scene->objects[instanceIndex]; if (object.IsRenderable() && (object.GetFilterMask() & filterMask)) { const float distance = wi::math::Distance(vis.camera->Eye, object.center); diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 449c5f9a6..9ec30177c 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -125,7 +125,11 @@ namespace wi::scene // Occlusion culling read: if(wi::renderer::GetOcclusionCullingEnabled() && !wi::renderer::GetFreezeCullingCameraEnabled()) { - uint32_t minQueryCount = uint32_t(objects.GetCount() + lights.GetCount() + 1); // +1 : ocean + uint32_t minQueryCount = uint32_t(objects.GetCount() + lights.GetCount()); + if (weather.IsOceanEnabled()) + { + minQueryCount += 1; + } if (queryHeap.desc.query_count < minQueryCount) { GPUQueryHeapDesc desc; @@ -3108,6 +3112,7 @@ namespace wi::scene aabb_objects.resize(objects.GetCount()); matrix_objects.resize(objects.GetCount()); matrix_objects_prev.resize(objects.GetCount()); + occlusion_results_objects.resize(objects.GetCount()); meshletAllocator.store(0u); @@ -3121,24 +3126,25 @@ namespace wi::scene AABB& aabb = aabb_objects[args.jobIndex]; // Update occlusion culling status: + OcclusionResult& occlusion_result = occlusion_results_objects[args.jobIndex]; if (!wi::renderer::GetFreezeCullingCameraEnabled()) { - object.occlusionHistory <<= 1u; // advance history by 1 frame - int query_id = object.occlusionQueries[queryheap_idx]; + occlusion_result.occlusionHistory <<= 1u; // advance history by 1 frame + int query_id = occlusion_result.occlusionQueries[queryheap_idx]; if (queryResultBuffer[queryheap_idx].mapped_data != nullptr && query_id >= 0) { uint64_t visible = ((uint64_t*)queryResultBuffer[queryheap_idx].mapped_data)[query_id]; if (visible) { - object.occlusionHistory |= 1; // visible + occlusion_result.occlusionHistory |= 1; // visible } } else { - object.occlusionHistory |= 1; // visible + occlusion_result.occlusionHistory |= 1; // visible } } - object.occlusionQueries[queryheap_idx] = -1; // invalidate query + occlusion_result.occlusionQueries[queryheap_idx] = -1; // invalidate query const LayerComponent* layer = layers.GetComponent(entity); uint32_t layerMask; diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 78177145e..18c05d0a2 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -123,8 +123,24 @@ namespace wi::scene std::atomic meshletAllocator{ 0 }; // Occlusion query state: + struct OcclusionResult + { + int occlusionQueries[wi::graphics::GraphicsDevice::GetBufferCount() + 1]; + // occlusion result history bitfield (32 bit->32 frame history) + uint32_t occlusionHistory = ~0u; + + constexpr bool IsOccluded() const + { + // Perform a conservative occlusion test: + // If it is visible in any frames in the history, it is determined visible in this frame + // But if all queries failed in the history, it is occluded. + // If it pops up for a frame after occluded, it is visible again for some frames + return occlusionHistory == 0; + } + }; + mutable wi::vector occlusion_results_objects; wi::graphics::GPUQueryHeap queryHeap; - wi::graphics::GPUBuffer queryResultBuffer[arraysize(ObjectComponent::occlusionQueries)]; + wi::graphics::GPUBuffer queryResultBuffer[arraysize(OcclusionResult::occlusionQueries)]; wi::graphics::GPUBuffer queryPredicationBuffer; int queryheap_idx = 0; mutable std::atomic queryAllocator{ 0 }; diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 92310d26c..251a90fde 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -668,19 +668,6 @@ namespace wi::scene // these will only be valid for a single frame: uint32_t mesh_index = ~0u; - // occlusion result history bitfield (32 bit->32 frame history) - mutable uint32_t occlusionHistory = ~0u; - mutable int occlusionQueries[wi::graphics::GraphicsDevice::GetBufferCount() + 1]; - - inline bool IsOccluded() const - { - // Perform a conservative occlusion test: - // If it is visible in any frames in the history, it is determined visible in this frame - // But if all queries failed in the history, it is occluded. - // If it pops up for a frame after occluded, it is visible again for some frames - return occlusionHistory == 0; - } - inline void SetRenderable(bool value) { if (value) { _flags |= RENDERABLE; } else { _flags &= ~RENDERABLE; } } inline void SetCastShadow(bool value) { if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } } inline void SetDynamic(bool value) { if (value) { _flags |= DYNAMIC; } else { _flags &= ~DYNAMIC; } } diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index be4d4796b..9289af5b5 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -342,6 +342,7 @@ namespace wi::terrain { const Chunk& chunk = it->first; ChunkData& chunk_data = it->second; + const bool chunk_visible = camera.frustum.CheckSphere(chunk_data.sphere.center, chunk_data.sphere.radius); const int dist = std::max(std::abs(center_chunk.x - chunk.x), std::abs(center_chunk.z - chunk.z)); // pointer refresh: @@ -443,24 +444,30 @@ namespace wi::terrain // Collect virtual texture update requests: if (virtual_texture_any) { - uint32_t texture_lod = 0; - const float distsq = wi::math::DistanceSquared(camera.Eye, chunk_data.sphere.center); - const float radius = chunk_data.sphere.radius; - const float radiussq = radius * radius; - if (distsq < radiussq) + if (chunk_visible) { - texture_lod = 0; + uint32_t texture_lod = 0; + const float distsq = wi::math::DistanceSquared(camera.Eye, chunk_data.sphere.center); + const float radius = chunk_data.sphere.radius; + const float radiussq = radius * radius; + if (distsq < radiussq) + { + texture_lod = 0; + } + else + { + const float dist = std::sqrt(distsq); + const float dist_to_sphere = dist - radius; + texture_lod = uint32_t(dist_to_sphere * texlodMultiplier); + } + chunk_data.required_texture_resolution = uint32_t(target_texture_resolution / std::pow(2.0f, (float)std::max(0u, texture_lod))); + chunk_data.required_texture_resolution = AlignTo(chunk_data.required_texture_resolution, 8u); + chunk_data.required_texture_resolution = std::max(8u, chunk_data.required_texture_resolution); } else { - const float dist = std::sqrt(distsq); - const float dist_to_sphere = dist - radius; - texture_lod = uint32_t(dist_to_sphere * texlodMultiplier); + chunk_data.required_texture_resolution = 8u; } - - chunk_data.required_texture_resolution = uint32_t(target_texture_resolution / std::pow(2.0f, (float)std::max(0u, texture_lod))); - chunk_data.required_texture_resolution = AlignTo(chunk_data.required_texture_resolution, 8u); - chunk_data.required_texture_resolution = std::max(8u, chunk_data.required_texture_resolution); MaterialComponent* material = scene->materials.GetComponent(chunk_data.entity); if (material != nullptr) @@ -1160,8 +1167,6 @@ namespace wi::terrain } else { - BakeVirtualTexturesToFiles(); - archive << _flags; archive << lod_multiplier; archive << texlod; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 18ddf7cb2..b55eee883 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 = 59; + const int revision = 60; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);