Raytracing LOD support (#547)

* raytracing LOD support

* software raytracing LOD

* update LOD before TLAS write

* version bump
This commit is contained in:
Turánszki János
2022-08-31 11:28:42 +02:00
committed by GitHub
parent 6d031729f7
commit 1450b4b059
7 changed files with 122 additions and 93 deletions
+6 -3
View File
@@ -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);
+2
View File
@@ -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);
+4 -3
View File
@@ -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);
}
+15 -12
View File
@@ -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)
+93 -73
View File
@@ -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;
+1 -1
View File
@@ -411,7 +411,7 @@ namespace wi::scene
uint32_t geometryOffset = 0;
uint32_t meshletCount = 0;
wi::graphics::RaytracingAccelerationStructure BLAS;
wi::vector<wi::graphics::RaytracingAccelerationStructure> BLASes; // one BLAS per LOD
enum BLAS_STATE
{
BLAS_STATE_NEEDS_REBUILD,
+1 -1
View File
@@ -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);