diff --git a/Editor/EmitterWindow.cpp b/Editor/EmitterWindow.cpp index f426253eb..ba0354b22 100644 --- a/Editor/EmitterWindow.cpp +++ b/Editor/EmitterWindow.cpp @@ -753,7 +753,7 @@ void EmitterWindow::UpdateData() std::string ss; ss += "Emitter Mesh: " + (meshName != nullptr ? meshName->name : "NO EMITTER MESH") + " (" + std::to_string(emitter->meshID) + ")\n"; - ss += "Memort Budget: " + std::to_string(emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f) + " MB\n"; + ss += "Memory usage: " + std::to_string(emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f) + " MB\n"; ss += "\n"; auto data = emitter->GetStatistics(); diff --git a/Editor/HairParticleWindow.cpp b/Editor/HairParticleWindow.cpp index 37a1d9614..48151fd71 100644 --- a/Editor/HairParticleWindow.cpp +++ b/Editor/HairParticleWindow.cpp @@ -9,7 +9,7 @@ void HairParticleWindow::Create(EditorComponent* _editor) { editor = _editor; wi::gui::Window::Create(ICON_HAIR " Hair Particle System", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE); - SetSize(XMFLOAT2(600, 260)); + SetSize(XMFLOAT2(600, 350)); closeButton.SetTooltip("Delete HairParticleSystem"); OnClose([=](wi::gui::EventArgs args) { @@ -31,6 +31,10 @@ void HairParticleWindow::Create(EditorComponent* _editor) float step = hei + 2; float wid = 150; + infoLabel.Create(""); + infoLabel.SetSize(XMFLOAT2(wid, 80)); + AddWidget(&infoLabel); + meshComboBox.Create("Mesh: "); meshComboBox.SetSize(XMFLOAT2(wid, hei)); meshComboBox.SetPos(XMFLOAT2(x, y)); @@ -265,14 +269,19 @@ wi::HairParticleSystem* HairParticleWindow::GetHair() void HairParticleWindow::UpdateData() { - auto emitter = GetHair(); - if (emitter == nullptr) + auto hair = GetHair(); + if (hair == nullptr) { return; } Scene& scene = editor->GetCurrentScene(); + std::string ss; + ss += "To use hair particle system, first you must select a surface mesh to spawn particles on.\n\n"; + ss += "Memory usage: " + std::to_string(hair->GetMemorySizeInBytes() / 1024.0f / 1024.0f) + " MB\n"; + infoLabel.SetText(ss); + meshComboBox.ClearItems(); meshComboBox.AddItem("NO MESH"); for (size_t i = 0; i < scene.meshes.GetCount(); ++i) @@ -281,7 +290,7 @@ void HairParticleWindow::UpdateData() const NameComponent& name = *scene.names.GetComponent(entity); meshComboBox.AddItem(name.name); - if (emitter->meshID == entity) + if (hair->meshID == entity) { meshComboBox.SetSelected((int)i + 1); } @@ -325,6 +334,7 @@ void HairParticleWindow::ResizeLayout() y += padding; }; + add_fullwidth(infoLabel); add(meshComboBox); add(lengthSlider); add(stiffnessSlider); diff --git a/Editor/HairParticleWindow.h b/Editor/HairParticleWindow.h index 62e31fdcc..96ea7a365 100644 --- a/Editor/HairParticleWindow.h +++ b/Editor/HairParticleWindow.h @@ -18,6 +18,7 @@ public: wi::HairParticleSystem* GetHair(); + wi::gui::Label infoLabel; wi::gui::ComboBox meshComboBox; wi::gui::Slider lengthSlider; wi::gui::Slider stiffnessSlider; diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index 64764c8c9..b4f17f149 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -680,9 +680,6 @@ void PaintToolWindow::Update(float dt) P = P * MUL + ADD; P = P * SCREEN; - if (selected.subsetIndex >= 0 && mesh->vertex_subsets[j] != selected.subsetIndex) - continue; - const float z = XMVectorGetZ(P); const float dist = XMVectorGetX(XMVector2Length(C - P)); if (z >= 0 && z <= 1 && dist <= pressure_radius) @@ -727,8 +724,6 @@ void PaintToolWindow::Update(float dt) mesh->indices[j + 1], mesh->indices[j + 2], }; - if (selected.subsetIndex >= 0 && (mesh->vertex_subsets[triangle[0]] != selected.subsetIndex || mesh->vertex_subsets[triangle[1]] != selected.subsetIndex || mesh->vertex_subsets[triangle[2]] != selected.subsetIndex)) - continue; const XMVECTOR P[arraysize(triangle)] = { XMVector3Transform(armature == nullptr ? XMLoadFloat3(&mesh->vertex_positions[triangle[0]]) : wi::scene::SkinVertex(*mesh, *armature, triangle[0]), W), diff --git a/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl b/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl index 03921cc12..777973563 100644 --- a/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl +++ b/WickedEngine/shaders/terrainVirtualTextureUpdateCS.hlsl @@ -7,7 +7,7 @@ struct Terrain { ShaderMaterial materials[region_count]; }; -ConstantBuffer terrain : register(b10); +ConstantBuffer terrain : register(b0); // These are expected to be in the same bind slots as corresponding MaterialComponent::TEXTURESLOT enums RWTexture2D output_baseColorMap : register(u0); diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index f106f8603..375858ff4 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -61,6 +61,8 @@ namespace wi if (particleBuffer.desc.size < MAX_PARTICLES * sizeof(Particle)) { + BLAS = {}; + GPUBufferDesc bd; bd.usage = Usage::DEFAULT; bd.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; @@ -253,6 +255,12 @@ namespace wi } } + } + + void EmittedParticleSystem::CreateRaytracingRenderData() + { + GraphicsDevice* device = wi::graphics::GetDevice(); + if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING) && !BLAS.IsValid() && primitiveBuffer.IsValid()) { RaytracingAccelerationStructureDesc desc; @@ -276,7 +284,6 @@ namespace wi assert(success); device->SetName(&BLAS, "EmittedParticleSystem::BLAS"); } - } uint64_t EmittedParticleSystem::GetMemorySizeInBytes() const diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h index 87e8eef2f..7be29ab37 100644 --- a/WickedEngine/wiEmittedParticle.h +++ b/WickedEngine/wiEmittedParticle.h @@ -69,6 +69,8 @@ namespace wi void UpdateGPU(uint32_t instanceIndex, const wi::scene::TransformComponent& transform, const wi::scene::MeshComponent* mesh, wi::graphics::CommandList cmd) const; void Draw(const wi::scene::MaterialComponent& material, wi::graphics::CommandList cmd) const; + void CreateRaytracingRenderData(); + ParticleCounters GetStatistics() { return statistics; } enum FLAGS diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index 7604dd7ff..c842dbd70 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -31,10 +31,32 @@ namespace wi static PipelineState PSO[RENDERPASS_COUNT]; static PipelineState PSO_wire; + uint64_t HairParticleSystem::GetMemorySizeInBytes() const + { + if (!simulationBuffer.IsValid()) + return 0; + + uint64_t retVal = 0; + + retVal += simulationBuffer.GetDesc().size; + retVal += constantBuffer.GetDesc().size; + retVal += vertexBuffer_POS[0].GetDesc().size; + retVal += vertexBuffer_POS[1].GetDesc().size; + retVal += vertexBuffer_UVS.GetDesc().size; + retVal += primitiveBuffer.GetDesc().size; + retVal += culledIndexBuffer.GetDesc().size; + retVal += indirectBuffer.GetDesc().size; + retVal += indexBuffer.GetDesc().size; + retVal += vertexBuffer_length.GetDesc().size; + + return retVal; + } + void HairParticleSystem::CreateRenderData(const wi::scene::MeshComponent& mesh) { GraphicsDevice* device = wi::graphics::GetDevice(); + BLAS = {}; _flags &= ~REBUILD_BUFFERS; regenerate_frame = true; @@ -166,6 +188,19 @@ namespace wi device->SetName(&indexBuffer, "HairParticleSystem::indexBuffer"); } + if (!indirectBuffer.IsValid()) + { + GPUBufferDesc desc; + desc.size = sizeof(uint) + sizeof(IndirectDrawArgsIndexedInstanced); // counter + draw args + desc.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; + desc.bind_flags = BindFlag::UNORDERED_ACCESS; + device->CreateBuffer(&desc, nullptr, &indirectBuffer); + } + } + void HairParticleSystem::CreateRaytracingRenderData() + { + GraphicsDevice* device = wi::graphics::GetDevice(); + if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING) && primitiveBuffer.IsValid()) { RaytracingAccelerationStructureDesc desc; @@ -189,15 +224,6 @@ namespace wi assert(success); device->SetName(&BLAS, "HairParticleSystem::BLAS"); } - - if (!indirectBuffer.IsValid()) - { - GPUBufferDesc desc; - desc.size = sizeof(uint) + sizeof(IndirectDrawArgsIndexedInstanced); // counter + draw args - desc.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; - desc.bind_flags = BindFlag::UNORDERED_ACCESS; - device->CreateBuffer(&desc, nullptr, &indirectBuffer); - } } void HairParticleSystem::UpdateCPU(const TransformComponent& transform, const MeshComponent& mesh, float dt) diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index 80235fffd..9e7c3e7d0 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -32,6 +32,7 @@ namespace wi wi::graphics::RaytracingAccelerationStructure BLAS; void CreateRenderData(const wi::scene::MeshComponent& mesh); + void CreateRaytracingRenderData(); void UpdateCPU( const wi::scene::TransformComponent& transform, @@ -88,5 +89,6 @@ namespace wi static void Initialize(); constexpr uint32_t GetParticleCount() const { return strandCount * segmentCount; } + uint64_t GetMemorySizeInBytes() const; }; } diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 2e1edc295..cccefe458 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -11,7 +11,7 @@ using namespace wi::enums; namespace wi { - void RenderPath3D::ResizeBuffers() + void RenderPath3D::DeleteGPUResources() { rtMain = {}; rtMain_render = {}; @@ -82,6 +82,11 @@ namespace wi surfelGIResources = {}; temporalAAResources = {}; visibilityResources = {}; + } + + void RenderPath3D::ResizeBuffers() + { + DeleteGPUResources(); GraphicsDevice* device = wi::graphics::GetDevice(); @@ -532,7 +537,7 @@ namespace wi { wi::renderer::CreateVolumetricCloudResources(volumetriccloudResources, internalResolution); } - if (getReflectionsEnabled()) + if (getReflectionsEnabled() && depthBuffer_Reflection.IsValid()) { if (!volumetriccloudResources_reflection.texture_cloudRender.IsValid()) { @@ -1239,6 +1244,16 @@ namespace wi RenderPath2D::Compose(cmd); } + void RenderPath3D::Stop() + { + DeleteGPUResources(); + } + + void RenderPath3D::Start() + { + ResizeBuffers(); + } + void RenderPath3D::RenderAO(CommandList cmd) const { diff --git a/WickedEngine/wiRenderPath3D.h b/WickedEngine/wiRenderPath3D.h index 99c67ecfa..0ab485945 100644 --- a/WickedEngine/wiRenderPath3D.h +++ b/WickedEngine/wiRenderPath3D.h @@ -154,6 +154,7 @@ namespace wi virtual void RenderTransparents(wi::graphics::CommandList cmd) const; virtual void RenderPostprocessChain(wi::graphics::CommandList cmd) const; + void DeleteGPUResources(); void ResizeBuffers() override; wi::scene::CameraComponent* camera = &wi::scene::GetCamera(); @@ -285,6 +286,9 @@ namespace wi void Update(float dt) override; void Render() const override; void Compose(wi::graphics::CommandList cmd) const override; + + void Stop() override; + void Start() override; }; } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 5bf443c09..57ed1ea50 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -2463,6 +2463,9 @@ void RenderMeshes( if (instancedBatch.instanceCount == 0) return; const MeshComponent& mesh = vis.scene->meshes[instancedBatch.meshIndex]; + if (!mesh.generalBuffer.IsValid()) + return; + const bool forceAlphaTestForDithering = instancedBatch.forceAlphatestForDithering != 0; const uint8_t userStencilRefOverride = instancedBatch.userStencilRefOverride; diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 92ea747e0..f07adfa53 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -106,7 +106,7 @@ namespace wi::scene materialArrayMapped = (ShaderMaterial*)materialUploadBuffer[device->GetBufferIndex()].mapped_data; TLAS_instancesMapped = nullptr; - if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) + if (IsAccelerationStructureUpdateRequested() && device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) { GPUBufferDesc desc; desc.stride = (uint32_t)device->GetTopLevelAccelerationStructureInstanceSize(); @@ -170,10 +170,13 @@ namespace wi::scene mesh.geometryOffset = geometryAllocator.fetch_add((uint32_t)mesh.subsets.size()); }); - wi::jobsystem::Execute(ctx, [&](wi::jobsystem::JobArgs args) { - // Must not keep inactive TLAS instances, so zero them out for safety: - std::memset(TLAS_instancesMapped, 0, TLAS_instancesUpload->desc.size); - }); + if (TLAS_instancesMapped != nullptr) + { + wi::jobsystem::Execute(ctx, [&](wi::jobsystem::JobArgs args) { + // Must not keep inactive TLAS instances, so zero them out for safety: + std::memset(TLAS_instancesMapped, 0, TLAS_instancesUpload->desc.size); + }); + } wi::jobsystem::Execute(ctx, [&](wi::jobsystem::JobArgs args) { // Must not keep inactive instances, so init them for safety: @@ -287,31 +290,34 @@ namespace wi::scene SetAccelerationStructureUpdateRequested(true); } - if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) + if (IsAccelerationStructureUpdateRequested()) { - // Recreate top level acceleration structure if the object count changed: - if (TLAS.desc.top_level.count < instanceArraySize) + if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) { - RaytracingAccelerationStructureDesc desc; - desc.flags = RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; - desc.type = RaytracingAccelerationStructureDesc::Type::TOPLEVEL; - desc.top_level.count = (uint32_t)instanceArraySize * 2; // *2 to grow fast - GPUBufferDesc bufdesc; - bufdesc.misc_flags |= ResourceMiscFlag::RAY_TRACING; - bufdesc.stride = (uint32_t)device->GetTopLevelAccelerationStructureInstanceSize(); - bufdesc.size = bufdesc.stride * desc.top_level.count; - bool success = device->CreateBuffer(&bufdesc, nullptr, &desc.top_level.instance_buffer); - assert(success); - device->SetName(&desc.top_level.instance_buffer, "Scene::TLAS.instanceBuffer"); - success = device->CreateRaytracingAccelerationStructure(&desc, &TLAS); - assert(success); - device->SetName(&TLAS, "Scene::TLAS"); + // Recreate top level acceleration structure if the object count changed: + if (TLAS.desc.top_level.count < instanceArraySize) + { + RaytracingAccelerationStructureDesc desc; + desc.flags = RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; + desc.type = RaytracingAccelerationStructureDesc::Type::TOPLEVEL; + desc.top_level.count = (uint32_t)instanceArraySize * 2; // *2 to grow fast + GPUBufferDesc bufdesc; + bufdesc.misc_flags |= ResourceMiscFlag::RAY_TRACING; + bufdesc.stride = (uint32_t)device->GetTopLevelAccelerationStructureInstanceSize(); + bufdesc.size = bufdesc.stride * desc.top_level.count; + bool success = device->CreateBuffer(&bufdesc, nullptr, &desc.top_level.instance_buffer); + assert(success); + device->SetName(&desc.top_level.instance_buffer, "Scene::TLAS.instanceBuffer"); + success = device->CreateRaytracingAccelerationStructure(&desc, &TLAS); + assert(success); + device->SetName(&TLAS, "Scene::TLAS"); + } + } + else + { + // Software GPU BVH: + BVH.Update(*this); } - } - - if (!device->CheckCapability(GraphicsDeviceCapability::RAYTRACING) && IsAccelerationStructureUpdateRequested()) - { - BVH.Update(*this); } // Update water ripples: @@ -2743,6 +2749,12 @@ namespace wi::scene mesh._flags &= ~MeshComponent::TLAS_FORCE_DOUBLE_SIDED; + if (!mesh.morph_targets.empty() && mesh.vertex_positions_morphed.size() != mesh.vertex_positions.size()) + { + mesh.vertex_positions_morphed.resize(mesh.vertex_positions.size()); + mesh.dirty_morph = true; + } + // Update morph targets if needed: if (mesh.dirty_morph && !mesh.morph_targets.empty()) { @@ -2869,8 +2881,13 @@ namespace wi::scene subsetIndex++; } - if (!mesh.BLASes.empty() && mesh.BLASes[0].IsValid()) + if (TLAS_instancesMapped != nullptr) // check TLAS, to know if we need to care about BLAS { + if (mesh.BLASes.empty() || !mesh.BLASes[0].IsValid()) + { + mesh.CreateRaytracingRenderData(); + } + const uint32_t lod_count = mesh.GetLODCount(); assert(uint32_t(mesh.BLASes.size()) == lod_count); for (uint32_t lod = 0; lod < lod_count; ++lod) @@ -3808,8 +3825,13 @@ namespace wi::scene const size_t instanceIndex = objects.GetCount() + args.jobIndex; std::memcpy(instanceArrayMapped + instanceIndex, &inst, sizeof(inst)); - if (TLAS_instancesMapped != nullptr && hair.BLAS.IsValid()) + if (TLAS_instancesMapped != nullptr) { + if (!hair.BLAS.IsValid()) + { + hair.CreateRaytracingRenderData(); + } + // TLAS instance data: RaytracingAccelerationStructureDesc::TopLevel::Instance instance; for (int i = 0; i < arraysize(instance.transform); ++i) @@ -3899,8 +3921,13 @@ namespace wi::scene const size_t instanceIndex = objects.GetCount() + hairs.GetCount() + args.jobIndex; std::memcpy(instanceArrayMapped + instanceIndex, &inst, sizeof(inst)); - if (TLAS_instancesMapped != nullptr && emitter.BLAS.IsValid()) + if (TLAS_instancesMapped != nullptr) { + if (!emitter.BLAS.IsValid()) + { + emitter.CreateRaytracingRenderData(); + } + // TLAS instance data: RaytracingAccelerationStructureDesc::TopLevel::Instance instance; for (int i = 0; i < arraysize(instance.transform); ++i) diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp index c1c089e13..87a7d5a36 100644 --- a/WickedEngine/wiScene_Components.cpp +++ b/WickedEngine/wiScene_Components.cpp @@ -382,10 +382,8 @@ namespace wi::scene return wi::renderer::CombineStencilrefs(engineStencilRef, userStencilRef); } - void MeshComponent::CreateRenderData() + void MeshComponent::DeleteRenderData() { - GraphicsDevice* device = wi::graphics::GetDevice(); - generalBuffer = {}; streamoutBuffer = {}; ib = {}; @@ -398,6 +396,13 @@ namespace wi::scene so_pos_nor_wind = {}; so_tan = {}; so_pre = {}; + BLASes.clear(); + } + void MeshComponent::CreateRenderData() + { + DeleteRenderData(); + + GraphicsDevice* device = wi::graphics::GetDevice(); if (vertex_tangents.empty() && !vertex_uvset_0.empty() && !vertex_normals.empty()) { @@ -477,22 +482,6 @@ namespace wi::scene } } - { - vertex_subsets.resize(vertex_positions.size()); - uint32_t first_subset = 0; - uint32_t last_subset = 0; - GetLODSubsetRange(0, first_subset, last_subset); - for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) - { - const MeshComponent::MeshSubset& subset = subsets[subsetIndex]; - for (uint32_t i = 0; i < subset.indexCount; ++i) - { - uint32_t index = indices[subset.indexOffset + i]; - vertex_subsets[index] = subsetIndex; - } - } - } - const size_t uv_count = std::max(vertex_uvset_0.size(), vertex_uvset_1.size()); GPUBufferDesc bd; @@ -547,12 +536,6 @@ namespace wi::scene // vertexBuffer - POSITION + NORMAL + WIND: { - if (!morph_targets.empty()) - { - vertex_positions_morphed.resize(vertex_positions.size()); - dirty_morph = true; - } - vb_pos_nor_wind.offset = buffer_offset; vb_pos_nor_wind.size = vertex_positions.size() * sizeof(Vertex_POS); Vertex_POS* vertices = (Vertex_POS*)(buffer_data.data() + buffer_offset); @@ -691,53 +674,6 @@ namespace wi::scene vb_bon.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_bon.offset, vb_bon.size); vb_bon.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_bon.subresource_srv); } - - if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) - { - BLAS_state = MeshComponent::BLAS_STATE_NEEDS_REBUILD; - - const uint32_t lod_count = GetLODCount(); - BLASes.resize(lod_count); - for (uint32_t lod = 0; lod < lod_count; ++lod) - { - RaytracingAccelerationStructureDesc desc; - desc.type = RaytracingAccelerationStructureDesc::Type::BOTTOMLEVEL; - - if (streamoutBuffer.IsValid()) - { - desc.flags |= RaytracingAccelerationStructureDesc::FLAG_ALLOW_UPDATE; - desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; - } - else - { - desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_TRACE; - } - - uint32_t first_subset = 0; - uint32_t last_subset = 0; - GetLODSubsetRange(lod, first_subset, last_subset); - for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) - { - const MeshComponent::MeshSubset& subset = subsets[subsetIndex]; - desc.bottom_level.geometries.emplace_back(); - auto& geometry = desc.bottom_level.geometries.back(); - geometry.type = RaytracingAccelerationStructureDesc::BottomLevel::Geometry::Type::TRIANGLES; - geometry.triangles.vertex_buffer = generalBuffer; - geometry.triangles.vertex_byte_offset = vb_pos_nor_wind.offset; - geometry.triangles.index_buffer = generalBuffer; - geometry.triangles.index_format = GetIndexFormat(); - geometry.triangles.index_count = subset.indexCount; - geometry.triangles.index_offset = ib.offset / GetIndexStride() + subset.indexOffset; - geometry.triangles.vertex_count = (uint32_t)vertex_positions.size(); - geometry.triangles.vertex_format = Format::R32G32B32_FLOAT; - geometry.triangles.vertex_stride = sizeof(MeshComponent::Vertex_POS); - } - - bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLASes[lod]); - assert(success); - device->SetName(&BLASes[lod], std::string("MeshComponent::BLAS[LOD" + std::to_string(lod) + "]").c_str()); - } - } } void MeshComponent::CreateStreamoutRenderData() { @@ -790,6 +726,57 @@ namespace wi::scene so_pre.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_pre.subresource_srv); so_pre.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_pre.subresource_uav); } + void MeshComponent::CreateRaytracingRenderData() + { + GraphicsDevice* device = wi::graphics::GetDevice(); + + if (!device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) + return; + + BLAS_state = MeshComponent::BLAS_STATE_NEEDS_REBUILD; + + const uint32_t lod_count = GetLODCount(); + BLASes.resize(lod_count); + for (uint32_t lod = 0; lod < lod_count; ++lod) + { + RaytracingAccelerationStructureDesc desc; + desc.type = RaytracingAccelerationStructureDesc::Type::BOTTOMLEVEL; + + if (streamoutBuffer.IsValid()) + { + desc.flags |= RaytracingAccelerationStructureDesc::FLAG_ALLOW_UPDATE; + desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; + } + else + { + desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_TRACE; + } + + uint32_t first_subset = 0; + uint32_t last_subset = 0; + GetLODSubsetRange(lod, first_subset, last_subset); + for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) + { + const MeshComponent::MeshSubset& subset = subsets[subsetIndex]; + desc.bottom_level.geometries.emplace_back(); + auto& geometry = desc.bottom_level.geometries.back(); + geometry.type = RaytracingAccelerationStructureDesc::BottomLevel::Geometry::Type::TRIANGLES; + geometry.triangles.vertex_buffer = generalBuffer; + geometry.triangles.vertex_byte_offset = vb_pos_nor_wind.offset; + geometry.triangles.index_buffer = generalBuffer; + geometry.triangles.index_format = GetIndexFormat(); + geometry.triangles.index_count = subset.indexCount; + geometry.triangles.index_offset = ib.offset / GetIndexStride() + subset.indexOffset; + geometry.triangles.vertex_count = (uint32_t)vertex_positions.size(); + geometry.triangles.vertex_format = Format::R32G32B32_FLOAT; + geometry.triangles.vertex_stride = sizeof(MeshComponent::Vertex_POS); + } + + bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLASes[lod]); + assert(success); + device->SetName(&BLASes[lod], std::string("MeshComponent::BLAS[LOD" + std::to_string(lod) + "]").c_str()); + } + } void MeshComponent::ComputeNormals(COMPUTE_NORMALS compute) { // Start recalculating normals: diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 251a90fde..20ee5462e 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -394,7 +394,6 @@ namespace wi::scene BufferView so_pos_nor_wind; BufferView so_tan; BufferView so_pre; - wi::vector vertex_subsets; uint32_t geometryOffset = 0; uint32_t meshletCount = 0; @@ -434,9 +433,13 @@ namespace wi::scene } } + // Deletes all GPU resources + void DeleteRenderData(); + // Recreates GPU resources for index/vertex buffers void CreateRenderData(); void CreateStreamoutRenderData(); + void CreateRaytracingRenderData(); enum COMPUTE_NORMALS { diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index e833195d8..bb38b8350 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -345,11 +345,36 @@ namespace wi::terrain 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)); + if (wi::renderer::GetOcclusionCullingEnabled()) + { + size_t object_index = scene->objects.GetIndex(chunk_data.entity); + if (object_index < scene->occlusion_results_objects.size()) + { + if (scene->occlusion_results_objects[object_index].IsOccluded()) + { + chunk_visible = false; + } + } + } + // pointer refresh: MeshComponent* chunk_mesh = scene->meshes.GetComponent(chunk_data.entity); if (chunk_mesh != nullptr) { chunk_data.mesh_vertex_positions = chunk_mesh->vertex_positions.data(); + +#if 0 + // Test: remove off screen chunks + // But the problem is that shadow casters shouldn't be removed outside view + if (chunk_visible && !chunk_mesh->generalBuffer.IsValid()) + { + chunk_mesh->CreateRenderData(); + } + else if (!chunk_visible && chunk_mesh->generalBuffer.IsValid()) + { + chunk_mesh->DeleteRenderData(); + } +#endif } else { @@ -383,18 +408,6 @@ namespace wi::terrain } } - if (wi::renderer::GetOcclusionCullingEnabled()) - { - size_t object_index = scene->objects.GetIndex(chunk_data.entity); - if (object_index < scene->occlusion_results_objects.size()) - { - if (scene->occlusion_results_objects[object_index].IsOccluded()) - { - chunk_visible = false; - } - } - } - // Grass property update: if (chunk_visible && chunk_data.grass_entity != INVALID_ENTITY) { @@ -540,7 +553,7 @@ namespace wi::terrain material_Slope.WriteShaderMaterial(&materials[1]); material_LowAltitude.WriteShaderMaterial(&materials[2]); material_HighAltitude.WriteShaderMaterial(&materials[3]); - device->BindDynamicConstantBuffer(materials, 10, cmd); + device->BindDynamicConstantBuffer(materials, 0, cmd); for (auto& chunk : virtual_texture_updates) { diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 26ae22fdc..f3af20a0f 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 = 64; + const int revision = 65; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);