MeshResource.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Copyright (C) 2009-2022, 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/Core/GpuMemoryPools.h>
  10. #include <AnKi/Util/Functions.h>
  11. #include <AnKi/Util/Filesystem.h>
  12. namespace anki {
  13. class MeshResource::LoadContext
  14. {
  15. public:
  16. MeshResourcePtr m_mesh;
  17. MeshBinaryLoader m_loader;
  18. LoadContext(const MeshResourcePtr& mesh, GenericMemoryPoolAllocator<U8> alloc)
  19. : m_mesh(mesh)
  20. , m_loader(&mesh->getManager(), alloc)
  21. {
  22. }
  23. };
  24. /// Mesh upload async task.
  25. class MeshResource::LoadTask : public AsyncLoaderTask
  26. {
  27. public:
  28. MeshResource::LoadContext m_ctx;
  29. LoadTask(const MeshResourcePtr& mesh)
  30. : m_ctx(mesh, mesh->getManager().getAsyncLoader().getAllocator())
  31. {
  32. }
  33. Error operator()([[maybe_unused]] AsyncLoaderTaskContext& ctx) final
  34. {
  35. return m_ctx.m_mesh->loadAsync(m_ctx.m_loader);
  36. }
  37. GenericMemoryPoolAllocator<U8> getAllocator() const
  38. {
  39. return m_ctx.m_mesh->getManager().getAsyncLoader().getAllocator();
  40. }
  41. };
  42. MeshResource::MeshResource(ResourceManager* manager)
  43. : ResourceObject(manager)
  44. {
  45. memset(&m_meshGpuDescriptor, 0, sizeof(m_meshGpuDescriptor));
  46. }
  47. MeshResource::~MeshResource()
  48. {
  49. m_subMeshes.destroy(getAllocator());
  50. m_vertexBufferInfos.destroy(getAllocator());
  51. if(m_vertexBuffersOffset != MAX_PTR_SIZE)
  52. {
  53. getManager().getVertexGpuMemory().free(m_vertexBuffersSize, m_vertexBuffersOffset);
  54. }
  55. if(m_indexBufferOffset != MAX_PTR_SIZE)
  56. {
  57. const PtrSize indexBufferSize = PtrSize(m_indexCount) * ((m_indexType == IndexType::U32) ? 4 : 2);
  58. getManager().getVertexGpuMemory().free(indexBufferSize, m_indexBufferOffset);
  59. }
  60. }
  61. Bool MeshResource::isCompatible(const MeshResource& other) const
  62. {
  63. return hasBoneWeights() == other.hasBoneWeights() && getSubMeshCount() == other.getSubMeshCount();
  64. }
  65. Error MeshResource::load(const ResourceFilename& filename, Bool async)
  66. {
  67. UniquePtr<LoadTask> task;
  68. LoadContext* ctx;
  69. LoadContext localCtx(MeshResourcePtr(this), getTempAllocator());
  70. StringAuto basename(getTempAllocator());
  71. getFilepathFilename(filename, basename);
  72. const Bool rayTracingEnabled = getManager().getGrManager().getDeviceCapabilities().m_rayTracingEnabled;
  73. if(async)
  74. {
  75. task.reset(getManager().getAsyncLoader().newTask<LoadTask>(MeshResourcePtr(this)));
  76. ctx = &task->m_ctx;
  77. }
  78. else
  79. {
  80. task.reset(nullptr);
  81. ctx = &localCtx;
  82. }
  83. // Open file
  84. MeshBinaryLoader& loader = ctx->m_loader;
  85. ANKI_CHECK(loader.load(filename));
  86. const MeshBinaryHeader& header = loader.getHeader();
  87. //
  88. // Submeshes
  89. //
  90. m_subMeshes.create(getAllocator(), header.m_subMeshCount);
  91. for(U32 i = 0; i < m_subMeshes.getSize(); ++i)
  92. {
  93. m_subMeshes[i].m_firstIndex = loader.getSubMeshes()[i].m_firstIndex;
  94. m_subMeshes[i].m_indexCount = loader.getSubMeshes()[i].m_indexCount;
  95. m_subMeshes[i].m_aabb.setMin(loader.getSubMeshes()[i].m_aabbMin);
  96. m_subMeshes[i].m_aabb.setMax(loader.getSubMeshes()[i].m_aabbMax);
  97. }
  98. //
  99. // Index stuff
  100. //
  101. m_indexCount = header.m_totalIndexCount;
  102. ANKI_ASSERT((m_indexCount % 3) == 0 && "Expecting triangles");
  103. m_indexType = header.m_indexType;
  104. const PtrSize indexBufferSize = PtrSize(m_indexCount) * ((m_indexType == IndexType::U32) ? 4 : 2);
  105. ANKI_CHECK(getManager().getVertexGpuMemory().allocate(indexBufferSize, m_indexBufferOffset));
  106. //
  107. // Vertex stuff
  108. //
  109. m_vertexCount = header.m_totalVertexCount;
  110. m_vertexBufferInfos.create(getAllocator(), header.m_vertexBufferCount);
  111. m_vertexBuffersSize = 0;
  112. for(U32 i = 0; i < header.m_vertexBufferCount; ++i)
  113. {
  114. alignRoundUp(MESH_BINARY_BUFFER_ALIGNMENT, m_vertexBuffersSize);
  115. m_vertexBufferInfos[i].m_offset = m_vertexBuffersSize;
  116. m_vertexBufferInfos[i].m_stride = header.m_vertexBuffers[i].m_vertexStride;
  117. m_vertexBuffersSize += m_vertexCount * m_vertexBufferInfos[i].m_stride;
  118. }
  119. ANKI_CHECK(getManager().getVertexGpuMemory().allocate(m_vertexBuffersSize, m_vertexBuffersOffset));
  120. // Readjust the individual offset now that we have a global offset
  121. for(U32 i = 0; i < header.m_vertexBufferCount; ++i)
  122. {
  123. m_vertexBufferInfos[i].m_offset += m_vertexBuffersOffset;
  124. }
  125. for(VertexAttributeId attrib = VertexAttributeId::FIRST; attrib < VertexAttributeId::COUNT; ++attrib)
  126. {
  127. AttribInfo& out = m_attributes[attrib];
  128. const MeshBinaryVertexAttribute& in = header.m_vertexAttributes[attrib];
  129. if(!!in.m_format)
  130. {
  131. out.m_format = in.m_format;
  132. out.m_relativeOffset = in.m_relativeOffset;
  133. out.m_buffIdx = U8(in.m_bufferBinding);
  134. ANKI_ASSERT(in.m_scale == 1.0f && "Not supported ATM");
  135. }
  136. }
  137. // Other
  138. m_aabb.setMin(header.m_aabbMin);
  139. m_aabb.setMax(header.m_aabbMax);
  140. m_vertexBuffer = getManager().getVertexGpuMemory().getVertexBuffer();
  141. //
  142. // Clear the buffers
  143. //
  144. if(async)
  145. {
  146. CommandBufferInitInfo cmdbinit;
  147. cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::GENERAL_WORK;
  148. CommandBufferPtr cmdb = getManager().getGrManager().newCommandBuffer(cmdbinit);
  149. cmdb->fillBuffer(m_vertexBuffer, m_vertexBuffersOffset, m_vertexBuffersSize, 0);
  150. cmdb->fillBuffer(m_vertexBuffer, m_indexBufferOffset, indexBufferSize, 0);
  151. cmdb->setBufferBarrier(m_vertexBuffer, BufferUsageBit::TRANSFER_DESTINATION, BufferUsageBit::VERTEX, 0,
  152. MAX_PTR_SIZE);
  153. cmdb->flush();
  154. }
  155. //
  156. // Create the BLAS
  157. //
  158. if(rayTracingEnabled)
  159. {
  160. AccelerationStructureInitInfo inf(StringAuto(getTempAllocator()).sprintf("%s_%s", "Blas", basename.cstr()));
  161. inf.m_type = AccelerationStructureType::BOTTOM_LEVEL;
  162. inf.m_bottomLevel.m_indexBuffer = m_vertexBuffer;
  163. inf.m_bottomLevel.m_indexBufferOffset = m_indexBufferOffset;
  164. inf.m_bottomLevel.m_indexCount = m_indexCount;
  165. inf.m_bottomLevel.m_indexType = m_indexType;
  166. U32 bufferIdx;
  167. Format format;
  168. U32 relativeOffset;
  169. getVertexAttributeInfo(VertexAttributeId::POSITION, bufferIdx, format, relativeOffset);
  170. BufferPtr buffer;
  171. PtrSize offset;
  172. PtrSize stride;
  173. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  174. inf.m_bottomLevel.m_positionBuffer = buffer;
  175. inf.m_bottomLevel.m_positionBufferOffset = offset;
  176. inf.m_bottomLevel.m_positionStride = U32(stride);
  177. inf.m_bottomLevel.m_positionsFormat = format;
  178. inf.m_bottomLevel.m_positionCount = m_vertexCount;
  179. m_blas = getManager().getGrManager().newAccelerationStructure(inf);
  180. }
  181. // Fill the GPU descriptor
  182. if(rayTracingEnabled)
  183. {
  184. m_meshGpuDescriptor.m_indexBufferPtr = m_vertexBuffer->getGpuAddress() + m_indexBufferOffset;
  185. U32 bufferIdx;
  186. Format format;
  187. U32 relativeOffset;
  188. getVertexAttributeInfo(VertexAttributeId::POSITION, bufferIdx, format, relativeOffset);
  189. BufferPtr buffer;
  190. PtrSize offset;
  191. PtrSize stride;
  192. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  193. m_meshGpuDescriptor.m_vertexBufferPtrs[VertexAttributeBufferId::POSITION] = buffer->getGpuAddress() + offset;
  194. getVertexAttributeInfo(VertexAttributeId::NORMAL, bufferIdx, format, relativeOffset);
  195. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  196. m_meshGpuDescriptor.m_vertexBufferPtrs[VertexAttributeBufferId::NORMAL_TANGENT_UV0] =
  197. buffer->getGpuAddress() + offset;
  198. if(hasBoneWeights())
  199. {
  200. getVertexAttributeInfo(VertexAttributeId::BONE_WEIGHTS, bufferIdx, format, relativeOffset);
  201. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  202. m_meshGpuDescriptor.m_vertexBufferPtrs[VertexAttributeBufferId::BONE] = buffer->getGpuAddress() + offset;
  203. }
  204. m_meshGpuDescriptor.m_indexCount = m_indexCount;
  205. m_meshGpuDescriptor.m_vertexCount = m_vertexCount;
  206. m_meshGpuDescriptor.m_aabbMin = header.m_aabbMin;
  207. m_meshGpuDescriptor.m_aabbMax = header.m_aabbMax;
  208. }
  209. // Submit the loading task
  210. if(async)
  211. {
  212. getManager().getAsyncLoader().submitTask(task.get());
  213. LoadTask* pTask;
  214. task.moveAndReset(pTask);
  215. }
  216. else
  217. {
  218. ANKI_CHECK(loadAsync(loader));
  219. }
  220. return Error::NONE;
  221. }
  222. Error MeshResource::loadAsync(MeshBinaryLoader& loader) const
  223. {
  224. GrManager& gr = getManager().getGrManager();
  225. TransferGpuAllocator& transferAlloc = getManager().getTransferGpuAllocator();
  226. Array<TransferGpuAllocatorHandle, 2> handles;
  227. CommandBufferInitInfo cmdbinit;
  228. cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::GENERAL_WORK;
  229. CommandBufferPtr cmdb = gr.newCommandBuffer(cmdbinit);
  230. // Set barriers
  231. cmdb->setBufferBarrier(m_vertexBuffer, BufferUsageBit::VERTEX, BufferUsageBit::TRANSFER_DESTINATION, 0,
  232. MAX_PTR_SIZE);
  233. // Write index buffer
  234. {
  235. const PtrSize indexBufferSize = PtrSize(m_indexCount) * ((m_indexType == IndexType::U32) ? 4 : 2);
  236. ANKI_CHECK(transferAlloc.allocate(indexBufferSize, handles[1]));
  237. void* data = handles[1].getMappedMemory();
  238. ANKI_ASSERT(data);
  239. ANKI_CHECK(loader.storeIndexBuffer(data, indexBufferSize));
  240. cmdb->copyBufferToBuffer(handles[1].getBuffer(), handles[1].getOffset(), m_vertexBuffer, m_indexBufferOffset,
  241. handles[1].getRange());
  242. }
  243. // Write vert buff
  244. {
  245. ANKI_CHECK(transferAlloc.allocate(m_vertexBuffersSize, handles[0]));
  246. U8* data = static_cast<U8*>(handles[0].getMappedMemory());
  247. ANKI_ASSERT(data);
  248. // Load to staging
  249. PtrSize offset = 0;
  250. for(U32 i = 0; i < m_vertexBufferInfos.getSize(); ++i)
  251. {
  252. alignRoundUp(MESH_BINARY_BUFFER_ALIGNMENT, offset);
  253. ANKI_CHECK(
  254. loader.storeVertexBuffer(i, data + offset, PtrSize(m_vertexBufferInfos[i].m_stride) * m_vertexCount));
  255. offset += PtrSize(m_vertexBufferInfos[i].m_stride) * m_vertexCount;
  256. }
  257. ANKI_ASSERT(offset == m_vertexBuffersSize);
  258. // Copy
  259. cmdb->copyBufferToBuffer(handles[0].getBuffer(), handles[0].getOffset(), m_vertexBuffer, m_vertexBuffersOffset,
  260. handles[0].getRange());
  261. }
  262. // Build the BLAS
  263. if(gr.getDeviceCapabilities().m_rayTracingEnabled)
  264. {
  265. cmdb->setBufferBarrier(m_vertexBuffer, BufferUsageBit::TRANSFER_DESTINATION,
  266. BufferUsageBit::ACCELERATION_STRUCTURE_BUILD | BufferUsageBit::VERTEX
  267. | BufferUsageBit::INDEX,
  268. 0, MAX_PTR_SIZE);
  269. cmdb->setAccelerationStructureBarrier(m_blas, AccelerationStructureUsageBit::NONE,
  270. AccelerationStructureUsageBit::BUILD);
  271. cmdb->buildAccelerationStructure(m_blas);
  272. cmdb->setAccelerationStructureBarrier(m_blas, AccelerationStructureUsageBit::BUILD,
  273. AccelerationStructureUsageBit::ALL_READ);
  274. }
  275. else
  276. {
  277. cmdb->setBufferBarrier(m_vertexBuffer, BufferUsageBit::TRANSFER_DESTINATION,
  278. BufferUsageBit::VERTEX | BufferUsageBit::INDEX, 0, MAX_PTR_SIZE);
  279. }
  280. // Finalize
  281. FencePtr fence;
  282. cmdb->flush({}, &fence);
  283. transferAlloc.release(handles[0], fence);
  284. transferAlloc.release(handles[1], fence);
  285. return Error::NONE;
  286. }
  287. } // end namespace anki