fixed RTAS build crash due to missing cross queue sync

This commit is contained in:
myT 2024-07-07 18:20:26 +02:00
parent 4955060c9f
commit 16a51506c0
4 changed files with 101 additions and 72 deletions

View file

@ -329,13 +329,27 @@ struct Raytracing
{ {
void Init(); void Init();
void ProcessWorld(world_t& world); void ProcessWorld(world_t& world);
void BeforeFrame(bool wantUpdate);
void BeginFrame(bool wantUpdate); void BeginFrame(bool wantUpdate);
uint32_t GetTLASBufferIndex(); uint32_t GetTLASBufferIndex();
uint32_t GetInstanceBufferIndex(); uint32_t GetInstanceBufferIndex();
bool CanRaytrace(); bool CanRaytrace();
private: private:
struct BLASBuildBuffers;
struct BLASBuffers;
struct ISurfaceList;
void TagMapSurfacesRecursively(mnode_t* node); void TagMapSurfacesRecursively(mnode_t* node);
void ProcessStaticSurfaces();
void EnsureBuffersAreLargeEnough(BLASBuildBuffers& buffers, uint32_t maxVertexCount, uint32_t maxIndexCount);
void EnsureBuffersAreLargeEnough(BLASBuffers& buffers, uint32_t maxVertexCount, uint32_t maxIndexCount, uint32_t maxMeshCount);
void BuildBLASes(BLASBuffers* blasBuffers, struct BLASBuilder* blasBuilders, ISurfaceList* surfaceList);
uint32_t GetRTFrameIndex() { return frameCount % RTFrameCount; }
enum Constants
{
RTFrameCount = RHI::FrameCount
};
struct BLASBucket struct BLASBucket
{ {
@ -389,10 +403,6 @@ private:
bool GetSurface(Surface& surface, uint32_t index) override; bool GetSurface(Surface& surface, uint32_t index) override;
}; };
void EnsureBuffersAreLargeEnough(BLASBuildBuffers& buffers, uint32_t maxVertexCount, uint32_t maxIndexCount);
void EnsureBuffersAreLargeEnough(BLASBuffers& buffers, uint32_t maxVertexCount, uint32_t maxIndexCount, uint32_t maxMeshCount);
void BuildBLASes(BLASBuffers* blasBuffers, struct BLASBuilder* blasBuilders, ISurfaceList* surfaceList);
struct FrameData struct FrameData
{ {
BLASBuildBuffers blasBuildBuffers[BLASBucket::Count] = {}; BLASBuildBuffers blasBuildBuffers[BLASBucket::Count] = {};
@ -401,14 +411,15 @@ private:
HBuffer tlasInstanceBuffer = RHI_MAKE_NULL_HANDLE(); HBuffer tlasInstanceBuffer = RHI_MAKE_NULL_HANDLE();
}; };
enum Constants { RTFrameCount = RHI::FrameCount + 1 };
uint32_t GetRTFrameIndex() { return tr.frameCount % RTFrameCount; }
FrameData frameData[RTFrameCount]; FrameData frameData[RTFrameCount];
BLASBuffers staticBLASBuffers[BLASBucket::Count] = {}; BLASBuffers staticBLASBuffers[BLASBucket::Count] = {};
StaticArray<TLASInstanceDesc, 2 * BLASBucket::Count> tlasInstanceDescs; StaticArray<TLASInstanceDesc, 2 * BLASBucket::Count> tlasInstanceDescs;
uint32_t staticTLASInstanceCount = 0; uint32_t staticTLASInstanceCount = 0;
bool pendingWorldProcess = false;
uint32_t frameCount = 0;
// we have a local frame counter because (for now)
// RHI::GetFrameIndex() increments during RHI::BeginFrame()
// in a given frame, we need BeforeFrame and BeginFrame to use the same buffer index
}; };
struct SunlightEditor struct SunlightEditor

View file

@ -630,9 +630,10 @@ void CRP::BeginFrame()
dynamicLights.WantRTASUpdate(tr.rtRefdef) || dynamicLights.WantRTASUpdate(tr.rtRefdef) ||
sunlight.WantRTASUpdate(tr.rtRefdef) || sunlight.WantRTASUpdate(tr.rtRefdef) ||
volumetricLight.WantRTASUpdate(tr.rtRefdef); volumetricLight.WantRTASUpdate(tr.rtRefdef);
raytracing.BeginFrame(rtasUpdate); raytracing.BeforeFrame(rtasUpdate); // uploads data
RHI::BeginFrame(); RHI::BeginFrame();
raytracing.BeginFrame(rtasUpdate); // does BLAS/TLAS builds
ui.BeginFrame(); ui.BeginFrame();
nuklear.BeginFrame(); nuklear.BeginFrame();

View file

@ -47,8 +47,6 @@ struct BLASBuilder
BLASMesh* traceMeshes; BLASMesh* traceMeshes;
}; };
static world_t* s_world;
static bool IsStaticBLASSurface(const msurface_t* surf) static bool IsStaticBLASSurface(const msurface_t* surf)
{ {
if(surf->shader->numStages == 0 || if(surf->shader->numStages == 0 ||
@ -205,23 +203,31 @@ void Raytracing::Init()
void Raytracing::ProcessWorld(world_t& world) void Raytracing::ProcessWorld(world_t& world)
{ {
if(!rhiInfo.hasInlineRaytracing) if(rhiInfo.hasInlineRaytracing)
{
pendingWorldProcess = true;
}
}
void Raytracing::ProcessStaticSurfaces()
{
if(!rhiInfo.hasInlineRaytracing ||
!pendingWorldProcess ||
tr.world == NULL)
{ {
return; return;
} }
pendingWorldProcess = false;
TagMapSurfacesRecursively(world.nodes); TagMapSurfacesRecursively(tr.world->nodes);
BLASBuilder staticBLASes[BLASBucket::Count]; BLASBuilder staticBLASes[BLASBucket::Count];
WorldSurfaceList surfaceList; WorldSurfaceList surfaceList;
s_world = &world;
BuildBLASes(staticBLASBuffers, staticBLASes, &surfaceList); BuildBLASes(staticBLASBuffers, staticBLASes, &surfaceList);
s_world = NULL;
FrameData& fd = frameData[GetRTFrameIndex()]; FrameData& fd = frameData[GetRTFrameIndex()];
// create ASes // create ASes
BeginTempCommandList();
for(uint32_t i = 0; i < BLASBucket::Count; i++) for(uint32_t i = 0; i < BLASBucket::Count; i++)
{ {
BLASBuilder& bucket = staticBLASes[i]; BLASBuilder& bucket = staticBLASes[i];
@ -239,7 +245,6 @@ void Raytracing::ProcessWorld(world_t& world)
desc.meshCount = bucket.meshCount; desc.meshCount = bucket.meshCount;
CmdCreateBLAS(&staticBLASBuffers[i].blasBuffer, desc); CmdCreateBLAS(&staticBLASBuffers[i].blasBuffer, desc);
} }
EndTempCommandList();
for(uint32_t i = 0; i < BLASBucket::Count; i++) for(uint32_t i = 0; i < BLASBucket::Count; i++)
{ {
BLASBuilder& bucket = staticBLASes[i]; BLASBuilder& bucket = staticBLASes[i];
@ -274,15 +279,76 @@ void Raytracing::ProcessWorld(world_t& world)
} }
} }
void Raytracing::BeginFrame(bool wantUpdate) void Raytracing::BeforeFrame(bool wantUpdate)
{ {
if(!rhiInfo.hasInlineRaytracing) if(!rhiInfo.hasInlineRaytracing ||
tr.world == NULL ||
tr.sceneCounterRT == 0 ||
pendingWorldProcess)
{ {
return; return;
} }
if(tr.world == NULL || tr.sceneCounterRT == 0) frameCount++;
FrameData& fd = frameData[GetRTFrameIndex()];
TLASInstance* traceInstances = (TLASInstance*)BeginBufferUpload(fd.tlasInstanceBuffer);
uint32_t instanceId = 0;
for(uint32_t i = 0; i < ARRAY_LEN(staticBLASBuffers); i++)
{ {
const BLASBuffers& buffers = staticBLASBuffers[i];
if(IsNullHandle(buffers.blasBuffer))
{
continue;
}
Q_assert(instanceId == tlasInstanceDescs[instanceId].instanceId);
TLASInstance traceInst = {};
traceInst.meshBufferIndex = GetBufferIndexSRV(buffers.meshBuffer);
traceInst.vertexBufferIndex = GetBufferIndexSRV(buffers.vertexBuffer);
traceInst.indexBufferIndex = GetBufferIndexSRV(buffers.indexBuffer);
traceInst.cullMode = (uint32_t)tlasInstanceDescs[instanceId++].cullMode;
*traceInstances++ = traceInst;
}
for(uint32_t i = 0; i < ARRAY_LEN(fd.dynamicBLASBuffers); i++)
{
const BLASBuffers& buffers = fd.dynamicBLASBuffers[i];
if(IsNullHandle(buffers.blasBuffer))
{
continue;
}
Q_assert(instanceId == tlasInstanceDescs[instanceId].instanceId);
TLASInstance traceInst = {};
traceInst.meshBufferIndex = GetBufferIndexSRV(buffers.meshBuffer);
traceInst.vertexBufferIndex = GetBufferIndexSRV(buffers.vertexBuffer);
traceInst.indexBufferIndex = GetBufferIndexSRV(buffers.indexBuffer);
traceInst.cullMode = (uint32_t)tlasInstanceDescs[instanceId++].cullMode;
*traceInstances++ = traceInst;
}
EndBufferUpload(fd.tlasInstanceBuffer);
#if defined(_DEBUG)
for(uint32_t i = 0; i < tlasInstanceDescs.count; i++)
{
Q_assert(tlasInstanceDescs[i].instanceId == i);
}
#endif
}
void Raytracing::BeginFrame(bool wantUpdate)
{
if(!rhiInfo.hasInlineRaytracing ||
tr.world == NULL ||
tr.sceneCounterRT == 0)
{
return;
}
if(pendingWorldProcess)
{
ProcessStaticSurfaces();
return; return;
} }
@ -296,7 +362,6 @@ void Raytracing::BeginFrame(bool wantUpdate)
backEnd.refdef = tr.rtRefdef; backEnd.refdef = tr.rtRefdef;
BeginTempCommandList();
const uint32_t renderPass = srp.BeginRenderPass("RTAS Build", 1.0f, 1.0f, 1.0f); const uint32_t renderPass = srp.BeginRenderPass("RTAS Build", 1.0f, 1.0f, 1.0f);
BLASBuilder dynamicBLASes[BLASBucket::Count]; BLASBuilder dynamicBLASes[BLASBucket::Count];
DynamicSurfaceList surfaceList; DynamicSurfaceList surfaceList;
@ -346,50 +411,6 @@ void Raytracing::BeginFrame(bool wantUpdate)
CmdCreateTLAS(&fd.tlasBuffer, desc); CmdCreateTLAS(&fd.tlasBuffer, desc);
} }
srp.EndRenderPass(renderPass); srp.EndRenderPass(renderPass);
EndTempCommandList();
TLASInstance* traceInstances = (TLASInstance*)BeginBufferUpload(fd.tlasInstanceBuffer);
uint32_t instanceId = 0;
for(uint32_t i = 0; i < ARRAY_LEN(staticBLASBuffers); i++)
{
const BLASBuffers& buffers = staticBLASBuffers[i];
if(IsNullHandle(buffers.blasBuffer))
{
continue;
}
Q_assert(instanceId == tlasInstanceDescs[instanceId].instanceId);
TLASInstance traceInst = {};
traceInst.meshBufferIndex = GetBufferIndexSRV(buffers.meshBuffer);
traceInst.vertexBufferIndex = GetBufferIndexSRV(buffers.vertexBuffer);
traceInst.indexBufferIndex = GetBufferIndexSRV(buffers.indexBuffer);
traceInst.cullMode = (uint32_t)tlasInstanceDescs[instanceId++].cullMode;
*traceInstances++ = traceInst;
}
for(uint32_t i = 0; i < ARRAY_LEN(fd.dynamicBLASBuffers); i++)
{
const BLASBuffers& buffers = fd.dynamicBLASBuffers[i];
if(IsNullHandle(buffers.blasBuffer))
{
continue;
}
Q_assert(instanceId == tlasInstanceDescs[instanceId].instanceId);
TLASInstance traceInst = {};
traceInst.meshBufferIndex = GetBufferIndexSRV(buffers.meshBuffer);
traceInst.vertexBufferIndex = GetBufferIndexSRV(buffers.vertexBuffer);
traceInst.indexBufferIndex = GetBufferIndexSRV(buffers.indexBuffer);
traceInst.cullMode = (uint32_t)tlasInstanceDescs[instanceId++].cullMode;
*traceInstances++ = traceInst;
}
EndBufferUpload(fd.tlasInstanceBuffer);
#if defined(_DEBUG)
for(uint32_t i = 0; i < tlasInstanceDescs.count; i++)
{
Q_assert(tlasInstanceDescs[i].instanceId == i);
}
#endif
} }
void Raytracing::TagMapSurfacesRecursively(mnode_t* node) void Raytracing::TagMapSurfacesRecursively(mnode_t* node)
@ -636,14 +657,14 @@ void Raytracing::BuildBLASes(BLASBuffers* blasBuffers, BLASBuilder* blasBuilders
uint32_t Raytracing::WorldSurfaceList::GetSurfaceCount() uint32_t Raytracing::WorldSurfaceList::GetSurfaceCount()
{ {
return s_world->numsurfaces; return tr.world->numsurfaces;
} }
bool Raytracing::WorldSurfaceList::GetSurface(Surface& surface, uint32_t index) bool Raytracing::WorldSurfaceList::GetSurface(Surface& surface, uint32_t index)
{ {
Q_assert(index < (uint32_t)s_world->numsurfaces); Q_assert(index < (uint32_t)tr.world->numsurfaces);
const msurface_t& surf = s_world->surfaces[index]; const msurface_t& surf = tr.world->surfaces[index];
if(surf.rtSurfType != RTST_STATIC || surf.shader->numStages <= 0) if(surf.rtSurfType != RTST_STATIC || surf.shader->numStages <= 0)
{ {
return true; return true;

View file

@ -5745,8 +5745,6 @@ namespace RHI
void CmdCreateBLAS(HBuffer* blasBuffer, const BLASDesc& rhiDesc) void CmdCreateBLAS(HBuffer* blasBuffer, const BLASDesc& rhiDesc)
{ {
ASSERT_DR_ENABLED(); ASSERT_DR_ENABLED();
Q_assert(rhi.commandList == rhi.tempCommandList);
Q_assert(rhi.tempCommandListOpen);
Q_assert(blasBuffer); Q_assert(blasBuffer);
Q_assert(!IsNullHandle(rhiDesc.vertexBuffer)); Q_assert(!IsNullHandle(rhiDesc.vertexBuffer));
Q_assert(!IsNullHandle(rhiDesc.indexBuffer)); Q_assert(!IsNullHandle(rhiDesc.indexBuffer));
@ -5831,8 +5829,6 @@ namespace RHI
void CmdCreateTLAS(HBuffer* tlasBuffer, const TLASDesc& rhiDesc) void CmdCreateTLAS(HBuffer* tlasBuffer, const TLASDesc& rhiDesc)
{ {
ASSERT_DR_ENABLED(); ASSERT_DR_ENABLED();
Q_assert(rhi.commandList == rhi.tempCommandList);
Q_assert(rhi.tempCommandListOpen);
Q_assert(tlasBuffer != NULL); Q_assert(tlasBuffer != NULL);
Q_assert(rhiDesc.instances); Q_assert(rhiDesc.instances);
Q_assert(rhiDesc.instanceCount > 0); Q_assert(rhiDesc.instanceCount > 0);