ModelComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  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. for(VertexStreamId stream = VertexStreamId::kPosition; stream <= VertexStreamId::kBoneWeights; ++stream)
  138. {
  139. if(!mesh.isVertexStreamPresent(stream))
  140. {
  141. continue;
  142. }
  143. PtrSize offset;
  144. U32 vertCount;
  145. mesh.getVertexStreamInfo(l, stream, offset, vertCount);
  146. const PtrSize elementSize = getFormatInfo(kMeshRelatedVertexStreamFormats[stream]).m_texelSize;
  147. ANKI_ASSERT((offset % elementSize) == 0);
  148. meshLod.m_vertexOffsets[U32(stream)] = U32(offset / elementSize);
  149. }
  150. U32 firstIndex;
  151. U32 indexCount;
  152. Aabb aabb;
  153. mesh.getSubMeshInfo(l, i, firstIndex, indexCount, aabb);
  154. PtrSize offset;
  155. IndexType indexType;
  156. mesh.getIndexBufferInfo(l, offset, indexCount, indexType);
  157. meshLod.m_indexBufferOffset = U32(offset) / getIndexSize(indexType) + firstIndex;
  158. meshLod.m_indexCount = indexCount;
  159. }
  160. // Copy the last LOD to the rest just in case
  161. for(U32 l = mesh.getLodCount(); l < kMaxLodCount; ++l)
  162. {
  163. meshLods[l] = meshLods[l - 1];
  164. }
  165. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_patchInfos[i].m_gpuSceneIndexMeshLods.getOffsetInGpuScene(), meshLods);
  166. // Upload the GpuSceneRenderable
  167. GpuSceneRenderable gpuRenderable;
  168. gpuRenderable.m_worldTransformsOffset = m_gpuSceneIndexTransforms.getOffsetInGpuScene();
  169. gpuRenderable.m_uniformsOffset = m_patchInfos[i].m_gpuSceneUniformsOffset;
  170. gpuRenderable.m_geometryOffset = m_patchInfos[i].m_gpuSceneIndexMeshLods.getOffsetInGpuScene();
  171. gpuRenderable.m_boneTransformsOffset = (hasSkin) ? m_skinComponent->getBoneTransformsGpuSceneOffset() : 0;
  172. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_patchInfos[i].m_gpuSceneIndexRenderable.getOffsetInGpuScene(),
  173. gpuRenderable);
  174. }
  175. // Upload the uniforms
  176. DynamicArray<U32, MemoryPoolPtrWrapper<StackMemoryPool>> allUniforms(info.m_framePool);
  177. allUniforms.resize(m_gpuSceneUniforms.getAllocatedSize() / 4);
  178. U32 count = 0;
  179. for(U32 i = 0; i < modelPatchCount; ++i)
  180. {
  181. const ModelPatch& patch = m_model->getModelPatches()[i];
  182. const MaterialResource& mtl = *patch.getMaterial();
  183. memcpy(&allUniforms[count], mtl.getPrefilledLocalUniforms().getBegin(), mtl.getPrefilledLocalUniforms().getSizeInBytes());
  184. count += U32(mtl.getPrefilledLocalUniforms().getSizeInBytes() / 4);
  185. }
  186. ANKI_ASSERT(count * 4 == m_gpuSceneUniforms.getAllocatedSize());
  187. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_gpuSceneUniforms.getOffset(), m_gpuSceneUniforms.getAllocatedSize(),
  188. &allUniforms[0]);
  189. }
  190. // Upload transforms
  191. if(moved || movedLastFrame) [[unlikely]]
  192. {
  193. Array<Mat3x4, 2> trfs;
  194. trfs[0] = Mat3x4(info.m_node->getWorldTransform());
  195. trfs[1] = Mat3x4(info.m_node->getPreviousWorldTransform());
  196. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_gpuSceneIndexTransforms.getOffsetInGpuScene(), trfs);
  197. }
  198. // Spatial update
  199. const Bool spatialNeedsUpdate = moved || resourceUpdated || m_skinComponent;
  200. if(spatialNeedsUpdate) [[unlikely]]
  201. {
  202. Aabb aabbLocal;
  203. if(m_skinComponent == nullptr) [[likely]]
  204. {
  205. aabbLocal = m_model->getBoundingVolume();
  206. }
  207. else
  208. {
  209. aabbLocal = m_skinComponent->getBoneBoundingVolumeLocalSpace().getCompoundShape(m_model->getBoundingVolume());
  210. }
  211. const Aabb aabbWorld = aabbLocal.getTransformed(info.m_node->getWorldTransform());
  212. m_spatial.setBoundingShape(aabbWorld);
  213. }
  214. const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
  215. updated = updated || spatialUpdated;
  216. // Update the buckets
  217. const Bool bucketsNeedUpdate = resourceUpdated || moved != movedLastFrame;
  218. if(bucketsNeedUpdate)
  219. {
  220. const U32 modelPatchCount = m_model->getModelPatches().getSize();
  221. for(U32 i = 0; i < modelPatchCount; ++i)
  222. {
  223. // Refresh the render state buckets
  224. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  225. {
  226. RenderStateBucketContainer::getSingleton().removeUser(m_patchInfos[i].m_renderStateBucketIndices[t]);
  227. if(!(RenderingTechniqueBit(1 << t) & m_patchInfos[i].m_techniques))
  228. {
  229. continue;
  230. }
  231. // Fill the state
  232. RenderingKey key;
  233. key.setLod(0); // Materials don't care
  234. key.setRenderingTechnique(t);
  235. key.setSkinned(hasSkin);
  236. key.setVelocity(moved);
  237. const MaterialVariant& mvariant = m_model->getModelPatches()[i].getMaterial()->getOrCreateVariant(key);
  238. RenderStateInfo state;
  239. state.m_primitiveTopology = PrimitiveTopology::kTriangles;
  240. state.m_indexedDrawcall = true;
  241. state.m_program = mvariant.getShaderProgram();
  242. m_patchInfos[i].m_renderStateBucketIndices[t] = RenderStateBucketContainer::getSingleton().addUser(state, t);
  243. }
  244. }
  245. }
  246. // Upload the AABBs to the GPU scene
  247. const Bool gpuSceneAabbsNeedUpdate = spatialNeedsUpdate || bucketsNeedUpdate;
  248. if(gpuSceneAabbsNeedUpdate)
  249. {
  250. const U32 modelPatchCount = m_model->getModelPatches().getSize();
  251. for(U32 i = 0; i < modelPatchCount; ++i)
  252. {
  253. for(RenderingTechnique t :
  254. EnumBitsIterable<RenderingTechnique, RenderingTechniqueBit>(m_patchInfos[i].m_techniques & ~RenderingTechniqueBit::kAllRt))
  255. {
  256. const Vec3 aabbMin = m_spatial.getAabbWorldSpace().getMin().xyz();
  257. const Vec3 aabbMax = m_spatial.getAabbWorldSpace().getMax().xyz();
  258. const GpuSceneRenderableAabb gpuVolume = initGpuSceneRenderableAabb(aabbMin, aabbMax, m_patchInfos[i].m_gpuSceneIndexRenderable.get(),
  259. m_patchInfos[i].m_renderStateBucketIndices[t].get());
  260. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool,
  261. m_patchInfos[i].m_gpuSceneIndexRenderableAabbs[t].getOffsetInGpuScene(), gpuVolume);
  262. }
  263. }
  264. }
  265. return Error::kNone;
  266. }
  267. void ModelComponent::setupRenderableQueueElements(U32 lod, RenderingTechnique technique, WeakArray<RenderableQueueElement>& outRenderables) const
  268. {
  269. ANKI_ASSERT(isEnabled());
  270. outRenderables.setArray(nullptr, 0);
  271. const RenderingTechniqueBit requestedRenderingTechniqueMask = RenderingTechniqueBit(1 << technique);
  272. if(!(m_presentRenderingTechniques & requestedRenderingTechniqueMask))
  273. {
  274. return;
  275. }
  276. // Allocate renderables
  277. U32 renderableCount = 0;
  278. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  279. {
  280. renderableCount += !!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask);
  281. }
  282. if(renderableCount == 0)
  283. {
  284. return;
  285. }
  286. RenderableQueueElement* renderables = static_cast<RenderableQueueElement*>(
  287. SceneGraph::getSingleton().getFrameMemoryPool().allocate(sizeof(RenderableQueueElement) * renderableCount, alignof(RenderableQueueElement)));
  288. outRenderables.setArray(renderables, renderableCount);
  289. // Fill renderables
  290. const Bool moved = m_node->movedThisFrame() && technique == RenderingTechnique::kGBuffer;
  291. const Bool hasSkin = m_skinComponent != nullptr && m_skinComponent->isEnabled();
  292. RenderingKey key;
  293. key.setLod(lod);
  294. key.setRenderingTechnique(technique);
  295. key.setVelocity(moved);
  296. key.setSkinned(hasSkin);
  297. renderableCount = 0;
  298. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  299. {
  300. if(!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask))
  301. {
  302. continue;
  303. }
  304. RenderableQueueElement& queueElem = renderables[renderableCount];
  305. const ModelPatch& patch = m_model->getModelPatches()[i];
  306. ModelRenderingInfo modelInf;
  307. patch.getRenderingInfo(key, modelInf);
  308. queueElem.m_program = modelInf.m_program.get();
  309. queueElem.m_worldTransformsOffset = m_gpuSceneIndexTransforms.getOffsetInGpuScene();
  310. queueElem.m_uniformsOffset = m_patchInfos[i].m_gpuSceneUniformsOffset;
  311. queueElem.m_geometryOffset = m_patchInfos[i].m_gpuSceneIndexMeshLods.getOffsetInGpuScene() + lod * sizeof(GpuSceneMeshLod);
  312. queueElem.m_boneTransformsOffset = (hasSkin) ? m_skinComponent->getBoneTransformsGpuSceneOffset() : 0;
  313. queueElem.m_indexCount = modelInf.m_indexCount;
  314. queueElem.m_firstIndex = U32(modelInf.m_indexBufferOffset / 2 + modelInf.m_firstIndex);
  315. queueElem.m_indexed = true;
  316. queueElem.m_primitiveTopology = PrimitiveTopology::kTriangles;
  317. queueElem.m_aabbMin = m_spatial.getAabbWorldSpace().getMin().xyz();
  318. queueElem.m_aabbMax = m_spatial.getAabbWorldSpace().getMax().xyz();
  319. queueElem.computeMergeKey();
  320. ++renderableCount;
  321. }
  322. }
  323. void ModelComponent::setupRayTracingInstanceQueueElements(U32 lod, RenderingTechnique technique,
  324. WeakArray<RayTracingInstanceQueueElement>& outInstances) const
  325. {
  326. ANKI_ASSERT(isEnabled());
  327. outInstances.setArray(nullptr, 0);
  328. const RenderingTechniqueBit requestedRenderingTechniqueMask = RenderingTechniqueBit(1 << technique);
  329. if(!(m_presentRenderingTechniques & requestedRenderingTechniqueMask))
  330. {
  331. return;
  332. }
  333. // Allocate instances
  334. U32 instanceCount = 0;
  335. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  336. {
  337. instanceCount += !!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask);
  338. }
  339. if(instanceCount == 0)
  340. {
  341. return;
  342. }
  343. RayTracingInstanceQueueElement* instances = static_cast<RayTracingInstanceQueueElement*>(SceneGraph::getSingleton().getFrameMemoryPool().allocate(
  344. sizeof(RayTracingInstanceQueueElement) * instanceCount, alignof(RayTracingInstanceQueueElement)));
  345. outInstances.setArray(instances, instanceCount);
  346. RenderingKey key;
  347. key.setLod(lod);
  348. key.setRenderingTechnique(technique);
  349. instanceCount = 0;
  350. for(U32 i = 0; i < m_patchInfos.getSize(); ++i)
  351. {
  352. if(!(m_patchInfos[i].m_techniques & requestedRenderingTechniqueMask))
  353. {
  354. continue;
  355. }
  356. RayTracingInstanceQueueElement& queueElem = instances[instanceCount];
  357. const ModelPatch& patch = m_model->getModelPatches()[i];
  358. GpuSceneContiguousArrays& gpuArrays = GpuSceneContiguousArrays::getSingleton();
  359. ModelRayTracingInfo modelInf;
  360. patch.getRayTracingInfo(key, modelInf);
  361. queueElem.m_bottomLevelAccelerationStructure = modelInf.m_bottomLevelAccelerationStructure.get();
  362. queueElem.m_shaderGroupHandleIndex = modelInf.m_shaderGroupHandleIndex;
  363. queueElem.m_worldTransformsOffset = m_gpuSceneIndexTransforms.getOffsetInGpuScene();
  364. queueElem.m_uniformsOffset = m_patchInfos[i].m_gpuSceneUniformsOffset;
  365. queueElem.m_geometryOffset =
  366. U32(m_patchInfos[i].m_gpuSceneIndexMeshLods.get() * sizeof(GpuSceneMeshLod) * kMaxLodCount + lod * sizeof(GpuSceneMeshLod));
  367. queueElem.m_geometryOffset += U32(gpuArrays.getArrayBase(GpuSceneContiguousArrayType::kMeshLods));
  368. queueElem.m_indexBufferOffset = U32(modelInf.m_indexBufferOffset);
  369. const Transform positionTransform(patch.getMesh()->getPositionsTranslation().xyz0(), Mat3x4::getIdentity(),
  370. patch.getMesh()->getPositionsScale());
  371. queueElem.m_transform = Mat3x4(m_node->getWorldTransform()).combineTransformations(Mat3x4(positionTransform));
  372. ++instanceCount;
  373. }
  374. }
  375. void ModelComponent::onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added)
  376. {
  377. ANKI_ASSERT(other);
  378. if(other->getClassId() != SkinComponent::getStaticClassId())
  379. {
  380. return;
  381. }
  382. const Bool alreadyHasSkinComponent = m_skinComponent != nullptr;
  383. if(added && !alreadyHasSkinComponent)
  384. {
  385. m_skinComponent = static_cast<SkinComponent*>(other);
  386. m_resourceChanged = true;
  387. }
  388. else if(!added && other == m_skinComponent)
  389. {
  390. m_skinComponent = nullptr;
  391. m_resourceChanged = true;
  392. }
  393. }
  394. } // end namespace anki