Fix crash when building the accel struct for scenes with no level mesh

This commit is contained in:
Magnus Norddahl 2025-01-27 21:21:14 +01:00
commit 0d976d35c5
6 changed files with 19 additions and 17 deletions

View file

@ -360,10 +360,11 @@ void VkDescriptorSetManager::CreateFixedPool()
if (fb->IsRayQueryEnabled())
{
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * MaxFixedSets);
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 5 * MaxFixedSets);
}
else
{
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 * MaxFixedSets);
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6 * MaxFixedSets);
}
poolbuilder.MaxSets(MaxFixedSets);
poolbuilder.DebugName("VkDescriptorSetManager.Fixed.Pool");

View file

@ -35,15 +35,10 @@ VkLevelMesh::VkLevelMesh(VulkanRenderDevice* fb) : fb(fb)
{
useRayQuery = fb->IsRayQueryEnabled();
CreateViewerObjects();
SetLevelMesh(nullptr);
}
void VkLevelMesh::SetLevelMesh(LevelMesh* mesh)
{
if (!mesh)
mesh = &NullMesh;
Mesh = mesh;
CreateVulkanObjects();
}
@ -88,7 +83,7 @@ void VkLevelMesh::CreateVulkanObjects()
// Wait for uploads to finish
PipelineBarrier()
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
// Find out how many segments we should split the map into
DynamicBLAS.resize(32); // fb->GetDevice()->PhysicalDevice.Properties.AccelerationStructure.maxInstanceCount is 65 or 382 on current devices (aug 2024)
@ -116,14 +111,14 @@ void VkLevelMesh::CreateVulkanObjects()
// Finish building the accel struct before using it from the shaders
PipelineBarrier()
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
else
{
// Uploads must finish before we can read from the shaders
PipelineBarrier()
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
}
@ -153,7 +148,7 @@ void VkLevelMesh::BeginFrame()
// Wait for uploads to finish
PipelineBarrier()
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
if (accelStructNeedsUpdate)
{
@ -192,14 +187,14 @@ void VkLevelMesh::BeginFrame()
// Finish building the accel struct before using it from the shaders
PipelineBarrier()
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
else
{
// Uploads must finish before we can read from the shaders
PipelineBarrier()
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
WriteDescriptors write;

View file

@ -126,7 +126,6 @@ private:
bool useRayQuery = true;
LevelMesh NullMesh;
LevelMesh* Mesh = nullptr;
std::unique_ptr<VulkanBuffer> VertexBuffer;

View file

@ -73,8 +73,7 @@ void VkLightmapper::ReleaseResources()
void VkLightmapper::SetLevelMesh(LevelMesh* level)
{
mesh = level;
if (mesh)
UpdateAccelStructDescriptors();
UpdateAccelStructDescriptors();
lightmapRaytraceLast.Reset();
lastPixelCount = 0;

View file

@ -227,6 +227,9 @@ void VulkanRenderDevice::InitializeState()
uniformblockalignment = (unsigned int)mDevice->PhysicalDevice.Properties.Properties.limits.minUniformBufferOffsetAlignment;
maxuniformblock = std::min(mDevice->PhysicalDevice.Properties.Properties.limits.maxUniformBufferRange, (uint32_t)1024 * 1024);
NullMesh.reset(new LevelMesh());
levelMesh = NullMesh.get();
mCommands.reset(new VkCommandBufferManager(this));
mSamplerManager.reset(new VkSamplerManager(this));
@ -521,8 +524,7 @@ void VulkanRenderDevice::BeginFrame()
{
levelMeshChanged = false;
mLevelMesh->SetLevelMesh(levelMesh);
if (levelMesh)
GetTextureManager()->CreateLightmap(levelMesh->Lightmap.TextureSize, levelMesh->Lightmap.TextureCount, std::move(levelMesh->Lightmap.TextureData));
GetTextureManager()->CreateLightmap(levelMesh->Lightmap.TextureSize, levelMesh->Lightmap.TextureCount, std::move(levelMesh->Lightmap.TextureData));
GetLightmapper()->SetLevelMesh(levelMesh);
}
@ -586,6 +588,11 @@ void VulkanRenderDevice::PrintStartupLog()
void VulkanRenderDevice::SetLevelMesh(LevelMesh* mesh)
{
if (!mesh) // Vulkan must have a mesh for its data structures in shaders to remain sane
{
NullMesh.reset(new LevelMesh()); // we must have a completely new mesh here as the upload ranges needs to reset as well
mesh = NullMesh.get();
}
levelMesh = mesh;
levelMeshChanged = true;
}

View file

@ -130,6 +130,7 @@ private:
LevelMesh* levelMesh = nullptr;
bool levelMeshChanged = true;
std::unique_ptr<LevelMesh> NullMesh;
int levelVertexFormatIndex = -1;
TArray<VkPipelineKey> levelMeshPipelineKeys;