MeshResource.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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/Resource/MeshResource.h>
  6. #include <AnKi/Resource/ResourceManager.h>
  7. #include <AnKi/Resource/MeshBinaryLoader.h>
  8. #include <AnKi/Resource/AsyncLoader.h>
  9. #include <AnKi/Util/Functions.h>
  10. #include <AnKi/Util/Filesystem.h>
  11. namespace anki {
  12. // Forward
  13. extern BoolCVar g_meshletRenderingCVar;
  14. class MeshResource::LoadContext
  15. {
  16. public:
  17. MeshResourcePtr m_mesh;
  18. MeshBinaryLoader m_loader;
  19. LoadContext(MeshResource* mesh)
  20. : m_mesh(mesh)
  21. , m_loader(&ResourceMemoryPool::getSingleton())
  22. {
  23. }
  24. };
  25. /// Mesh upload async task.
  26. class MeshResource::LoadTask : public AsyncLoaderTask
  27. {
  28. public:
  29. MeshResource::LoadContext m_ctx;
  30. LoadTask(MeshResource* mesh)
  31. : m_ctx(mesh)
  32. {
  33. }
  34. Error operator()([[maybe_unused]] AsyncLoaderTaskContext& ctx) final
  35. {
  36. return m_ctx.m_mesh->loadAsync(m_ctx.m_loader);
  37. }
  38. static BaseMemoryPool& getMemoryPool()
  39. {
  40. return ResourceMemoryPool::getSingleton();
  41. }
  42. };
  43. MeshResource::MeshResource()
  44. {
  45. }
  46. MeshResource::~MeshResource()
  47. {
  48. for(Lod& lod : m_lods)
  49. {
  50. UnifiedGeometryBuffer::getSingleton().deferredFree(lod.m_indexBufferAllocationToken);
  51. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  52. {
  53. UnifiedGeometryBuffer::getSingleton().deferredFree(lod.m_vertexBuffersAllocationToken[stream]);
  54. }
  55. }
  56. }
  57. Error MeshResource::load(const ResourceFilename& filename, Bool async)
  58. {
  59. UniquePtr<LoadTask> task;
  60. LoadContext* ctx;
  61. LoadContext localCtx(this);
  62. String basename;
  63. getFilepathFilename(filename, basename);
  64. const Bool rayTracingEnabled = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled;
  65. if(async)
  66. {
  67. task.reset(ResourceManager::getSingleton().getAsyncLoader().newTask<LoadTask>(this));
  68. ctx = &task->m_ctx;
  69. }
  70. else
  71. {
  72. task.reset(nullptr);
  73. ctx = &localCtx;
  74. }
  75. // Open file
  76. MeshBinaryLoader& loader = ctx->m_loader;
  77. ANKI_CHECK(loader.load(filename));
  78. const MeshBinaryHeader& header = loader.getHeader();
  79. // Misc
  80. m_indexType = header.m_indexType;
  81. m_aabb.setMin(header.m_boundingVolume.m_aabbMin);
  82. m_aabb.setMax(header.m_boundingVolume.m_aabbMax);
  83. m_positionsScale = header.m_vertexAttributes[VertexStreamId::kPosition].m_scale[0];
  84. m_positionsTranslation = Vec3(&header.m_vertexAttributes[VertexStreamId::kPosition].m_translation[0]);
  85. // Submeshes
  86. m_subMeshes.resize(header.m_subMeshCount);
  87. for(U32 i = 0; i < m_subMeshes.getSize(); ++i)
  88. {
  89. for(U32 lod = 0; lod < header.m_lodCount; ++lod)
  90. {
  91. m_subMeshes[i].m_firstIndices[lod] = loader.getSubMeshes()[i].m_lods[lod].m_firstIndex;
  92. m_subMeshes[i].m_indexCounts[lod] = loader.getSubMeshes()[i].m_lods[lod].m_indexCount;
  93. m_subMeshes[i].m_firstMeshlet[lod] = loader.getSubMeshes()[i].m_lods[lod].m_firstMeshlet;
  94. m_subMeshes[i].m_meshletCounts[lod] = loader.getSubMeshes()[i].m_lods[lod].m_meshletCount;
  95. }
  96. m_subMeshes[i].m_aabb.setMin(loader.getSubMeshes()[i].m_boundingVolume.m_aabbMin);
  97. m_subMeshes[i].m_aabb.setMax(loader.getSubMeshes()[i].m_boundingVolume.m_aabbMax);
  98. }
  99. // LODs
  100. m_lods.resize(header.m_lodCount);
  101. for(I32 l = I32(header.m_lodCount - 1); l >= 0; --l)
  102. {
  103. Lod& lod = m_lods[l];
  104. // Index stuff
  105. lod.m_indexCount = header.m_indexCounts[l];
  106. ANKI_ASSERT((lod.m_indexCount % 3) == 0 && "Expecting triangles");
  107. const PtrSize indexBufferSize = PtrSize(lod.m_indexCount) * getIndexSize(m_indexType);
  108. lod.m_indexBufferAllocationToken = UnifiedGeometryBuffer::getSingleton().allocate(indexBufferSize, getIndexSize(m_indexType));
  109. // Vertex stuff
  110. lod.m_vertexCount = header.m_vertexCounts[l];
  111. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  112. {
  113. if(header.m_vertexAttributes[stream].m_format == Format::kNone)
  114. {
  115. continue;
  116. }
  117. m_presentVertStreams |= VertexStreamMask(1 << stream);
  118. lod.m_vertexBuffersAllocationToken[stream] =
  119. UnifiedGeometryBuffer::getSingleton().allocateFormat(kMeshRelatedVertexStreamFormats[stream], lod.m_vertexCount);
  120. }
  121. // Meshlet
  122. if(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar.get())
  123. {
  124. const PtrSize meshletIndicesSize = header.m_meshletPrimitiveCounts[l] * sizeof(U8Vec4);
  125. lod.m_meshletIndices = UnifiedGeometryBuffer::getSingleton().allocate(meshletIndicesSize, sizeof(U8Vec4));
  126. const PtrSize meshletBoundingVolumesSize = header.m_meshletCounts[l] * sizeof(MeshletBoundingVolume);
  127. lod.m_meshletBoundingVolumes = UnifiedGeometryBuffer::getSingleton().allocate(meshletBoundingVolumesSize, sizeof(MeshletBoundingVolume));
  128. const PtrSize meshletGeomDescriptorsSize = header.m_meshletCounts[l] * sizeof(MeshletGeometryDescriptor);
  129. lod.m_meshletGeometryDescriptors =
  130. UnifiedGeometryBuffer::getSingleton().allocate(meshletGeomDescriptorsSize, sizeof(MeshletGeometryDescriptor));
  131. lod.m_meshletCount = header.m_meshletCounts[l];
  132. }
  133. // BLAS
  134. if(rayTracingEnabled)
  135. {
  136. AccelerationStructureInitInfo inf(ResourceString().sprintf("%s_%s", "Blas", basename.cstr()));
  137. inf.m_type = AccelerationStructureType::kBottomLevel;
  138. inf.m_bottomLevel.m_indexBuffer = &UnifiedGeometryBuffer::getSingleton().getBuffer();
  139. inf.m_bottomLevel.m_indexBufferOffset = lod.m_indexBufferAllocationToken.getOffset();
  140. inf.m_bottomLevel.m_indexCount = lod.m_indexCount;
  141. inf.m_bottomLevel.m_indexType = m_indexType;
  142. inf.m_bottomLevel.m_positionBuffer = &UnifiedGeometryBuffer::getSingleton().getBuffer();
  143. inf.m_bottomLevel.m_positionBufferOffset = lod.m_vertexBuffersAllocationToken[VertexStreamId::kPosition].getOffset();
  144. inf.m_bottomLevel.m_positionStride = getFormatInfo(kMeshRelatedVertexStreamFormats[VertexStreamId::kPosition]).m_texelSize;
  145. inf.m_bottomLevel.m_positionsFormat = kMeshRelatedVertexStreamFormats[VertexStreamId::kPosition];
  146. inf.m_bottomLevel.m_positionCount = lod.m_vertexCount;
  147. lod.m_blas = GrManager::getSingleton().newAccelerationStructure(inf);
  148. }
  149. }
  150. // Clear the buffers
  151. if(async)
  152. {
  153. CommandBufferInitInfo cmdbinit("MeshResourceClear");
  154. cmdbinit.m_flags = CommandBufferFlag::kSmallBatch | CommandBufferFlag::kGeneralWork;
  155. CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbinit);
  156. for(const Lod& lod : m_lods)
  157. {
  158. cmdb->fillBuffer(lod.m_indexBufferAllocationToken, 0);
  159. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  160. {
  161. if(header.m_vertexAttributes[stream].m_format != Format::kNone)
  162. {
  163. cmdb->fillBuffer(lod.m_vertexBuffersAllocationToken[stream], 0);
  164. }
  165. }
  166. if(lod.m_meshletIndices.isValid())
  167. {
  168. cmdb->fillBuffer(lod.m_meshletIndices, 0);
  169. cmdb->fillBuffer(lod.m_meshletBoundingVolumes, 0);
  170. cmdb->fillBuffer(lod.m_meshletGeometryDescriptors, 0);
  171. }
  172. }
  173. const BufferBarrierInfo barrier = {&UnifiedGeometryBuffer::getSingleton().getBuffer(), BufferUsageBit::kTransferDestination,
  174. BufferUsageBit::kVertex, 0, kMaxPtrSize};
  175. cmdb->setPipelineBarrier({}, {&barrier, 1}, {});
  176. cmdb->flush();
  177. }
  178. // Submit the loading task
  179. if(async)
  180. {
  181. ResourceManager::getSingleton().getAsyncLoader().submitTask(task.get());
  182. LoadTask* pTask;
  183. task.moveAndReset(pTask);
  184. }
  185. else
  186. {
  187. ANKI_CHECK(loadAsync(loader));
  188. }
  189. return Error::kNone;
  190. }
  191. Error MeshResource::loadAsync(MeshBinaryLoader& loader) const
  192. {
  193. GrManager& gr = GrManager::getSingleton();
  194. TransferGpuAllocator& transferAlloc = ResourceManager::getSingleton().getTransferGpuAllocator();
  195. Array<TransferGpuAllocatorHandle, kMaxLodCount*(U32(VertexStreamId::kMeshRelatedCount) + 1 + 3)> handles;
  196. U32 handleCount = 0;
  197. Buffer* unifiedGeometryBuffer = &UnifiedGeometryBuffer::getSingleton().getBuffer();
  198. const BufferUsageBit unifiedGeometryBufferNonTransferUsage = unifiedGeometryBuffer->getBufferUsage() ^ BufferUsageBit::kTransferDestination;
  199. CommandBufferInitInfo cmdbinit;
  200. cmdbinit.m_flags = CommandBufferFlag::kSmallBatch | CommandBufferFlag::kGeneralWork;
  201. CommandBufferPtr cmdb = gr.newCommandBuffer(cmdbinit);
  202. // Set transfer to transfer barrier because of the clear that happened while sync loading
  203. const BufferBarrierInfo barrier = {unifiedGeometryBuffer, unifiedGeometryBufferNonTransferUsage, BufferUsageBit::kTransferDestination, 0,
  204. kMaxPtrSize};
  205. cmdb->setPipelineBarrier({}, {&barrier, 1}, {});
  206. // Upload index and vertex buffers
  207. for(U32 lodIdx = 0; lodIdx < m_lods.getSize(); ++lodIdx)
  208. {
  209. const Lod& lod = m_lods[lodIdx];
  210. // Upload index buffer
  211. {
  212. TransferGpuAllocatorHandle& handle = handles[handleCount++];
  213. const PtrSize indexBufferSize = PtrSize(lod.m_indexCount) * getIndexSize(m_indexType);
  214. ANKI_CHECK(transferAlloc.allocate(indexBufferSize, handle));
  215. void* data = handle.getMappedMemory();
  216. ANKI_ASSERT(data);
  217. ANKI_CHECK(loader.storeIndexBuffer(lodIdx, data, indexBufferSize));
  218. cmdb->copyBufferToBuffer(&handle.getBuffer(), handle.getOffset(), unifiedGeometryBuffer, lod.m_indexBufferAllocationToken.getOffset(),
  219. handle.getRange());
  220. }
  221. // Upload vert buffers
  222. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  223. {
  224. if(!(m_presentVertStreams & VertexStreamMask(1 << stream)))
  225. {
  226. continue;
  227. }
  228. TransferGpuAllocatorHandle& handle = handles[handleCount++];
  229. const PtrSize vertexBufferSize = PtrSize(lod.m_vertexCount) * getFormatInfo(kMeshRelatedVertexStreamFormats[stream]).m_texelSize;
  230. ANKI_CHECK(transferAlloc.allocate(vertexBufferSize, handle));
  231. U8* data = static_cast<U8*>(handle.getMappedMemory());
  232. ANKI_ASSERT(data);
  233. // Load to staging
  234. ANKI_CHECK(loader.storeVertexBuffer(lodIdx, U32(stream), data, vertexBufferSize));
  235. // Copy
  236. cmdb->copyBufferToBuffer(&handle.getBuffer(), handle.getOffset(), unifiedGeometryBuffer,
  237. lod.m_vertexBuffersAllocationToken[stream].getOffset(), handle.getRange());
  238. }
  239. if(lod.m_meshletBoundingVolumes.isValid())
  240. {
  241. // Indices
  242. TransferGpuAllocatorHandle& handle = handles[handleCount++];
  243. const PtrSize primitivesSize = lod.m_meshletIndices.getAllocatedSize();
  244. ANKI_CHECK(transferAlloc.allocate(primitivesSize, handle));
  245. ANKI_CHECK(loader.storeMeshletIndicesBuffer(lodIdx, handle.getMappedMemory(), primitivesSize));
  246. cmdb->copyBufferToBuffer(&handle.getBuffer(), handle.getOffset(), unifiedGeometryBuffer, lod.m_meshletIndices.getOffset(),
  247. handle.getRange());
  248. // Meshlets
  249. ResourceDynamicArray<MeshBinaryMeshlet> binaryMeshlets;
  250. binaryMeshlets.resize(loader.getHeader().m_meshletCounts[lodIdx]);
  251. ANKI_CHECK(loader.storeMeshletBuffer(lodIdx, WeakArray(binaryMeshlets)));
  252. TransferGpuAllocatorHandle& handle2 = handles[handleCount++];
  253. ANKI_CHECK(transferAlloc.allocate(lod.m_meshletBoundingVolumes.getAllocatedSize(), handle2));
  254. WeakArray<MeshletBoundingVolume> outMeshletBoundingVolumes(static_cast<MeshletBoundingVolume*>(handle2.getMappedMemory()),
  255. loader.getHeader().m_meshletCounts[lodIdx]);
  256. TransferGpuAllocatorHandle& handle3 = handles[handleCount++];
  257. ANKI_CHECK(transferAlloc.allocate(lod.m_meshletGeometryDescriptors.getAllocatedSize(), handle3));
  258. WeakArray<MeshletGeometryDescriptor> outMeshletGeomDescriptors(static_cast<MeshletGeometryDescriptor*>(handle3.getMappedMemory()),
  259. loader.getHeader().m_meshletCounts[lodIdx]);
  260. for(U32 i = 0; i < binaryMeshlets.getSize(); ++i)
  261. {
  262. const MeshBinaryMeshlet& inMeshlet = binaryMeshlets[i];
  263. MeshletGeometryDescriptor& outMeshletGeom = outMeshletGeomDescriptors[i];
  264. MeshletBoundingVolume& outMeshletBoundingVolume = outMeshletBoundingVolumes[i];
  265. outMeshletBoundingVolume = {};
  266. outMeshletGeom = {};
  267. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  268. {
  269. if(!(m_presentVertStreams & VertexStreamMask(1u << stream)))
  270. {
  271. continue;
  272. }
  273. outMeshletGeom.m_vertexOffsets[U32(stream)] =
  274. lod.m_vertexBuffersAllocationToken[stream].getOffset() / getFormatInfo(kMeshRelatedVertexStreamFormats[stream]).m_texelSize
  275. + inMeshlet.m_firstVertex;
  276. }
  277. outMeshletGeom.m_firstPrimitive =
  278. lod.m_meshletIndices.getOffset() / getFormatInfo(kMeshletPrimitiveFormat).m_texelSize + inMeshlet.m_firstPrimitive;
  279. outMeshletGeom.m_primitiveCount_R16_Uint_vertexCount_R16_Uint = (inMeshlet.m_primitiveCount << 16u) | inMeshlet.m_vertexCount;
  280. outMeshletGeom.m_positionTranslation = m_positionsTranslation;
  281. outMeshletGeom.m_positionScale = m_positionsScale;
  282. outMeshletBoundingVolume.m_aabbMin = inMeshlet.m_boundingVolume.m_aabbMin;
  283. outMeshletBoundingVolume.m_aabbMax = inMeshlet.m_boundingVolume.m_aabbMax;
  284. outMeshletBoundingVolume.m_coneDirection_R8G8B8_Snorm_cosHalfAngle_R8_Snorm =
  285. packSnorm4x8(Vec4(inMeshlet.m_coneDirection, cos(inMeshlet.m_coneAngle / 2.0f)));
  286. outMeshletBoundingVolume.m_coneApex = inMeshlet.m_coneApex;
  287. outMeshletBoundingVolume.m_sphereRadius =
  288. ((outMeshletBoundingVolume.m_aabbMin + outMeshletBoundingVolume.m_aabbMax) / 2.0f - outMeshletBoundingVolume.m_aabbMax)
  289. .getLength();
  290. }
  291. cmdb->copyBufferToBuffer(&handle2.getBuffer(), handle2.getOffset(), unifiedGeometryBuffer, lod.m_meshletBoundingVolumes.getOffset(),
  292. handle2.getRange());
  293. cmdb->copyBufferToBuffer(&handle3.getBuffer(), handle3.getOffset(), unifiedGeometryBuffer, lod.m_meshletGeometryDescriptors.getOffset(),
  294. handle3.getRange());
  295. }
  296. }
  297. if(gr.getDeviceCapabilities().m_rayTracingEnabled)
  298. {
  299. // Build BLASes
  300. // Set the barriers
  301. BufferBarrierInfo bufferBarrier;
  302. bufferBarrier.m_buffer = unifiedGeometryBuffer;
  303. bufferBarrier.m_offset = 0;
  304. bufferBarrier.m_range = kMaxPtrSize;
  305. bufferBarrier.m_previousUsage = BufferUsageBit::kTransferDestination;
  306. bufferBarrier.m_nextUsage = unifiedGeometryBufferNonTransferUsage;
  307. Array<AccelerationStructureBarrierInfo, kMaxLodCount> asBarriers;
  308. for(U32 lodIdx = 0; lodIdx < m_lods.getSize(); ++lodIdx)
  309. {
  310. asBarriers[lodIdx].m_as = m_lods[lodIdx].m_blas.get();
  311. asBarriers[lodIdx].m_previousUsage = AccelerationStructureUsageBit::kNone;
  312. asBarriers[lodIdx].m_nextUsage = AccelerationStructureUsageBit::kBuild;
  313. }
  314. cmdb->setPipelineBarrier({}, {&bufferBarrier, 1}, {&asBarriers[0], m_lods.getSize()});
  315. // Build BLASes
  316. for(U32 lodIdx = 0; lodIdx < m_lods.getSize(); ++lodIdx)
  317. {
  318. // TODO find a temp buffer
  319. BufferInitInfo buffInit("BLAS scratch");
  320. buffInit.m_size = m_lods[lodIdx].m_blas->getBuildScratchBufferSize();
  321. buffInit.m_usage = BufferUsageBit::kAccelerationStructureBuildScratch;
  322. BufferPtr scratchBuff = GrManager::getSingleton().newBuffer(buffInit);
  323. cmdb->buildAccelerationStructure(m_lods[lodIdx].m_blas.get(), scratchBuff.get(), 0);
  324. }
  325. // Barriers again
  326. for(U32 lodIdx = 0; lodIdx < m_lods.getSize(); ++lodIdx)
  327. {
  328. asBarriers[lodIdx].m_as = m_lods[lodIdx].m_blas.get();
  329. asBarriers[lodIdx].m_previousUsage = AccelerationStructureUsageBit::kBuild;
  330. asBarriers[lodIdx].m_nextUsage = AccelerationStructureUsageBit::kAllRead;
  331. }
  332. cmdb->setPipelineBarrier({}, {}, {&asBarriers[0], m_lods.getSize()});
  333. }
  334. else
  335. {
  336. // Only set a barrier
  337. BufferBarrierInfo bufferBarrier;
  338. bufferBarrier.m_buffer = unifiedGeometryBuffer;
  339. bufferBarrier.m_offset = 0;
  340. bufferBarrier.m_range = kMaxPtrSize;
  341. bufferBarrier.m_previousUsage = BufferUsageBit::kTransferDestination;
  342. bufferBarrier.m_nextUsage = unifiedGeometryBufferNonTransferUsage;
  343. cmdb->setPipelineBarrier({}, {&bufferBarrier, 1}, {});
  344. }
  345. // Finalize
  346. FencePtr fence;
  347. cmdb->flush({}, &fence);
  348. for(U32 i = 0; i < handleCount; ++i)
  349. {
  350. transferAlloc.release(handles[i], fence);
  351. }
  352. return Error::kNone;
  353. }
  354. } // end namespace anki