GpuSceneBuffer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Core/GpuMemory/GpuSceneBuffer.h>
  6. #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
  7. #include <AnKi/Core/ConfigSet.h>
  8. #include <AnKi/Util/Tracer.h>
  9. #include <AnKi/Resource/ResourceManager.h>
  10. #include <AnKi/Gr/CommandBuffer.h>
  11. namespace anki {
  12. void GpuSceneBuffer::init()
  13. {
  14. const PtrSize poolSize = ConfigSet::getSingleton().getCoreGpuSceneInitialSize();
  15. const Array classes = {32_B, 64_B, 128_B, 256_B, poolSize};
  16. BufferUsageBit buffUsage = BufferUsageBit::kAllStorage | BufferUsageBit::kTransferDestination;
  17. m_pool.init(buffUsage, classes, poolSize, "GpuScene", true);
  18. // Allocate something dummy to force creating the GPU buffer
  19. GpuSceneBufferAllocation alloc;
  20. allocate(16, 4, alloc);
  21. deferredFree(alloc);
  22. }
  23. /// It packs the source and destination offsets as well as the size of the patch itself.
  24. class GpuSceneMicroPatcher::PatchHeader
  25. {
  26. public:
  27. U32 m_dwordCountAndSrcDwordOffsetPack;
  28. U32 m_dstDwordOffset;
  29. };
  30. GpuSceneMicroPatcher::GpuSceneMicroPatcher()
  31. {
  32. }
  33. GpuSceneMicroPatcher::~GpuSceneMicroPatcher()
  34. {
  35. static_assert(sizeof(PatchHeader) == 8);
  36. }
  37. Error GpuSceneMicroPatcher::init()
  38. {
  39. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/GpuSceneMicroPatching.ankiprogbin", m_copyProgram));
  40. const ShaderProgramResourceVariant* variant;
  41. m_copyProgram->getOrCreateVariant(variant);
  42. m_grProgram = variant->getProgram();
  43. return Error::kNone;
  44. }
  45. void GpuSceneMicroPatcher::newCopy(StackMemoryPool& frameCpuPool, PtrSize gpuSceneDestOffset, PtrSize dataSize, const void* data)
  46. {
  47. ANKI_ASSERT(dataSize > 0 && (dataSize % 4) == 0);
  48. ANKI_ASSERT((ptrToNumber(data) % 4) == 0);
  49. ANKI_ASSERT((gpuSceneDestOffset % 4) == 0 && gpuSceneDestOffset / 4 < kMaxU32);
  50. const U32 dataDwords = U32(dataSize / 4);
  51. U32 gpuSceneDestDwordOffset = U32(gpuSceneDestOffset / 4);
  52. const U32* patchIt = static_cast<const U32*>(data);
  53. const U32* const patchEnd = patchIt + dataDwords;
  54. // Break the data into multiple copies
  55. LockGuard lock(m_mtx);
  56. if(m_crntFramePatchHeaders.getSize() == 0)
  57. {
  58. m_crntFramePatchHeaders = DynamicArray<PatchHeader, MemoryPoolPtrWrapper<StackMemoryPool>>(&frameCpuPool);
  59. m_crntFramePatchData = DynamicArray<U32, MemoryPoolPtrWrapper<StackMemoryPool>>(&frameCpuPool);
  60. }
  61. while(patchIt < patchEnd)
  62. {
  63. const U32 patchDwords = min(kDwordsPerPatch, U32(patchEnd - patchIt));
  64. PatchHeader& header = *m_crntFramePatchHeaders.emplaceBack();
  65. ANKI_ASSERT(((patchDwords - 1) & 0b111111) == (patchDwords - 1));
  66. header.m_dwordCountAndSrcDwordOffsetPack = patchDwords - 1;
  67. header.m_dwordCountAndSrcDwordOffsetPack <<= 26;
  68. ANKI_ASSERT((m_crntFramePatchData.getSize() & 0x3FFFFFF) == m_crntFramePatchData.getSize());
  69. header.m_dwordCountAndSrcDwordOffsetPack |= m_crntFramePatchData.getSize();
  70. header.m_dstDwordOffset = gpuSceneDestDwordOffset;
  71. const U32 srcOffset = m_crntFramePatchData.getSize();
  72. m_crntFramePatchData.resize(srcOffset + patchDwords);
  73. memcpy(&m_crntFramePatchData[srcOffset], patchIt, patchDwords * 4);
  74. patchIt += patchDwords;
  75. gpuSceneDestDwordOffset += patchDwords;
  76. }
  77. }
  78. void GpuSceneMicroPatcher::patchGpuScene(CommandBuffer& cmdb)
  79. {
  80. if(m_crntFramePatchHeaders.getSize() == 0)
  81. {
  82. return;
  83. }
  84. ANKI_ASSERT(m_crntFramePatchData.getSize() > 0);
  85. ANKI_TRACE_INC_COUNTER(GpuSceneMicroPatches, m_crntFramePatchHeaders.getSize());
  86. ANKI_TRACE_INC_COUNTER(GpuSceneMicroPatchUploadData, m_crntFramePatchData.getSizeInBytes());
  87. RebarAllocation headersToken;
  88. void* mapped = RebarTransientMemoryPool::getSingleton().allocateFrame(m_crntFramePatchHeaders.getSizeInBytes(), headersToken);
  89. memcpy(mapped, &m_crntFramePatchHeaders[0], m_crntFramePatchHeaders.getSizeInBytes());
  90. RebarAllocation dataToken;
  91. mapped = RebarTransientMemoryPool::getSingleton().allocateFrame(m_crntFramePatchData.getSizeInBytes(), dataToken);
  92. memcpy(mapped, &m_crntFramePatchData[0], m_crntFramePatchData.getSizeInBytes());
  93. cmdb.bindStorageBuffer(0, 0, RebarTransientMemoryPool::getSingleton().getBuffer(), headersToken.m_offset, headersToken.m_range);
  94. cmdb.bindStorageBuffer(0, 1, RebarTransientMemoryPool::getSingleton().getBuffer(), dataToken.m_offset, dataToken.m_range);
  95. cmdb.bindStorageBuffer(0, 2, GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
  96. cmdb.bindShaderProgram(m_grProgram);
  97. const U32 workgroupCountX = m_crntFramePatchHeaders.getSize();
  98. cmdb.dispatchCompute(workgroupCountX, 1, 1);
  99. // Cleanup to prepare for the new frame
  100. U32* data;
  101. U32 size, storage;
  102. m_crntFramePatchData.moveAndReset(data, size, storage);
  103. PatchHeader* datah;
  104. m_crntFramePatchHeaders.moveAndReset(datah, size, storage);
  105. }
  106. } // end namespace anki