|
|
@@ -6,7 +6,9 @@
|
|
|
#include <AnKi/Core/GpuMemoryPools.h>
|
|
|
#include <AnKi/Core/ConfigSet.h>
|
|
|
#include <AnKi/Gr/GrManager.h>
|
|
|
+#include <AnKi/Gr/CommandBuffer.h>
|
|
|
#include <AnKi/Util/Tracer.h>
|
|
|
+#include <AnKi/Resource/ResourceManager.h>
|
|
|
|
|
|
namespace anki {
|
|
|
|
|
|
@@ -25,7 +27,7 @@ void UnifiedGeometryMemoryPool::init(HeapMemoryPool* pool, GrManager* gr, const
|
|
|
buffUsage |= BufferUsageBit::kAccelerationStructureBuild;
|
|
|
}
|
|
|
|
|
|
- m_alloc.init(gr, pool, buffUsage, classes, poolSize, "UnifiedGeometry", false);
|
|
|
+ m_pool.init(gr, pool, buffUsage, classes, poolSize, "UnifiedGeometry", false);
|
|
|
}
|
|
|
|
|
|
void GpuSceneMemoryPool::init(HeapMemoryPool* pool, GrManager* gr, const ConfigSet& cfg)
|
|
|
@@ -38,7 +40,7 @@ void GpuSceneMemoryPool::init(HeapMemoryPool* pool, GrManager* gr, const ConfigS
|
|
|
|
|
|
BufferUsageBit buffUsage = BufferUsageBit::kAllStorage | BufferUsageBit::kTransferDestination;
|
|
|
|
|
|
- m_alloc.init(gr, pool, buffUsage, classes, poolSize, "GpuScene", true);
|
|
|
+ m_pool.init(gr, pool, buffUsage, classes, poolSize, "GpuScene", true);
|
|
|
}
|
|
|
|
|
|
RebarStagingGpuMemoryPool::~RebarStagingGpuMemoryPool()
|
|
|
@@ -130,4 +132,101 @@ PtrSize RebarStagingGpuMemoryPool::endFrame()
|
|
|
return usedMemory;
|
|
|
}
|
|
|
|
|
|
+/// It packs the source and destination offsets as well as the size of the patch itself.
|
|
|
+class GpuSceneMicroPatcher::PatchHeader
|
|
|
+{
|
|
|
+public:
|
|
|
+ U32 m_dwordCountAndSrcDwordOffsetPack;
|
|
|
+ U32 m_dstDwordOffset;
|
|
|
+};
|
|
|
+
|
|
|
+GpuSceneMicroPatcher::~GpuSceneMicroPatcher()
|
|
|
+{
|
|
|
+ static_assert(sizeof(PatchHeader) == 8);
|
|
|
+}
|
|
|
+
|
|
|
+Error GpuSceneMicroPatcher::init(ResourceManager* rsrc)
|
|
|
+{
|
|
|
+ ANKI_CHECK(rsrc->loadResource("ShaderBinaries/GpuSceneMicroPatching.ankiprogbin", m_copyProgram));
|
|
|
+ const ShaderProgramResourceVariant* variant;
|
|
|
+ m_copyProgram->getOrCreateVariant(variant);
|
|
|
+ m_grProgram = variant->getProgram();
|
|
|
+
|
|
|
+ return Error::kNone;
|
|
|
+}
|
|
|
+
|
|
|
+void GpuSceneMicroPatcher::newCopy(StackMemoryPool& frameCpuPool, PtrSize gpuSceneDestOffset, PtrSize dataSize,
|
|
|
+ const void* data)
|
|
|
+{
|
|
|
+ ANKI_ASSERT(dataSize > 0 && (dataSize % 4) == 0);
|
|
|
+ ANKI_ASSERT((ptrToNumber(data) % 4) == 0);
|
|
|
+ ANKI_ASSERT((gpuSceneDestOffset % 4) == 0 && gpuSceneDestOffset / 4 < kMaxU32);
|
|
|
+
|
|
|
+ const U32 dataDwords = U32(dataSize / 4);
|
|
|
+ U32 gpuSceneDestDwordOffset = U32(gpuSceneDestOffset / 4);
|
|
|
+
|
|
|
+ const U32* patchIt = static_cast<const U32*>(data);
|
|
|
+ const U32* const patchEnd = patchIt + dataDwords;
|
|
|
+
|
|
|
+ // Break the data into multiple copies
|
|
|
+ LockGuard lock(m_mtx);
|
|
|
+ while(patchIt < patchEnd)
|
|
|
+ {
|
|
|
+ const U32 patchDwords = U32(patchEnd - patchIt);
|
|
|
+
|
|
|
+ PatchHeader& header = *m_crntFramePatchHeaders.emplaceBack(frameCpuPool);
|
|
|
+ ANKI_ASSERT(((patchDwords - 1) & 0b111111) == (patchDwords - 1));
|
|
|
+ header.m_dwordCountAndSrcDwordOffsetPack = patchDwords - 1;
|
|
|
+ header.m_dwordCountAndSrcDwordOffsetPack <<= 26;
|
|
|
+ ANKI_ASSERT((m_crntFramePatchData.getSize() & 0x3FFFFFF) == m_crntFramePatchData.getSize());
|
|
|
+ header.m_dwordCountAndSrcDwordOffsetPack |= m_crntFramePatchData.getSize();
|
|
|
+ header.m_dstDwordOffset = gpuSceneDestDwordOffset;
|
|
|
+
|
|
|
+ const U32 srcOffset = m_crntFramePatchData.getSize();
|
|
|
+ m_crntFramePatchData.resize(frameCpuPool, srcOffset + patchDwords);
|
|
|
+ memcpy(&m_crntFramePatchData[srcOffset], patchIt, patchDwords * 4);
|
|
|
+
|
|
|
+ patchIt += kDwordsPerPatch;
|
|
|
+ gpuSceneDestDwordOffset += kDwordsPerPatch;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GpuSceneMicroPatcher::patchGpuScene(RebarStagingGpuMemoryPool& rebarPool, CommandBuffer& cmdb,
|
|
|
+ const BufferPtr& gpuSceneBuffer)
|
|
|
+{
|
|
|
+ if(m_crntFramePatchHeaders.getSize() == 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ANKI_ASSERT(m_crntFramePatchData.getSize() > 0);
|
|
|
+
|
|
|
+ ANKI_TRACE_INC_COUNTER(GpuSceneMicroPatches, m_crntFramePatchHeaders.getSize());
|
|
|
+ ANKI_TRACE_INC_COUNTER(GpuSceneMicroPatchUploadData, m_crntFramePatchData.getSizeInBytes());
|
|
|
+
|
|
|
+ RebarGpuMemoryToken headersToken;
|
|
|
+ void* mapped = rebarPool.allocateFrame(m_crntFramePatchHeaders.getSizeInBytes(), headersToken);
|
|
|
+ memcpy(mapped, &m_crntFramePatchHeaders[0], m_crntFramePatchHeaders.getSizeInBytes());
|
|
|
+
|
|
|
+ RebarGpuMemoryToken dataToken;
|
|
|
+ mapped = rebarPool.allocateFrame(m_crntFramePatchData.getSizeInBytes(), dataToken);
|
|
|
+ memcpy(mapped, &m_crntFramePatchData[0], m_crntFramePatchData.getSizeInBytes());
|
|
|
+
|
|
|
+ cmdb.bindStorageBuffer(0, 0, rebarPool.getBuffer(), headersToken.m_offset, headersToken.m_range);
|
|
|
+ cmdb.bindStorageBuffer(0, 1, rebarPool.getBuffer(), dataToken.m_offset, dataToken.m_range);
|
|
|
+ cmdb.bindStorageBuffer(0, 2, gpuSceneBuffer, 0, kMaxPtrSize);
|
|
|
+
|
|
|
+ cmdb.bindShaderProgram(m_grProgram);
|
|
|
+
|
|
|
+ const U32 workgroupCountX = m_crntFramePatchHeaders.getSize();
|
|
|
+ cmdb.dispatchCompute(workgroupCountX, 1, 1);
|
|
|
+
|
|
|
+ // Cleanup to prepare for the new frame
|
|
|
+ U32* data;
|
|
|
+ U32 size, storage;
|
|
|
+ m_crntFramePatchData.moveAndReset(data, size, storage);
|
|
|
+ PatchHeader* datah;
|
|
|
+ m_crntFramePatchHeaders.moveAndReset(datah, size, storage);
|
|
|
+}
|
|
|
+
|
|
|
} // end namespace anki
|