diff --git a/WickedEngine/wiGPUBVH.cpp b/WickedEngine/wiGPUBVH.cpp index e5ec2d4cb..4a38ea0a4 100644 --- a/WickedEngine/wiGPUBVH.cpp +++ b/WickedEngine/wiGPUBVH.cpp @@ -158,13 +158,16 @@ namespace wi { const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - for (size_t j = 0; j < mesh.subsets.size(); ++j) + uint32_t first_subset = 0; + uint32_t last_subset = 0; + mesh.GetLODSubsetRange(object.lod, first_subset, last_subset); + for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { - auto& subset = mesh.subsets[j]; + const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; BVHPushConstants push; push.instanceIndex = (uint)i; - push.subsetIndex = (uint)j; + push.subsetIndex = subsetIndex; push.primitiveCount = subset.indexCount / 3; push.primitiveOffset = primitiveCount; device->PushConstants(&push, sizeof(push), cmd); diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 18738f285..6481ae56c 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -6364,6 +6364,8 @@ using namespace vulkan_internal; float blendConstants[] = { 1,1,1,1 }; vkCmdSetBlendConstants(commandlist.GetCommandBuffer(), blendConstants); + vkCmdSetStencilReference(commandlist.GetCommandBuffer(), VK_STENCIL_FRONT_AND_BACK, ~0u); + if (features2.features.depthBounds == VK_TRUE) { vkCmdSetDepthBounds(commandlist.GetCommandBuffer(), 0.0f, 1.0f); diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 21af243ad..596106077 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -514,13 +514,14 @@ void RenderPath3D::Update(float dt) RenderPath2D::Update(dt); + const bool hw_raytrace = device->CheckCapability(GraphicsDeviceCapability::RAYTRACING); if (getSceneUpdateEnabled()) { if (wi::renderer::GetSurfelGIEnabled() || wi::renderer::GetDDGIEnabled() || - wi::renderer::GetRaytracedShadowsEnabled() || - getAO() == AO_RTAO || - getRaytracedReflectionEnabled()) + (hw_raytrace && wi::renderer::GetRaytracedShadowsEnabled()) || + (hw_raytrace && getAO() == AO_RTAO) || + (hw_raytrace && getRaytracedReflectionEnabled())) { scene->SetAccelerationStructureUpdateRequested(true); } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 294e974bb..8483be2be 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -4253,22 +4253,25 @@ void UpdateRaytracingAccelerationStructures(const Scene& scene, CommandList cmd) for (size_t i = 0; i < scene.meshes.GetCount(); ++i) { const MeshComponent& mesh = scene.meshes[i]; - if (mesh.BLAS.IsValid()) + for (auto& BLAS : mesh.BLASes) { - switch (mesh.BLAS_state) + if (BLAS.IsValid()) { - default: - case MeshComponent::BLAS_STATE_COMPLETE: - break; - case MeshComponent::BLAS_STATE_NEEDS_REBUILD: - device->BuildRaytracingAccelerationStructure(&mesh.BLAS, cmd, nullptr); - break; - case MeshComponent::BLAS_STATE_NEEDS_REFIT: - device->BuildRaytracingAccelerationStructure(&mesh.BLAS, cmd, &mesh.BLAS); - break; + switch (mesh.BLAS_state) + { + default: + case MeshComponent::BLAS_STATE_COMPLETE: + break; + case MeshComponent::BLAS_STATE_NEEDS_REBUILD: + device->BuildRaytracingAccelerationStructure(&BLAS, cmd, nullptr); + break; + case MeshComponent::BLAS_STATE_NEEDS_REFIT: + device->BuildRaytracingAccelerationStructure(&BLAS, cmd, &BLAS); + break; + } } - mesh.BLAS_state = MeshComponent::BLAS_STATE_COMPLETE; } + mesh.BLAS_state = MeshComponent::BLAS_STATE_COMPLETE; } for (size_t i = 0; i < scene.hairs.GetCount(); ++i) diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index fd775d8f8..4d8afa032 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -699,42 +699,47 @@ namespace wi::scene { BLAS_state = MeshComponent::BLAS_STATE_NEEDS_REBUILD; - RaytracingAccelerationStructureDesc desc; - desc.type = RaytracingAccelerationStructureDesc::Type::BOTTOMLEVEL; - - if (streamoutBuffer.IsValid()) + const uint32_t lod_count = GetLODCount(); + BLASes.resize(lod_count); + for (uint32_t lod = 0; lod < lod_count; ++lod) { - desc.flags |= RaytracingAccelerationStructureDesc::FLAG_ALLOW_UPDATE; - desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; - } - else - { - desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_TRACE; - } + RaytracingAccelerationStructureDesc desc; + desc.type = RaytracingAccelerationStructureDesc::Type::BOTTOMLEVEL; - 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]; - 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); - } + if (streamoutBuffer.IsValid()) + { + desc.flags |= RaytracingAccelerationStructureDesc::FLAG_ALLOW_UPDATE; + desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; + } + else + { + desc.flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_TRACE; + } - bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLAS); - assert(success); - device->SetName(&BLAS, "MeshComponent::BLAS"); + 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() @@ -4223,12 +4228,39 @@ namespace wi::scene if (material != nullptr) { subset.materialIndex = (uint32_t)materials.GetIndex(subset.materialID); - const uint32_t lod_index = mesh.subsets_per_lod > 0 ? subsetIndex / mesh.subsets_per_lod : 0; - if (lod_index == 0 && mesh.BLAS.IsValid()) + } + else + { + subset.materialIndex = 0; + } + + geometry.indexOffset = subset.indexOffset; + geometry.materialIndex = subset.materialIndex; + geometry.meshletOffset = mesh.meshletCount; + geometry.meshletCount = triangle_count_to_meshlet_count(subset.indexCount / 3u); + mesh.meshletCount += geometry.meshletCount; + std::memcpy(geometryArrayMapped + mesh.geometryOffset + subsetIndex, &geometry, sizeof(geometry)); + subsetIndex++; + } + + if (!mesh.BLASes.empty() && mesh.BLASes[0].IsValid()) + { + const uint32_t lod_count = mesh.GetLODCount(); + assert(uint32_t(mesh.BLASes.size()) == lod_count); + for (uint32_t lod = 0; lod < lod_count; ++lod) + { + uint32_t first_subset = 0; + uint32_t last_subset = 0; + mesh.GetLODSubsetRange(lod, first_subset, last_subset); + for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { - auto& geometry = mesh.BLAS.desc.bottom_level.geometries[subsetIndex]; + const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; + const MaterialComponent& material = materials[subset.materialIndex]; + + const uint32_t geometry_index = subsetIndex - first_subset; + auto& geometry = mesh.BLASes[lod].desc.bottom_level.geometries[geometry_index]; uint32_t flags = geometry.flags; - if (material->IsAlphaTestEnabled() || (material->GetRenderTypes() & RENDERTYPE_TRANSPARENT) || !material->IsCastingShadow()) + if (material.IsAlphaTestEnabled() || (material.GetRenderTypes() & RENDERTYPE_TRANSPARENT) || !material.IsCastingShadow()) { geometry.flags &= ~RaytracingAccelerationStructureDesc::BottomLevel::Geometry::FLAG_OPAQUE; } @@ -4246,24 +4278,12 @@ namespace wi::scene geometry.triangles.vertex_buffer = mesh.streamoutBuffer; geometry.triangles.vertex_byte_offset = mesh.so_pos_nor_wind.offset; } - if (material->IsDoubleSided()) + if (material.IsDoubleSided()) { mesh._flags |= MeshComponent::TLAS_FORCE_DOUBLE_SIDED; } } } - else - { - subset.materialIndex = 0; - } - - geometry.indexOffset = subset.indexOffset; - geometry.materialIndex = subset.materialIndex; - geometry.meshletOffset = mesh.meshletCount; - geometry.meshletCount = triangle_count_to_meshlet_count(subset.indexCount / 3u); - mesh.meshletCount += geometry.meshletCount; - std::memcpy(geometryArrayMapped + mesh.geometryOffset + subsetIndex, &geometry, sizeof(geometry)); - subsetIndex++; } }); @@ -4633,6 +4653,28 @@ namespace wi::scene std::memcpy(instanceArrayMapped + args.jobIndex, &inst, sizeof(inst)); // memcpy whole structure into mapped pointer to avoid read from uncached memory + // LOD select: + { + const float distsq = wi::math::DistanceSquared(camera.Eye, object.center); + const float radius = object.radius; + const float radiussq = radius * radius; + if (distsq < radiussq) + { + object.lod = 0; + } + else + { + const MeshComponent* mesh = meshes.GetComponent(object.meshID); + if (mesh != nullptr && mesh->subsets_per_lod > 0) + { + const float dist = std::sqrt(distsq); + const float dist_to_sphere = dist - radius; + object.lod = uint32_t(dist_to_sphere * object.lod_distance_multiplier); + object.lod = std::min(object.lod, mesh->GetLODCount() - 1); + } + } + } + if (TLAS_instancesMapped != nullptr) { // TLAS instance data: @@ -4646,7 +4688,7 @@ namespace wi::scene } instance.instance_id = args.jobIndex; instance.instance_mask = layerMask & 0xFF; - instance.bottom_level = &mesh.BLAS; + instance.bottom_level = &mesh.BLASes[object.lod]; instance.instance_contribution_to_hit_group_index = 0; instance.flags = 0; @@ -4706,28 +4748,6 @@ namespace wi::scene wi::texturehelper::CreateTexture(object.lightmap, object.lightmapTextureData.data(), object.lightmapWidth, object.lightmapHeight, object.lightmap.desc.format); device->SetName(&object.lightmap, "lightmap"); } - - // LOD select: - { - const float distsq = wi::math::DistanceSquared(camera.Eye, object.center); - const float radius = object.radius; - const float radiussq = radius * radius; - if (distsq < radiussq) - { - object.lod = 0; - } - else - { - const MeshComponent* mesh = meshes.GetComponent(object.meshID); - if (mesh != nullptr && mesh->subsets_per_lod > 0) - { - const float dist = std::sqrt(distsq); - const float dist_to_sphere = dist - radius; - object.lod = uint32_t(dist_to_sphere * object.lod_distance_multiplier); - object.lod = std::min(object.lod, mesh->GetLODCount() - 1); - } - } - } } aabb.layerMask = layerMask; diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 23e0ce2d7..475261444 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -411,7 +411,7 @@ namespace wi::scene uint32_t geometryOffset = 0; uint32_t meshletCount = 0; - wi::graphics::RaytracingAccelerationStructure BLAS; + wi::vector BLASes; // one BLAS per LOD enum BLAS_STATE { BLAS_STATE_NEEDS_REBUILD, diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index b0ba96cb1..a84989454 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 = 32; + const int revision = 33; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);