Skip to content

Commit

Permalink
Precache all replacements, before static geometry
Browse files Browse the repository at this point in the history
  • Loading branch information
sultim-t committed Nov 18, 2023
1 parent 9966910 commit da6f91f
Show file tree
Hide file tree
Showing 10 changed files with 376 additions and 255 deletions.
194 changes: 124 additions & 70 deletions Source/ASManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ RTGL1::ASManager::ASManager( VkDevice _device,
scratchBuffer = std::make_shared< ChunkedStackAllocator >(
allocator,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
16 * 1024 * 1024,
scratchOffsetAligment,
"Scratch buffer" );

Expand All @@ -95,13 +96,20 @@ RTGL1::ASManager::ASManager( VkDevice _device,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;

allocStaticGeom = std::make_unique< ChunkedStackAllocator >(
allocator, usage, asAlignment, "BLAS common buffer for static" );
allocator, usage, 16 * 1024 * 1024, asAlignment, "BLAS common buffer for static" );

allocReplacementsGeom =
std::make_unique< ChunkedStackAllocator >( allocator,
usage,
64 * 1024 * 1024,
asAlignment,
"BLAS common buffer for replacements" );

allocDynamicGeom = std::make_unique< ChunkedStackAllocator >(
allocator, usage, asAlignment, "BLAS common buffer for dynamic" );
allocator, usage, 16 * 1024 * 1024, asAlignment, "BLAS common buffer for dynamic" );

allocTlas = std::make_unique< ChunkedStackAllocator >(
allocator, usage, asAlignment, "TLAS common buffer" );
allocator, usage, 16 * 1024 * 1024, asAlignment, "TLAS common buffer" );
}

_maxReplacementsVerts = _maxReplacementsVerts > 0 ? _maxReplacementsVerts : 2097152;
Expand Down Expand Up @@ -625,41 +633,66 @@ RTGL1::ASManager::~ASManager()
vkDestroyFence( device, staticCopyFence, nullptr );
}

RTGL1::StaticGeometryToken RTGL1::ASManager::BeginStaticGeometry()
RTGL1::StaticGeometryToken RTGL1::ASManager::BeginStaticGeometry( bool freeReplacements )
{
// the whole static vertex data must be recreated, clear previous data
collectorStatic->Reset();
// static vertex data must be recreated, clear previous data
// (just statics or fully, if need to erase replacements)
collectorStatic->Reset( freeReplacements ? nullptr : &collectorStatic_replacements );
geomInfoMgr->ResetOnlyStatic();

// static geometry submission happens very infrequently, e.g. on level load
vkDeviceWaitIdle( device );

// destroy previous static
// destroy previous AS
builtStaticInstances.clear();
// and replacements, because they depend on allocator / vertex collector of static
builtReplacements.clear();
if( freeReplacements )
{
builtReplacements.clear();
}

// free AS memory
allocStaticGeom->Reset();
if( freeReplacements )
{
allocReplacementsGeom->Reset();
}

erase_if( curFrame_objects, []( const Object& o ) { return o.isStatic; } );

assert( asBuilder->IsEmpty() );
return StaticGeometryToken( InitAsExisting );
}

void RTGL1::ASManager::SubmitStaticGeometry( StaticGeometryToken& token )
void RTGL1::ASManager::MarkReplacementsRegionEnd( const StaticGeometryToken& token )
{
assert( token );
collectorStatic_replacements = collectorStatic->GetCurrentRanges();
}

void RTGL1::ASManager::SubmitStaticGeometry( StaticGeometryToken& token, bool buildReplacements )
{
assert( token );
token = {};

if( builtStaticInstances.empty() )
if( builtStaticInstances.empty() && !buildReplacements )
{
return;
}

VkCommandBuffer cmd = cmdManager->StartGraphicsCmd();

// copy from staging with barrier
collectorStatic->CopyFromStaging( cmd );
if( buildReplacements )
{
collectorStatic->CopyFromStaging( cmd );
}
else
{
auto onlyStaticRange = VertexCollector::CopyRanges::RemoveAtStart(
collectorStatic->GetCurrentRanges(), collectorStatic_replacements );

collectorStatic->CopyFromStaging( cmd, onlyStaticRange );
}

assert( !asBuilder->IsEmpty() );
asBuilder->BuildBottomLevel( cmd );
Expand All @@ -679,7 +712,7 @@ RTGL1::DynamicGeometryToken RTGL1::ASManager::BeginDynamicGeometry( VkCommandBuf
scratchBuffer->Reset();

// dynamic vertices are refilled each frame
collectorDynamic[ frameIndex ]->Reset();
collectorDynamic[ frameIndex ]->Reset( nullptr );
// destroy dynamic instances from N-2
builtDynamicInstances[ frameIndex ].clear();
allocDynamicGeom->Reset();
Expand All @@ -690,6 +723,48 @@ RTGL1::DynamicGeometryToken RTGL1::ASManager::BeginDynamicGeometry( VkCommandBuf
return DynamicGeometryToken( InitAsExisting );
}

auto RTGL1::ASManager::UploadAndBuildAS( const RgMeshPrimitiveInfo& primitive,
VertexCollectorFilterTypeFlags geomFlags,
VertexCollector& vertexAlloc,
ChunkedStackAllocator& accelStructAlloc,
const bool isDynamic ) -> std::shared_ptr< BuiltAS >
{
auto uploadedData = vertexAlloc.Upload( geomFlags, primitive );
if( !uploadedData )
{
return {};
}

// NOTE: dedicated allocation, so pointers in asBuilder
// are valid until end of the frame
auto newlyBuilt = new BuiltAS{
.flags = geomFlags,
.blas = BLASComponent{ device },
.geometry = *uploadedData,
};
{
const bool fastTrace = isDynamic ? false : true;

// get AS size and create buffer for AS
const auto buildSizes =
ASBuilder::GetBottomBuildSizes( device,
newlyBuilt->geometry.asGeometryInfo,
newlyBuilt->geometry.asRange.primitiveCount,
fastTrace );
newlyBuilt->blas.RecreateIfNotValid( buildSizes, accelStructAlloc );

// add BLAS, all passed arrays must be alive until BuildBottomLevel() call
asBuilder->AddBLAS( newlyBuilt->blas.GetAS(),
{ &newlyBuilt->geometry.asGeometryInfo, 1 },
{ &newlyBuilt->geometry.asRange, 1 },
buildSizes,
fastTrace,
false,
false );
}
return std::shared_ptr< BuiltAS >{ newlyBuilt };
}

bool RTGL1::ASManager::AddMeshPrimitive( uint32_t frameIndex,
const RgMeshInfo& mesh,
const RgMeshPrimitiveInfo& primitive,
Expand Down Expand Up @@ -737,71 +812,29 @@ bool RTGL1::ASManager::AddMeshPrimitive( uint32_t frameIndex,
}
else
{
// assert( 0 );
assert( 0 );
}
}
}

// if AS doesn't exist, create it
if( !builtInstance )
{
auto& dstCollector =
isStatic || isReplacement ? collectorStatic : collectorDynamic[ frameIndex ];

auto copyRanges = VertexCollector::CopyRanges{};

auto uploadedData = dstCollector->Upload(
geomFlags, mesh, primitive, isReplacement ? &copyRanges : nullptr );
if( !uploadedData )
if( isReplacement )
{
// expected AS to be created for a replacement
assert( 0 );
return false;
}

builtInstance =
UploadAndBuildAS( primitive,
geomFlags,
isStatic ? *collectorStatic : *collectorDynamic[ frameIndex ],
isStatic ? *allocStaticGeom : *allocDynamicGeom,
!isStatic );

// NOTE: dedicated allocation, so pointers in asBuilder
// are valid until end of the frame
auto newlyBuilt = new BuiltAS{
.flags = geomFlags,
.blas = BLASComponent{ device },
.geometry = *uploadedData,
};
{
const bool fastTrace = isStatic || isReplacement ? true : false;

// get AS size and create buffer for AS
const auto buildSizes =
ASBuilder::GetBottomBuildSizes( device,
newlyBuilt->geometry.asGeometryInfo,
newlyBuilt->geometry.asRange.primitiveCount,
fastTrace );
newlyBuilt->blas.RecreateIfNotValid(
buildSizes, isStatic || isReplacement ? *allocStaticGeom : *allocDynamicGeom );

// add BLAS, all passed arrays must be alive until BuildBottomLevel() call
asBuilder->AddBLAS( newlyBuilt->blas.GetAS(),
{ &newlyBuilt->geometry.asGeometryInfo, 1 },
{ &newlyBuilt->geometry.asRange, 1 },
buildSizes,
fastTrace,
false,
false );
}


builtInstance = std::shared_ptr< BuiltAS >{ newlyBuilt };

// save a built instance to a corresponding storage
if( isReplacement )
{
assert( copyRanges.vertices.valid() );
curFrame_replacementDataToCopy =
VertexCollector::CopyRanges::Merge( curFrame_replacementDataToCopy, copyRanges );

// look at the TODO note above
assert( builtReplacements[ mesh.pMeshName ].size() == uniqueID.primitiveIndex );
builtReplacements[ mesh.pMeshName ].push_back( builtInstance );
}
else if( isStatic )
if( isStatic )
{
builtStaticInstances.push_back( builtInstance );
}
Expand Down Expand Up @@ -881,6 +914,31 @@ bool RTGL1::ASManager::AddMeshPrimitive( uint32_t frameIndex,
return true;
}

void RTGL1::ASManager::CacheReplacement( std::string_view meshName,
const RgMeshPrimitiveInfo& primitive,
uint32_t index )
{
constexpr bool isReplacement = true;
constexpr bool isStatic = false;
constexpr bool isDynamic = false;

const auto geomFlags =
VertexCollectorFilterTypeFlags_GetForGeometry( {}, primitive, isStatic, isReplacement );

std::shared_ptr< BuiltAS > builtInstance = UploadAndBuildAS(
primitive, geomFlags, *collectorStatic, *allocReplacementsGeom, isDynamic );

if( !builtInstance )
{
debug::Warning( "Failed to upload vertex data of a replacement primitive" );
return;
}

// TODO: look at the note above on primitiveIndex
assert( builtReplacements[ meshName ].size() == index );
builtReplacements[ meshName ].push_back( builtInstance );
}

void RTGL1::ASManager::SubmitDynamicGeometry( DynamicGeometryToken& token,
VkCommandBuffer cmd,
uint32_t frameIndex )
Expand All @@ -890,11 +948,7 @@ void RTGL1::ASManager::SubmitDynamicGeometry( DynamicGeometryToken& token,

{
auto label = CmdLabel{ cmd, "Vertex data" };

collectorDynamic[ frameIndex ]->CopyFromStaging( cmd );

collectorStatic->CopyFromStaging( cmd, curFrame_replacementDataToCopy );
curFrame_replacementDataToCopy = {};
}


Expand Down
24 changes: 17 additions & 7 deletions Source/ASManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ class ASManager
ASManager& operator=( ASManager&& other ) noexcept = delete;


[[nodiscard]] StaticGeometryToken BeginStaticGeometry();
[[nodiscard]] StaticGeometryToken BeginStaticGeometry( bool freeReplacements );
void MarkReplacementsRegionEnd( const StaticGeometryToken& token );
// Submitting static geometry to the building is a heavy operation
// with waiting for it to complete.
void SubmitStaticGeometry( StaticGeometryToken& token );
void SubmitStaticGeometry( StaticGeometryToken& token, bool buildReplacements );


[[nodiscard]] DynamicGeometryToken BeginDynamicGeometry( VkCommandBuffer cmd,
Expand All @@ -76,6 +77,10 @@ class ASManager
const TextureManager& textureManager,
GeomInfoManager& geomInfoManager );

void CacheReplacement( std::string_view meshName,
const RgMeshPrimitiveInfo& primitive,
uint32_t index );


auto MakeUniqueIDToTlasID( bool disableRTGeometry ) const -> UniqueIDToTlasID;
void BuildTLAS( VkCommandBuffer cmd,
Expand Down Expand Up @@ -112,6 +117,12 @@ class ASManager
VertexCollector::UploadResult geometry;
};

auto UploadAndBuildAS( const RgMeshPrimitiveInfo& primitive,
VertexCollectorFilterTypeFlags geomFlags,
VertexCollector& vertexAlloc,
ChunkedStackAllocator& accelStructAlloc,
const bool isDynamic ) -> std::shared_ptr< BuiltAS >;

static auto MakeVkTLAS( const BuiltAS& builtAS,
uint32_t rayCullMaskWorld,
bool allowGeometryWithSkyFlag,
Expand All @@ -131,6 +142,7 @@ class ASManager
// device-local buffer for storing previous info
Buffer previousDynamicPositions;
Buffer previousDynamicIndices;
VertexCollector::CopyRanges collectorStatic_replacements{};

// building
std::shared_ptr< ChunkedStackAllocator > scratchBuffer;
Expand All @@ -140,13 +152,13 @@ class ASManager
std::shared_ptr< TextureManager > textureMgr;
std::shared_ptr< GeomInfoManager > geomInfoMgr;

rgl::string_map< std::vector< std::shared_ptr< BuiltAS > > > builtReplacements;

std::unique_ptr< ChunkedStackAllocator > allocTlas;
std::unique_ptr< ChunkedStackAllocator > allocReplacementsGeom;
std::unique_ptr< ChunkedStackAllocator > allocStaticGeom;
std::unique_ptr< ChunkedStackAllocator > allocDynamicGeom;

std::vector< std::shared_ptr< BuiltAS > > builtStaticInstances;
rgl::string_map< std::vector< std::shared_ptr< BuiltAS > > > builtReplacements;
std::vector< std::shared_ptr< BuiltAS > > builtStaticInstances;
std::vector< std::shared_ptr< BuiltAS > > builtDynamicInstances[ MAX_FRAMES_IN_FLIGHT ];

// Exists only in the current frame
Expand All @@ -162,8 +174,6 @@ class ASManager
};
std::vector< Object > curFrame_objects;

VertexCollector::CopyRanges curFrame_replacementDataToCopy{};

// top level AS
std::unique_ptr< AutoBuffer > instanceBuffer;
std::unique_ptr< TLASComponent > tlas[ MAX_FRAMES_IN_FLIGHT ];
Expand Down
2 changes: 2 additions & 0 deletions Source/GltfImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "DrawFrameInfo.h"

#include <filesystem>
#include <ranges>
#include <span>

struct cgltf_node;
struct cgltf_data;
Expand Down
Loading

0 comments on commit da6f91f

Please sign in to comment.