2
0

MeshResource.cpp 11 KB

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