MeshResource.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // Copyright (C) 2009-2020, 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/MeshLoader.h>
  8. #include <anki/resource/AsyncLoader.h>
  9. #include <anki/util/Functions.h>
  10. #include <anki/util/Xml.h>
  11. namespace anki
  12. {
  13. class MeshResource::LoadContext
  14. {
  15. public:
  16. MeshResource* m_mesh;
  17. MeshLoader m_loader;
  18. LoadContext(MeshResource* 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(MeshResource* 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. };
  38. MeshResource::MeshResource(ResourceManager* manager)
  39. : ResourceObject(manager)
  40. {
  41. memset(&m_meshGpuDescriptor, 0, sizeof(m_meshGpuDescriptor));
  42. }
  43. MeshResource::~MeshResource()
  44. {
  45. m_subMeshes.destroy(getAllocator());
  46. m_vertBufferInfos.destroy(getAllocator());
  47. }
  48. Bool MeshResource::isCompatible(const MeshResource& other) const
  49. {
  50. return hasBoneWeights() == other.hasBoneWeights() && getSubMeshCount() == other.getSubMeshCount()
  51. && m_texChannelCount == other.m_texChannelCount;
  52. }
  53. Error MeshResource::load(const ResourceFilename& filename, Bool async)
  54. {
  55. LoadTask* task;
  56. LoadContext* ctx;
  57. LoadContext localCtx(this, getTempAllocator());
  58. const Bool rayTracingEnabled = getManager().getGrManager().getDeviceCapabilities().m_rayTracingEnabled;
  59. if(rayTracingEnabled)
  60. {
  61. async = false; // TODO Find a better way
  62. }
  63. if(async)
  64. {
  65. task = getManager().getAsyncLoader().newTask<LoadTask>(this);
  66. ctx = &task->m_ctx;
  67. }
  68. else
  69. {
  70. task = nullptr;
  71. ctx = &localCtx;
  72. }
  73. // Open file
  74. MeshLoader& loader = ctx->m_loader;
  75. ANKI_CHECK(loader.load(filename));
  76. const MeshBinaryFile::Header& header = loader.getHeader();
  77. // Get submeshes
  78. m_subMeshes.create(getAllocator(), header.m_subMeshCount);
  79. for(U32 i = 0; i < m_subMeshes.getSize(); ++i)
  80. {
  81. m_subMeshes[i].m_firstIndex = loader.getSubMeshes()[i].m_firstIndex;
  82. m_subMeshes[i].m_indexCount = loader.getSubMeshes()[i].m_indexCount;
  83. const Vec3 obbCenter = (loader.getSubMeshes()[i].m_aabbMax + loader.getSubMeshes()[i].m_aabbMin) / 2.0f;
  84. const Vec3 obbExtend = loader.getSubMeshes()[i].m_aabbMax - obbCenter;
  85. m_subMeshes[i].m_obb = Obb(obbCenter.xyz0(), Mat3x4::getIdentity(), obbExtend.xyz0());
  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_indexBuff = getManager().getGrManager().newBuffer(
  98. BufferInitInfo(indexBuffSize, indexBufferUsage, BufferMapAccessBit::NONE, "MeshIdx"));
  99. // Vertex stuff
  100. m_vertCount = header.m_totalVertexCount;
  101. m_vertBufferInfos.create(getAllocator(), header.m_vertexBufferCount);
  102. U32 totalVertexBuffSize = 0;
  103. for(U32 i = 0; i < header.m_vertexBufferCount; ++i)
  104. {
  105. alignRoundUp(VERTEX_BUFFER_ALIGNMENT, totalVertexBuffSize);
  106. m_vertBufferInfos[i].m_offset = totalVertexBuffSize;
  107. m_vertBufferInfos[i].m_stride = header.m_vertexBuffers[i].m_vertexStride;
  108. totalVertexBuffSize += m_vertCount * m_vertBufferInfos[i].m_stride;
  109. }
  110. BufferUsageBit vertexBufferUsage = BufferUsageBit::VERTEX | BufferUsageBit::TRANSFER_DESTINATION;
  111. if(rayTracingEnabled)
  112. {
  113. vertexBufferUsage |= BufferUsageBit::ACCELERATION_STRUCTURE_BUILD;
  114. }
  115. m_vertBuff = getManager().getGrManager().newBuffer(
  116. BufferInitInfo(totalVertexBuffSize, vertexBufferUsage, BufferMapAccessBit::NONE, "MeshVert"));
  117. m_texChannelCount = !!header.m_vertexAttributes[VertexAttributeLocation::UV2].m_format ? 2 : 1;
  118. for(VertexAttributeLocation attrib = VertexAttributeLocation::FIRST; attrib < VertexAttributeLocation::COUNT;
  119. ++attrib)
  120. {
  121. AttribInfo& out = m_attribs[attrib];
  122. const MeshBinaryFile::VertexAttribute& in = header.m_vertexAttributes[attrib];
  123. if(!!in.m_format)
  124. {
  125. out.m_fmt = 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. const Vec3 obbCenter = (header.m_aabbMax + header.m_aabbMin) / 2.0f;
  133. const Vec3 obbExtend = header.m_aabbMax - obbCenter;
  134. m_obb = Obb(obbCenter.xyz0(), Mat3x4::getIdentity(), obbExtend.xyz0());
  135. // Clear the buffers
  136. if(!async)
  137. {
  138. CommandBufferInitInfo cmdbinit;
  139. cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH;
  140. CommandBufferPtr cmdb = getManager().getGrManager().newCommandBuffer(cmdbinit);
  141. cmdb->fillBuffer(m_vertBuff, 0, MAX_PTR_SIZE, 0);
  142. cmdb->fillBuffer(m_indexBuff, 0, MAX_PTR_SIZE, 0);
  143. cmdb->setBufferBarrier(m_vertBuff, BufferUsageBit::TRANSFER_DESTINATION, BufferUsageBit::VERTEX, 0,
  144. MAX_PTR_SIZE);
  145. cmdb->setBufferBarrier(m_indexBuff, BufferUsageBit::TRANSFER_DESTINATION, BufferUsageBit::INDEX, 0,
  146. MAX_PTR_SIZE);
  147. cmdb->flush();
  148. }
  149. // Create the BLAS
  150. if(rayTracingEnabled)
  151. {
  152. AccelerationStructureInitInfo inf("Mesh BLAS");
  153. inf.m_type = AccelerationStructureType::BOTTOM_LEVEL;
  154. inf.m_bottomLevel.m_indexBuffer = m_indexBuff;
  155. inf.m_bottomLevel.m_indexBufferOffset = 0;
  156. inf.m_bottomLevel.m_indexCount = m_indexCount;
  157. inf.m_bottomLevel.m_indexType = m_indexType;
  158. U32 bufferIdx;
  159. Format format;
  160. PtrSize relativeOffset;
  161. getVertexAttributeInfo(VertexAttributeLocation::POSITION, bufferIdx, format, relativeOffset);
  162. BufferPtr buffer;
  163. PtrSize offset;
  164. PtrSize stride;
  165. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  166. inf.m_bottomLevel.m_positionBuffer = buffer;
  167. inf.m_bottomLevel.m_positionBufferOffset = offset;
  168. inf.m_bottomLevel.m_positionStride = U32(stride);
  169. inf.m_bottomLevel.m_positionsFormat = format;
  170. inf.m_bottomLevel.m_positionCount = m_vertCount;
  171. m_blas = getManager().getGrManager().newAccelerationStructure(inf);
  172. }
  173. // Fill the GPU descriptor
  174. if(rayTracingEnabled)
  175. {
  176. U32 bufferIdx;
  177. Format format;
  178. PtrSize relativeOffset;
  179. getVertexAttributeInfo(VertexAttributeLocation::POSITION, bufferIdx, format, relativeOffset);
  180. BufferPtr buffer;
  181. PtrSize offset;
  182. PtrSize stride;
  183. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  184. m_meshGpuDescriptor.m_indexBufferPtr = m_indexBuff->getGpuAddress();
  185. m_meshGpuDescriptor.m_positionBufferPtr = buffer->getGpuAddress();
  186. getVertexAttributeInfo(VertexAttributeLocation::NORMAL, bufferIdx, format, relativeOffset);
  187. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  188. m_meshGpuDescriptor.m_mainVertexBufferPtr = buffer->getGpuAddress();
  189. if(hasBoneWeights())
  190. {
  191. getVertexAttributeInfo(VertexAttributeLocation::BONE_WEIGHTS, bufferIdx, format, relativeOffset);
  192. getVertexBufferInfo(bufferIdx, buffer, offset, stride);
  193. m_meshGpuDescriptor.m_boneInfoVertexBufferPtr = buffer->getGpuAddress();
  194. }
  195. m_meshGpuDescriptor.m_indexCount = m_indexCount;
  196. m_meshGpuDescriptor.m_vertexCount = m_vertCount;
  197. m_meshGpuDescriptor.m_aabbMin = header.m_aabbMin;
  198. m_meshGpuDescriptor.m_aabbMax = header.m_aabbMax;
  199. }
  200. // Submit the loading task
  201. if(async)
  202. {
  203. getManager().getAsyncLoader().submitTask(task);
  204. }
  205. else
  206. {
  207. ANKI_CHECK(loadAsync(loader));
  208. }
  209. return Error::NONE;
  210. }
  211. Error MeshResource::loadAsync(MeshLoader& loader) const
  212. {
  213. GrManager& gr = getManager().getGrManager();
  214. TransferGpuAllocator& transferAlloc = getManager().getTransferGpuAllocator();
  215. Array<TransferGpuAllocatorHandle, 2> handles;
  216. CommandBufferInitInfo cmdbinit;
  217. cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::TRANSFER_WORK;
  218. CommandBufferPtr cmdb = gr.newCommandBuffer(cmdbinit);
  219. // Set barriers
  220. cmdb->setBufferBarrier(m_vertBuff, BufferUsageBit::VERTEX, BufferUsageBit::TRANSFER_DESTINATION, 0, MAX_PTR_SIZE);
  221. cmdb->setBufferBarrier(m_indexBuff, BufferUsageBit::INDEX, BufferUsageBit::TRANSFER_DESTINATION, 0, MAX_PTR_SIZE);
  222. // Write index buffer
  223. {
  224. ANKI_CHECK(transferAlloc.allocate(m_indexBuff->getSize(), handles[1]));
  225. void* data = handles[1].getMappedMemory();
  226. ANKI_ASSERT(data);
  227. ANKI_CHECK(loader.storeIndexBuffer(data, m_indexBuff->getSize()));
  228. cmdb->copyBufferToBuffer(handles[1].getBuffer(), handles[1].getOffset(), m_indexBuff, 0, handles[1].getRange());
  229. }
  230. // Write vert buff
  231. {
  232. ANKI_CHECK(transferAlloc.allocate(m_vertBuff->getSize(), handles[0]));
  233. U8* data = static_cast<U8*>(handles[0].getMappedMemory());
  234. ANKI_ASSERT(data);
  235. // Load to staging
  236. PtrSize offset = 0;
  237. for(U32 i = 0; i < m_vertBufferInfos.getSize(); ++i)
  238. {
  239. alignRoundUp(VERTEX_BUFFER_ALIGNMENT, offset);
  240. ANKI_CHECK(
  241. loader.storeVertexBuffer(i, data + offset, PtrSize(m_vertBufferInfos[i].m_stride) * m_vertCount));
  242. offset += PtrSize(m_vertBufferInfos[i].m_stride) * m_vertCount;
  243. }
  244. ANKI_ASSERT(offset == m_vertBuff->getSize());
  245. // Copy
  246. cmdb->copyBufferToBuffer(handles[0].getBuffer(), handles[0].getOffset(), m_vertBuff, 0, handles[0].getRange());
  247. }
  248. // Build the BLAS
  249. if(gr.getDeviceCapabilities().m_rayTracingEnabled)
  250. {
  251. cmdb->setBufferBarrier(m_vertBuff, BufferUsageBit::TRANSFER_DESTINATION,
  252. BufferUsageBit::ACCELERATION_STRUCTURE_BUILD | BufferUsageBit::VERTEX, 0, MAX_PTR_SIZE);
  253. cmdb->setBufferBarrier(m_indexBuff, BufferUsageBit::TRANSFER_DESTINATION,
  254. BufferUsageBit::ACCELERATION_STRUCTURE_BUILD | BufferUsageBit::INDEX, 0, MAX_PTR_SIZE);
  255. cmdb->setAccelerationStructureBarrier(m_blas, AccelerationStructureUsageBit::NONE,
  256. AccelerationStructureUsageBit::BUILD);
  257. cmdb->buildAccelerationStructure(m_blas);
  258. cmdb->setAccelerationStructureBarrier(m_blas, AccelerationStructureUsageBit::BUILD,
  259. AccelerationStructureUsageBit::ALL_READ);
  260. }
  261. else
  262. {
  263. cmdb->setBufferBarrier(m_vertBuff, BufferUsageBit::TRANSFER_DESTINATION, BufferUsageBit::VERTEX, 0,
  264. MAX_PTR_SIZE);
  265. cmdb->setBufferBarrier(m_indexBuff, BufferUsageBit::TRANSFER_DESTINATION, BufferUsageBit::INDEX, 0,
  266. MAX_PTR_SIZE);
  267. }
  268. // Finalize
  269. FencePtr fence;
  270. cmdb->flush(&fence);
  271. transferAlloc.release(handles[0], fence);
  272. transferAlloc.release(handles[1], fence);
  273. return Error::NONE;
  274. }
  275. } // end namespace anki