ModelComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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/Scene/Components/ModelComponent.h>
  6. #include <AnKi/Scene/SceneNode.h>
  7. #include <AnKi/Scene/SceneGraph.h>
  8. #include <AnKi/Scene/Components/MoveComponent.h>
  9. #include <AnKi/Scene/Components/SkinComponent.h>
  10. #include <AnKi/Resource/ModelResource.h>
  11. #include <AnKi/Resource/ResourceManager.h>
  12. #include <AnKi/Shaders/Include/GpuSceneFunctions.h>
  13. namespace anki {
  14. ModelComponent::ModelComponent(SceneNode* node)
  15. : SceneComponent(node, getStaticClassId())
  16. , m_node(node)
  17. , m_spatial(this)
  18. {
  19. m_gpuSceneIndexTransforms = GpuSceneContiguousArrays::getSingleton().allocate(GpuSceneContiguousArrayType::kTransformPairs);
  20. }
  21. ModelComponent::~ModelComponent()
  22. {
  23. m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
  24. }
  25. void ModelComponent::freeGpuScene()
  26. {
  27. GpuSceneBuffer::getSingleton().deferredFree(m_gpuSceneUniforms);
  28. GpuSceneContiguousArrays& arr = GpuSceneContiguousArrays::getSingleton();
  29. for(PatchInfo& patch : m_patchInfos)
  30. {
  31. arr.deferredFree(patch.m_gpuSceneIndexMeshLods);
  32. arr.deferredFree(patch.m_gpuSceneIndexRenderable);
  33. for(GpuSceneContiguousArrayIndex& idx : patch.m_gpuSceneIndexRenderableAabbs)
  34. {
  35. arr.deferredFree(idx);
  36. }
  37. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  38. {
  39. RenderStateBucketContainer::getSingleton().removeUser(patch.m_renderStateBucketIndices[t]);
  40. }
  41. }
  42. }
  43. void ModelComponent::loadModelResource(CString filename)
  44. {
  45. ModelResourcePtr rsrc;
  46. const Error err = ResourceManager::getSingleton().loadResource(filename, rsrc);
  47. if(err)
  48. {
  49. ANKI_SCENE_LOGE("Failed to load model resource");
  50. return;
  51. }
  52. m_resourceChanged = true;
  53. m_model = std::move(rsrc);
  54. const U32 modelPatchCount = m_model->getModelPatches().getSize();
  55. // Init
  56. freeGpuScene();
  57. m_patchInfos.resize(modelPatchCount);
  58. m_presentRenderingTechniques = RenderingTechniqueBit::kNone;
  59. // Allocate all uniforms so you can make one allocation
  60. U32 uniformsSize = 0;
  61. for(U32 i = 0; i < modelPatchCount; ++i)
  62. {
  63. const U32 size = U32(m_model->getModelPatches()[i].getMaterial()->getPrefilledLocalUniforms().getSizeInBytes());
  64. ANKI_ASSERT((size % 4) == 0);
  65. uniformsSize += size;
  66. }
  67. GpuSceneBuffer::getSingleton().allocate(uniformsSize, 4, m_gpuSceneUniforms);
  68. uniformsSize = 0;
  69. // Init the patches
  70. for(U32 i = 0; i < modelPatchCount; ++i)
  71. {
  72. PatchInfo& out = m_patchInfos[i];
  73. const ModelPatch& in = m_model->getModelPatches()[i];
  74. out.m_techniques = in.getMaterial()->getRenderingTechniques();
  75. m_castsShadow = m_castsShadow || in.getMaterial()->castsShadow();
  76. m_presentRenderingTechniques |= in.getMaterial()->getRenderingTechniques();
  77. out.m_gpuSceneUniformsOffset = m_gpuSceneUniforms.getOffset() + uniformsSize;
  78. uniformsSize += U32(in.getMaterial()->getPrefilledLocalUniforms().getSizeInBytes());
  79. out.m_gpuSceneIndexMeshLods = GpuSceneContiguousArrays::getSingleton().allocate(GpuSceneContiguousArrayType::kMeshLods);
  80. out.m_gpuSceneIndexRenderable = GpuSceneContiguousArrays::getSingleton().allocate(GpuSceneContiguousArrayType::kRenderables);
  81. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  82. {
  83. if(!(RenderingTechniqueBit(1 << t) & out.m_techniques) || !!(RenderingTechniqueBit(1 << t) & RenderingTechniqueBit::kAllRt))
  84. {
  85. continue;
  86. }
  87. GpuSceneContiguousArrayType allocType = GpuSceneContiguousArrayType::kCount;
  88. switch(t)
  89. {
  90. case RenderingTechnique::kGBuffer:
  91. allocType = GpuSceneContiguousArrayType::kRenderableBoundingVolumesGBuffer;
  92. break;
  93. case RenderingTechnique::kForward:
  94. allocType = GpuSceneContiguousArrayType::kRenderableBoundingVolumesForward;
  95. break;
  96. case RenderingTechnique::kDepth:
  97. allocType = GpuSceneContiguousArrayType::kRenderableBoundingVolumesDepth;
  98. break;
  99. default:
  100. ANKI_ASSERT(0);
  101. }
  102. out.m_gpuSceneIndexRenderableAabbs[t] = GpuSceneContiguousArrays::getSingleton().allocate(allocType);
  103. }
  104. }
  105. }
  106. Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
  107. {
  108. if(!isEnabled()) [[unlikely]]
  109. {
  110. updated = false;
  111. return Error::kNone;
  112. }
  113. const Bool resourceUpdated = m_resourceChanged;
  114. m_resourceChanged = false;
  115. const Bool moved = info.m_node->movedThisFrame() || m_firstTimeUpdate;
  116. const Bool movedLastFrame = m_movedLastFrame || m_firstTimeUpdate;
  117. m_firstTimeUpdate = false;
  118. m_movedLastFrame = moved;
  119. const Bool hasSkin = m_skinComponent != nullptr && m_skinComponent->isEnabled();
  120. updated = resourceUpdated || moved || movedLastFrame;
  121. // Upload GpuSceneMeshLod, uniforms and GpuSceneRenderable
  122. if(resourceUpdated) [[unlikely]]
  123. {
  124. // Upload the mesh views
  125. const U32 modelPatchCount = m_model->getModelPatches().getSize();
  126. for(U32 i = 0; i < modelPatchCount; ++i)
  127. {
  128. const ModelPatch& patch = m_model->getModelPatches()[i];
  129. const MeshResource& mesh = *patch.getMesh();
  130. Array<GpuSceneMeshLod, kMaxLodCount> meshLods;
  131. for(U32 l = 0; l < mesh.getLodCount(); ++l)
  132. {
  133. GpuSceneMeshLod& meshLod = meshLods[l];
  134. meshLod = {};
  135. meshLod.m_positionScale = mesh.getPositionsScale();
  136. meshLod.m_positionTranslation = mesh.getPositionsTranslation();
  137. ModelPatchGeometryInfo inf;
  138. patch.getGeometryInfo(l, inf);
  139. ANKI_ASSERT((inf.m_indexBufferOffset % getIndexSize(inf.m_indexType)) == 0);
  140. meshLod.m_firstIndex = U32(inf.m_indexBufferOffset / getIndexSize(inf.m_indexType));
  141. meshLod.m_indexCount = inf.m_indexCount;
  142. for(VertexStreamId stream = VertexStreamId::kMeshRelatedFirst; stream < VertexStreamId::kMeshRelatedCount; ++stream)
  143. {
  144. if(mesh.isVertexStreamPresent(stream))
  145. {
  146. const PtrSize elementSize = getFormatInfo(kMeshRelatedVertexStreamFormats[stream]).m_texelSize;
  147. ANKI_ASSERT((inf.m_vertexBufferOffsets[stream] % elementSize) == 0);
  148. meshLod.m_vertexOffsets[U32(stream)] = U32(inf.m_vertexBufferOffsets[stream] / elementSize);
  149. }
  150. else
  151. {
  152. meshLod.m_vertexOffsets[U32(stream)] = kMaxU32;
  153. }
  154. }
  155. }
  156. // Copy the last LOD to the rest just in case
  157. for(U32 l = mesh.getLodCount(); l < kMaxLodCount; ++l)
  158. {
  159. meshLods[l] = meshLods[l - 1];
  160. }
  161. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_patchInfos[i].m_gpuSceneIndexMeshLods.getOffsetInGpuScene(), meshLods);
  162. // Upload the GpuSceneRenderable
  163. GpuSceneRenderable gpuRenderable;
  164. gpuRenderable.m_worldTransformsOffset = m_gpuSceneIndexTransforms.getOffsetInGpuScene();
  165. gpuRenderable.m_uniformsOffset = m_patchInfos[i].m_gpuSceneUniformsOffset;
  166. gpuRenderable.m_geometryOffset = m_patchInfos[i].m_gpuSceneIndexMeshLods.getOffsetInGpuScene();
  167. gpuRenderable.m_boneTransformsOffset = (hasSkin) ? m_skinComponent->getBoneTransformsGpuSceneOffset() : 0;
  168. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_patchInfos[i].m_gpuSceneIndexRenderable.getOffsetInGpuScene(),
  169. gpuRenderable);
  170. }
  171. // Upload the uniforms
  172. DynamicArray<U32, MemoryPoolPtrWrapper<StackMemoryPool>> allUniforms(info.m_framePool);
  173. allUniforms.resize(m_gpuSceneUniforms.getAllocatedSize() / 4);
  174. U32 count = 0;
  175. for(U32 i = 0; i < modelPatchCount; ++i)
  176. {
  177. const ModelPatch& patch = m_model->getModelPatches()[i];
  178. const MaterialResource& mtl = *patch.getMaterial();
  179. memcpy(&allUniforms[count], mtl.getPrefilledLocalUniforms().getBegin(), mtl.getPrefilledLocalUniforms().getSizeInBytes());
  180. count += U32(mtl.getPrefilledLocalUniforms().getSizeInBytes() / 4);
  181. }
  182. ANKI_ASSERT(count * 4 == m_gpuSceneUniforms.getAllocatedSize());
  183. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_gpuSceneUniforms.getOffset(), m_gpuSceneUniforms.getAllocatedSize(),
  184. &allUniforms[0]);
  185. }
  186. // Upload transforms
  187. if(moved || movedLastFrame) [[unlikely]]
  188. {
  189. Array<Mat3x4, 2> trfs;
  190. trfs[0] = Mat3x4(info.m_node->getWorldTransform());
  191. trfs[1] = Mat3x4(info.m_node->getPreviousWorldTransform());
  192. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_gpuSceneIndexTransforms.getOffsetInGpuScene(), trfs);
  193. }
  194. // Spatial update
  195. const Bool spatialNeedsUpdate = moved || resourceUpdated || m_skinComponent;
  196. if(spatialNeedsUpdate) [[unlikely]]
  197. {
  198. Aabb aabbLocal;
  199. if(m_skinComponent == nullptr) [[likely]]
  200. {
  201. aabbLocal = m_model->getBoundingVolume();
  202. }
  203. else
  204. {
  205. aabbLocal = m_skinComponent->getBoneBoundingVolumeLocalSpace().getCompoundShape(m_model->getBoundingVolume());
  206. }
  207. const Aabb aabbWorld = aabbLocal.getTransformed(info.m_node->getWorldTransform());
  208. m_spatial.setBoundingShape(aabbWorld);
  209. }
  210. const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
  211. updated = updated || spatialUpdated;
  212. // Update the buckets
  213. const Bool bucketsNeedUpdate = resourceUpdated || moved != movedLastFrame;
  214. if(bucketsNeedUpdate)
  215. {
  216. const U32 modelPatchCount = m_model->getModelPatches().getSize();
  217. for(U32 i = 0; i < modelPatchCount; ++i)
  218. {
  219. // Refresh the render state buckets
  220. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  221. {
  222. RenderStateBucketContainer::getSingleton().removeUser(m_patchInfos[i].m_renderStateBucketIndices[t]);
  223. if(!(RenderingTechniqueBit(1 << t) & m_patchInfos[i].m_techniques))
  224. {
  225. continue;
  226. }
  227. // Fill the state
  228. RenderingKey key;
  229. key.setLod(0); // Materials don't care
  230. key.setRenderingTechnique(t);
  231. key.setSkinned(hasSkin);
  232. key.setVelocity(moved);
  233. const MaterialVariant& mvariant = m_model->getModelPatches()[i].getMaterial()->getOrCreateVariant(key);
  234. RenderStateInfo state;
  235. state.m_primitiveTopology = PrimitiveTopology::kTriangles;
  236. state.m_indexedDrawcall = true;
  237. state.m_program = mvariant.getShaderProgram();
  238. m_patchInfos[i].m_renderStateBucketIndices[t] = RenderStateBucketContainer::getSingleton().addUser(state, t);
  239. }
  240. }
  241. }
  242. // Upload the AABBs to the GPU scene
  243. const Bool gpuSceneAabbsNeedUpdate = spatialNeedsUpdate || bucketsNeedUpdate;
  244. if(gpuSceneAabbsNeedUpdate)
  245. {
  246. const U32 modelPatchCount = m_model->getModelPatches().getSize();
  247. for(U32 i = 0; i < modelPatchCount; ++i)
  248. {
  249. for(RenderingTechnique t :
  250. EnumBitsIterable<RenderingTechnique, RenderingTechniqueBit>(m_patchInfos[i].m_techniques & ~RenderingTechniqueBit::kAllRt))
  251. {
  252. const Vec3 aabbMin = m_spatial.getAabbWorldSpace().getMin().xyz();
  253. const Vec3 aabbMax = m_spatial.getAabbWorldSpace().getMax().xyz();
  254. const GpuSceneRenderableAabb gpuVolume = initGpuSceneRenderableAabb(aabbMin, aabbMax, m_patchInfos[i].m_gpuSceneIndexRenderable.get(),
  255. m_patchInfos[i].m_renderStateBucketIndices[t].get());
  256. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool,
  257. m_patchInfos[i].m_gpuSceneIndexRenderableAabbs[t].getOffsetInGpuScene(), gpuVolume);
  258. }
  259. }
  260. }
  261. return Error::kNone;
  262. }
  263. void ModelComponent::setupRenderableQueueElements(U32 lod, RenderingTechnique technique, WeakArray<RenderableQueueElement>& outRenderables) const
  264. {
  265. ANKI_ASSERT(isEnabled());
  266. outRenderables.setArray(nullptr, 0);
  267. const RenderingTechniqueBit requestedRenderingTechniqueMask = RenderingTechniqueBit(1 << technique);
  268. if(!(m_presentRenderingTechniques & requestedRenderingTechniqueMask))
  269. {
  270. return;
  271. }
  272. // Allocate renderables
  273. U32 renderableCount = 0;
  274. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  275. {
  276. renderableCount += !!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask);
  277. }
  278. if(renderableCount == 0)
  279. {
  280. return;
  281. }
  282. RenderableQueueElement* renderables = static_cast<RenderableQueueElement*>(
  283. SceneGraph::getSingleton().getFrameMemoryPool().allocate(sizeof(RenderableQueueElement) * renderableCount, alignof(RenderableQueueElement)));
  284. outRenderables.setArray(renderables, renderableCount);
  285. // Fill renderables
  286. const Bool moved = m_node->movedThisFrame() && technique == RenderingTechnique::kGBuffer;
  287. const Bool hasSkin = m_skinComponent != nullptr && m_skinComponent->isEnabled();
  288. RenderingKey key;
  289. key.setLod(lod);
  290. key.setRenderingTechnique(technique);
  291. key.setVelocity(moved);
  292. key.setSkinned(hasSkin);
  293. renderableCount = 0;
  294. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  295. {
  296. if(!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask))
  297. {
  298. continue;
  299. }
  300. RenderableQueueElement& queueElem = renderables[renderableCount];
  301. const ModelPatch& patch = m_model->getModelPatches()[i];
  302. ModelRenderingInfo modelInf;
  303. patch.getRenderingInfo(key, modelInf);
  304. queueElem.m_program = modelInf.m_program.get();
  305. queueElem.m_worldTransformsOffset = m_gpuSceneIndexTransforms.getOffsetInGpuScene();
  306. queueElem.m_uniformsOffset = m_patchInfos[i].m_gpuSceneUniformsOffset;
  307. queueElem.m_geometryOffset = m_patchInfos[i].m_gpuSceneIndexMeshLods.getOffsetInGpuScene() + lod * sizeof(GpuSceneMeshLod);
  308. queueElem.m_boneTransformsOffset = (hasSkin) ? m_skinComponent->getBoneTransformsGpuSceneOffset() : 0;
  309. queueElem.m_indexCount = modelInf.m_indexCount;
  310. queueElem.m_firstIndex = U32(modelInf.m_indexBufferOffset / 2 + modelInf.m_firstIndex);
  311. queueElem.m_indexed = true;
  312. queueElem.m_primitiveTopology = PrimitiveTopology::kTriangles;
  313. queueElem.m_aabbMin = m_spatial.getAabbWorldSpace().getMin().xyz();
  314. queueElem.m_aabbMax = m_spatial.getAabbWorldSpace().getMax().xyz();
  315. queueElem.computeMergeKey();
  316. ++renderableCount;
  317. }
  318. }
  319. void ModelComponent::setupRayTracingInstanceQueueElements(U32 lod, RenderingTechnique technique,
  320. WeakArray<RayTracingInstanceQueueElement>& outInstances) const
  321. {
  322. ANKI_ASSERT(isEnabled());
  323. outInstances.setArray(nullptr, 0);
  324. const RenderingTechniqueBit requestedRenderingTechniqueMask = RenderingTechniqueBit(1 << technique);
  325. if(!(m_presentRenderingTechniques & requestedRenderingTechniqueMask))
  326. {
  327. return;
  328. }
  329. // Allocate instances
  330. U32 instanceCount = 0;
  331. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  332. {
  333. instanceCount += !!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask);
  334. }
  335. if(instanceCount == 0)
  336. {
  337. return;
  338. }
  339. RayTracingInstanceQueueElement* instances = static_cast<RayTracingInstanceQueueElement*>(SceneGraph::getSingleton().getFrameMemoryPool().allocate(
  340. sizeof(RayTracingInstanceQueueElement) * instanceCount, alignof(RayTracingInstanceQueueElement)));
  341. outInstances.setArray(instances, instanceCount);
  342. RenderingKey key;
  343. key.setLod(lod);
  344. key.setRenderingTechnique(technique);
  345. instanceCount = 0;
  346. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  347. {
  348. if(!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask))
  349. {
  350. continue;
  351. }
  352. RayTracingInstanceQueueElement& queueElem = instances[instanceCount];
  353. const ModelPatch& patch = m_model->getModelPatches()[i];
  354. GpuSceneContiguousArrays& gpuArrays = GpuSceneContiguousArrays::getSingleton();
  355. ModelRayTracingInfo modelInf;
  356. patch.getRayTracingInfo(key, modelInf);
  357. queueElem.m_bottomLevelAccelerationStructure = modelInf.m_bottomLevelAccelerationStructure.get();
  358. queueElem.m_shaderGroupHandleIndex = modelInf.m_shaderGroupHandleIndex;
  359. queueElem.m_worldTransformsOffset = m_gpuSceneIndexTransforms.getOffsetInGpuScene();
  360. queueElem.m_uniformsOffset = m_patchInfos[i].m_gpuSceneUniformsOffset;
  361. queueElem.m_geometryOffset =
  362. U32(m_patchInfos[i].m_gpuSceneIndexMeshLods.get() * sizeof(GpuSceneMeshLod) * kMaxLodCount + lod * sizeof(GpuSceneMeshLod));
  363. queueElem.m_geometryOffset += U32(gpuArrays.getArrayBaseOffset(GpuSceneContiguousArrayType::kMeshLods));
  364. queueElem.m_indexBufferOffset = U32(modelInf.m_indexBufferOffset);
  365. const Transform positionTransform(patch.getMesh()->getPositionsTranslation().xyz0(), Mat3x4::getIdentity(),
  366. patch.getMesh()->getPositionsScale());
  367. queueElem.m_transform = Mat3x4(m_node->getWorldTransform()).combineTransformations(Mat3x4(positionTransform));
  368. ++instanceCount;
  369. }
  370. }
  371. void ModelComponent::onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added)
  372. {
  373. ANKI_ASSERT(other);
  374. if(other->getClassId() != SkinComponent::getStaticClassId())
  375. {
  376. return;
  377. }
  378. const Bool alreadyHasSkinComponent = m_skinComponent != nullptr;
  379. if(added && !alreadyHasSkinComponent)
  380. {
  381. m_skinComponent = static_cast<SkinComponent*>(other);
  382. m_resourceChanged = true;
  383. }
  384. else if(!added && other == m_skinComponent)
  385. {
  386. m_skinComponent = nullptr;
  387. m_resourceChanged = true;
  388. }
  389. }
  390. } // end namespace anki