ModelResource.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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/ModelResource.h>
  6. #include <AnKi/Resource/ResourceManager.h>
  7. #include <AnKi/Resource/MeshResource.h>
  8. #include <AnKi/Util/Xml.h>
  9. #include <AnKi/Util/Logger.h>
  10. namespace anki {
  11. static Bool attributeIsRequired(VertexAttributeId loc, Pass pass, Bool hasSkin)
  12. {
  13. if(pass == Pass::GB || pass == Pass::FS)
  14. {
  15. return true;
  16. }
  17. else if(!hasSkin)
  18. {
  19. return loc == VertexAttributeId::POSITION;
  20. }
  21. else
  22. {
  23. return loc == VertexAttributeId::POSITION || loc == VertexAttributeId::BONE_INDICES
  24. || loc == VertexAttributeId::BONE_WEIGHTS;
  25. }
  26. }
  27. void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& inf) const
  28. {
  29. ANKI_ASSERT(!(!m_model->supportsSkinning() && key.isSkinned()));
  30. const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
  31. // Vertex attributes & bindings
  32. {
  33. U32 bufferBindingVisitedMask = 0;
  34. Array<U32, MAX_VERTEX_ATTRIBUTES> realBufferBindingToVirtual;
  35. inf.m_vertexAttributeCount = 0;
  36. inf.m_vertexBufferBindingCount = 0;
  37. for(VertexAttributeId loc : EnumIterable<VertexAttributeId>())
  38. {
  39. if(!m_presentVertexAttributes.get(loc) || !attributeIsRequired(loc, key.getPass(), key.isSkinned()))
  40. {
  41. continue;
  42. }
  43. // Attribute
  44. ModelVertexAttribute& outAttribInfo = inf.m_vertexAttributes[inf.m_vertexAttributeCount++];
  45. outAttribInfo.m_location = loc;
  46. outAttribInfo.m_bufferBinding = m_vertexAttributeInfos[loc].m_bufferBinding;
  47. outAttribInfo.m_relativeOffset = m_vertexAttributeInfos[loc].m_relativeOffset;
  48. outAttribInfo.m_format = m_vertexAttributeInfos[loc].m_format;
  49. // Binding. Also, remove any holes in the bindings
  50. if(!(bufferBindingVisitedMask & (1 << outAttribInfo.m_bufferBinding)))
  51. {
  52. bufferBindingVisitedMask |= 1 << outAttribInfo.m_bufferBinding;
  53. ModelVertexBufferBinding& outBinding = inf.m_vertexBufferBindings[inf.m_vertexBufferBindingCount];
  54. const VertexBufferInfo& inBinding = m_vertexBufferInfos[meshLod][outAttribInfo.m_bufferBinding];
  55. outBinding.m_buffer = inBinding.m_buffer;
  56. ANKI_ASSERT(outBinding.m_buffer.isCreated());
  57. outBinding.m_offset = inBinding.m_offset;
  58. ANKI_ASSERT(outBinding.m_offset != MAX_PTR_SIZE);
  59. outBinding.m_stride = inBinding.m_stride;
  60. ANKI_ASSERT(outBinding.m_stride != MAX_PTR_SIZE);
  61. realBufferBindingToVirtual[outAttribInfo.m_bufferBinding] = inf.m_vertexBufferBindingCount;
  62. ++inf.m_vertexBufferBindingCount;
  63. }
  64. // Change the binding of the attrib
  65. outAttribInfo.m_bufferBinding = realBufferBindingToVirtual[outAttribInfo.m_bufferBinding];
  66. }
  67. ANKI_ASSERT(inf.m_vertexAttributeCount != 0 && inf.m_vertexBufferBindingCount != 0);
  68. }
  69. // Index buff
  70. inf.m_indexBuffer = m_indexBufferInfos[meshLod].m_buffer;
  71. inf.m_indexBufferOffset = 0;
  72. inf.m_indexCount = m_indexBufferInfos[meshLod].m_indexCount;
  73. inf.m_firstIndex = m_indexBufferInfos[meshLod].m_firstIndex;
  74. inf.m_indexType = m_indexType;
  75. // Get program
  76. {
  77. RenderingKey mtlKey = key;
  78. mtlKey.setLod(min(key.getLod(), m_mtl->getLodCount() - 1));
  79. const MaterialVariant& variant = m_mtl->getOrCreateVariant(mtlKey);
  80. inf.m_program = variant.getShaderProgram();
  81. if(m_mtl->supportsSkinning())
  82. {
  83. inf.m_boneTransformsBinding = m_mtl->getBoneTransformsStorageBlockBinding();
  84. inf.m_prevFrameBoneTransformsBinding = m_mtl->getPrevFrameBoneTransformsStorageBlockBinding();
  85. }
  86. else
  87. {
  88. inf.m_boneTransformsBinding = inf.m_prevFrameBoneTransformsBinding = MAX_U32;
  89. }
  90. }
  91. }
  92. void ModelPatch::getRayTracingInfo(U32 lod, ModelRayTracingInfo& info) const
  93. {
  94. ANKI_ASSERT(m_mtl->getSupportedRayTracingTypes() != RayTypeBit::NONE);
  95. info.m_grObjectReferenceCount = 0;
  96. memset(&info.m_descriptor, 0, sizeof(info.m_descriptor));
  97. // Mesh
  98. const MeshResourcePtr& mesh = m_meshes[min(U32(m_meshLodCount - 1), lod)];
  99. info.m_bottomLevelAccelerationStructure = mesh->getBottomLevelAccelerationStructure();
  100. info.m_descriptor.m_mesh = mesh->getMeshGpuDescriptor();
  101. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getIndexBuffer();
  102. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getVertexBuffer();
  103. // Material
  104. info.m_descriptor.m_material = m_mtl->getMaterialGpuDescriptor();
  105. for(RayType rayType : EnumIterable<RayType>())
  106. {
  107. if(!!(m_mtl->getSupportedRayTracingTypes() & RayTypeBit(1 << rayType)))
  108. {
  109. info.m_shaderGroupHandleIndices[rayType] = m_mtl->getShaderGroupHandleIndex(rayType);
  110. }
  111. else
  112. {
  113. info.m_shaderGroupHandleIndices[rayType] = MAX_U32;
  114. }
  115. }
  116. ConstWeakArray<TextureViewPtr> textureViews = m_mtl->getAllTextureViews();
  117. for(U32 i = 0; i < textureViews.getSize(); ++i)
  118. {
  119. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = textureViews[i];
  120. }
  121. }
  122. Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames, const CString& mtlFName,
  123. U32 subMeshIndex, Bool async, ResourceManager* manager)
  124. {
  125. ANKI_ASSERT(meshFNames.getSize() > 0);
  126. #if ANKI_ENABLE_ASSERTIONS
  127. m_model = model;
  128. #endif
  129. // Load material
  130. ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
  131. // Load meshes
  132. m_meshLodCount = 0;
  133. for(U32 lod = 0; lod < meshFNames.getSize(); lod++)
  134. {
  135. ANKI_CHECK(manager->loadResource(meshFNames[lod], m_meshes[lod], async));
  136. // Sanity check
  137. if(lod > 0 && !m_meshes[lod]->isCompatible(*m_meshes[lod - 1]))
  138. {
  139. ANKI_RESOURCE_LOGE("Meshes not compatible");
  140. return Error::USER_DATA;
  141. }
  142. // Submesh index
  143. if(subMeshIndex != MAX_U32 && subMeshIndex >= m_meshes[lod]->getSubMeshCount())
  144. {
  145. ANKI_RESOURCE_LOGE("Wrong subMeshIndex given");
  146. return Error::USER_DATA;
  147. }
  148. ++m_meshLodCount;
  149. }
  150. // Create the cached items
  151. {
  152. // Vertex attributes
  153. for(VertexAttributeId attrib : EnumIterable<VertexAttributeId>())
  154. {
  155. const MeshResource& mesh = *m_meshes[0].get();
  156. const Bool enabled = mesh.isVertexAttributePresent(attrib);
  157. m_presentVertexAttributes.set(U32(attrib), enabled);
  158. if(!enabled)
  159. {
  160. continue;
  161. }
  162. VertexAttributeInfo& outAttribInfo = m_vertexAttributeInfos[attrib];
  163. U32 bufferBinding, relativeOffset;
  164. mesh.getVertexAttributeInfo(attrib, bufferBinding, outAttribInfo.m_format, relativeOffset);
  165. outAttribInfo.m_bufferBinding = bufferBinding & 0xFu;
  166. outAttribInfo.m_relativeOffset = relativeOffset & 0xFFFFFFu;
  167. }
  168. // Vertex buffers
  169. for(U32 lod = 0; lod < m_meshLodCount; ++lod)
  170. {
  171. const MeshResource& mesh = *m_meshes[lod].get();
  172. for(VertexAttributeId attrib : EnumIterable<VertexAttributeId>())
  173. {
  174. if(!m_presentVertexAttributes.get(attrib))
  175. {
  176. continue;
  177. }
  178. VertexBufferInfo& outVertBufferInfo =
  179. m_vertexBufferInfos[lod][m_vertexAttributeInfos[attrib].m_bufferBinding];
  180. if(!outVertBufferInfo.m_buffer.isCreated())
  181. {
  182. PtrSize offset, stride;
  183. mesh.getVertexBufferInfo(m_vertexAttributeInfos[attrib].m_bufferBinding, outVertBufferInfo.m_buffer,
  184. offset, stride);
  185. outVertBufferInfo.m_offset = offset & 0xFFFFFFFFFFFF;
  186. outVertBufferInfo.m_stride = stride & 0xFFFF;
  187. }
  188. }
  189. }
  190. // Index buffer
  191. for(U32 lod = 0; lod < m_meshLodCount; ++lod)
  192. {
  193. const MeshResource& mesh = *m_meshes[lod].get();
  194. IndexBufferInfo& outIndexBufferInfo = m_indexBufferInfos[lod];
  195. if(subMeshIndex == MAX_U32)
  196. {
  197. IndexType indexType;
  198. PtrSize offset;
  199. mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, offset, outIndexBufferInfo.m_indexCount,
  200. indexType);
  201. ANKI_ASSERT(offset == 0);
  202. m_indexType = indexType;
  203. outIndexBufferInfo.m_firstIndex = 0;
  204. }
  205. else
  206. {
  207. IndexType indexType;
  208. PtrSize offset;
  209. mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, offset, outIndexBufferInfo.m_indexCount,
  210. indexType);
  211. ANKI_ASSERT(offset == 0);
  212. m_indexType = indexType;
  213. Aabb aabb;
  214. mesh.getSubMeshInfo(subMeshIndex, outIndexBufferInfo.m_firstIndex, outIndexBufferInfo.m_indexCount,
  215. aabb);
  216. }
  217. }
  218. }
  219. return Error::NONE;
  220. }
  221. ModelResource::ModelResource(ResourceManager* manager)
  222. : ResourceObject(manager)
  223. {
  224. }
  225. ModelResource::~ModelResource()
  226. {
  227. auto alloc = getAllocator();
  228. m_modelPatches.destroy(alloc);
  229. }
  230. Error ModelResource::load(const ResourceFilename& filename, Bool async)
  231. {
  232. auto alloc = getAllocator();
  233. // Load
  234. //
  235. XmlElement el;
  236. XmlDocument doc;
  237. ANKI_CHECK(openFileParseXml(filename, doc));
  238. XmlElement rootEl;
  239. ANKI_CHECK(doc.getChildElement("model", rootEl));
  240. // <modelPatches>
  241. XmlElement modelPatchesEl;
  242. ANKI_CHECK(rootEl.getChildElement("modelPatches", modelPatchesEl));
  243. XmlElement modelPatchEl;
  244. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  245. // Count
  246. U32 count = 0;
  247. do
  248. {
  249. ++count;
  250. // Move to next
  251. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  252. } while(modelPatchEl);
  253. // Check number of model patches
  254. if(count < 1)
  255. {
  256. ANKI_RESOURCE_LOGE("Zero number of model patches");
  257. return Error::USER_DATA;
  258. }
  259. m_modelPatches.create(alloc, count);
  260. count = 0;
  261. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  262. do
  263. {
  264. U32 subMeshIndex;
  265. Bool subMeshIndexPresent;
  266. ANKI_CHECK(modelPatchEl.getAttributeNumberOptional("subMeshIndex", subMeshIndex, subMeshIndexPresent));
  267. if(!subMeshIndexPresent)
  268. {
  269. subMeshIndex = MAX_U32;
  270. }
  271. XmlElement materialEl;
  272. ANKI_CHECK(modelPatchEl.getChildElement("material", materialEl));
  273. Array<CString, 3> meshesFnames;
  274. U32 meshesCount = 1;
  275. XmlElement meshEl;
  276. ANKI_CHECK(modelPatchEl.getChildElement("mesh", meshEl));
  277. XmlElement meshEl1;
  278. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh1", meshEl1));
  279. XmlElement meshEl2;
  280. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh2", meshEl2));
  281. ANKI_CHECK(meshEl.getText(meshesFnames[0]));
  282. if(meshEl1)
  283. {
  284. ++meshesCount;
  285. ANKI_CHECK(meshEl1.getText(meshesFnames[1]));
  286. }
  287. if(meshEl2)
  288. {
  289. ++meshesCount;
  290. ANKI_CHECK(meshEl2.getText(meshesFnames[2]));
  291. }
  292. CString cstr;
  293. ANKI_CHECK(materialEl.getText(cstr));
  294. ANKI_CHECK(m_modelPatches[count].init(this, ConstWeakArray<CString>(&meshesFnames[0], meshesCount), cstr,
  295. subMeshIndex, async, &getManager()));
  296. if(count > 0 && m_modelPatches[count].supportsSkinning() != m_modelPatches[count - 1].supportsSkinning())
  297. {
  298. ANKI_RESOURCE_LOGE("All model patches should support skinning or all shouldn't support skinning");
  299. return Error::USER_DATA;
  300. }
  301. m_skinning = m_modelPatches[count].supportsSkinning();
  302. // Move to next
  303. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  304. ++count;
  305. } while(modelPatchEl);
  306. ANKI_ASSERT(count == m_modelPatches.getSize());
  307. // Calculate compound bounding volume
  308. m_boundingVolume = m_modelPatches[0].m_meshes[0]->getBoundingShape();
  309. for(auto it = m_modelPatches.getBegin() + 1; it != m_modelPatches.getEnd(); ++it)
  310. {
  311. m_boundingVolume = m_boundingVolume.getCompoundShape((*it).m_meshes[0]->getBoundingShape());
  312. }
  313. return Error::NONE;
  314. }
  315. } // end namespace anki