Browse Source

Fix bugs with sub meshes

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
fd4463bb36

+ 1 - 1
AnKi/Importer/GltfImporterMesh.cpp

@@ -722,11 +722,11 @@ Error GltfImporter::writeMesh(const cgltf_mesh& mesh, CString nameOverride, F32
 	}
 	}
 
 
 	// Write indices
 	// Write indices
+	U32 vertCount = 0;
 	for(const SubMesh& submesh : submeshes)
 	for(const SubMesh& submesh : submeshes)
 	{
 	{
 		DynamicArrayAuto<U16> indices(m_alloc);
 		DynamicArrayAuto<U16> indices(m_alloc);
 		indices.create(submesh.m_indices.getSize());
 		indices.create(submesh.m_indices.getSize());
-		U32 vertCount = 0;
 		for(U32 i = 0; i < indices.getSize(); ++i)
 		for(U32 i = 0; i < indices.getSize(); ++i)
 		{
 		{
 			const U32 idx = submesh.m_indices[i] + vertCount;
 			const U32 idx = submesh.m_indices[i] + vertCount;

+ 13 - 9
AnKi/Resource/ModelResource.cpp

@@ -83,8 +83,9 @@ void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& i
 
 
 	// Index buff
 	// Index buff
 	inf.m_indexBuffer = m_indexBufferInfos[meshLod].m_buffer;
 	inf.m_indexBuffer = m_indexBufferInfos[meshLod].m_buffer;
-	inf.m_indexBufferOffset = m_indexBufferInfos[meshLod].m_offset;
+	inf.m_indexBufferOffset = 0;
 	inf.m_indexCount = m_indexBufferInfos[meshLod].m_indexCount;
 	inf.m_indexCount = m_indexBufferInfos[meshLod].m_indexCount;
+	inf.m_firstIndex = m_indexBufferInfos[meshLod].m_firstIndex;
 	inf.m_indexType = m_indexType;
 	inf.m_indexType = m_indexType;
 
 
 	// Get program
 	// Get program
@@ -233,22 +234,25 @@ Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames,
 			if(subMeshIndex == MAX_U32)
 			if(subMeshIndex == MAX_U32)
 			{
 			{
 				IndexType indexType;
 				IndexType indexType;
-				mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, outIndexBufferInfo.m_offset,
-										outIndexBufferInfo.m_indexCount, indexType);
+				PtrSize offset;
+				mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, offset, outIndexBufferInfo.m_indexCount,
+										indexType);
+				ANKI_ASSERT(offset == 0);
 				m_indexType = indexType;
 				m_indexType = indexType;
+				outIndexBufferInfo.m_firstIndex = 0;
 			}
 			}
 			else
 			else
 			{
 			{
 				IndexType indexType;
 				IndexType indexType;
-				mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, outIndexBufferInfo.m_offset,
-										outIndexBufferInfo.m_indexCount, indexType);
+				PtrSize offset;
+				mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, offset, outIndexBufferInfo.m_indexCount,
+										indexType);
+				ANKI_ASSERT(offset == 0);
 				m_indexType = indexType;
 				m_indexType = indexType;
 
 
-				U32 firstIndex;
 				Aabb aabb;
 				Aabb aabb;
-				mesh.getSubMeshInfo(subMeshIndex, firstIndex, outIndexBufferInfo.m_indexCount, aabb);
-
-				outIndexBufferInfo.m_offset = ((m_indexType == IndexType::U16) ? 2 : 4) * firstIndex;
+				mesh.getSubMeshInfo(subMeshIndex, outIndexBufferInfo.m_firstIndex, outIndexBufferInfo.m_indexCount,
+									aabb);
 			}
 			}
 		}
 		}
 	}
 	}

+ 2 - 1
AnKi/Resource/ModelResource.h

@@ -73,6 +73,7 @@ public:
 	BufferPtr m_indexBuffer;
 	BufferPtr m_indexBuffer;
 	PtrSize m_indexBufferOffset;
 	PtrSize m_indexBufferOffset;
 	IndexType m_indexType;
 	IndexType m_indexType;
+	U32 m_firstIndex;
 	U32 m_indexCount;
 	U32 m_indexCount;
 
 
 	U32 m_boneTransformsBinding;
 	U32 m_boneTransformsBinding;
@@ -157,7 +158,7 @@ private:
 	{
 	{
 	public:
 	public:
 		BufferPtr m_buffer;
 		BufferPtr m_buffer;
-		PtrSize m_offset = MAX_PTR_SIZE;
+		U32 m_firstIndex = MAX_U32;
 		U32 m_indexCount = MAX_U32;
 		U32 m_indexCount = MAX_U32;
 	};
 	};
 
 

+ 1 - 3
AnKi/Scene/CameraNode.cpp

@@ -94,7 +94,7 @@ void CameraNode::onMoveComponentUpdate(MoveComponent& move)
 
 
 	// Frustum
 	// Frustum
 	U count = 0;
 	U count = 0;
-	const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fc) {
+	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fc) {
 		if(count == 0)
 		if(count == 0)
 		{
 		{
 			fc.setWorldTransform(worldTransform);
 			fc.setWorldTransform(worldTransform);
@@ -112,9 +112,7 @@ void CameraNode::onMoveComponentUpdate(MoveComponent& move)
 		}
 		}
 
 
 		++count;
 		++count;
-		return Error::NONE;
 	});
 	});
-	(void)err;
 }
 }
 
 
 PerspectiveCameraNode::PerspectiveCameraNode(SceneGraph* scene, CString name)
 PerspectiveCameraNode::PerspectiveCameraNode(SceneGraph* scene, CString name)

+ 2 - 9
AnKi/Scene/Components/MoveComponent.cpp

@@ -75,17 +75,10 @@ Bool MoveComponent::updateWorldTransform(SceneNode& node)
 	// If this is dirty then make children dirty as well. Don't walk the whole tree because you will re-walk it later
 	// If this is dirty then make children dirty as well. Don't walk the whole tree because you will re-walk it later
 	if(dirty)
 	if(dirty)
 	{
 	{
-		Error err = node.visitChildrenMaxDepth(1, [](SceneNode& childNode) -> Error {
-			Error e = childNode.iterateComponentsOfType<MoveComponent>([](MoveComponent& mov) -> Error {
-				mov.markForUpdate();
-				return Error::NONE;
-			});
-
-			(void)e;
-
+		const Error err = node.visitChildrenMaxDepth(1, [](SceneNode& childNode) -> Error {
+			childNode.iterateComponentsOfType<MoveComponent>([](MoveComponent& mov) { mov.markForUpdate(); });
 			return Error::NONE;
 			return Error::NONE;
 		});
 		});
-
 		(void)err;
 		(void)err;
 	}
 	}
 
 

+ 3 - 9
AnKi/Scene/GlobalIlluminationProbeNode.cpp

@@ -156,19 +156,16 @@ void GlobalIlluminationProbeNode::onShapeUpdateOrProbeNeedsRendering()
 
 
 		// Update frustum components
 		// Update frustum components
 		U count = 0;
 		U count = 0;
-		const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
+		iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
 			Transform trf = m_cubeFaceTransforms[count];
 			Transform trf = m_cubeFaceTransforms[count];
 			trf.setOrigin(gic.getRenderPosition().xyz0());
 			trf.setOrigin(gic.getRenderPosition().xyz0());
 
 
 			frc.setWorldTransform(trf);
 			frc.setWorldTransform(trf);
 			frc.setFar(effectiveDistance);
 			frc.setFar(effectiveDistance);
 			++count;
 			++count;
-
-			return Error::NONE;
 		});
 		});
 
 
 		ANKI_ASSERT(count == 6);
 		ANKI_ASSERT(count == 6);
-		(void)err;
 	}
 	}
 
 
 	// Update the spatial comp
 	// Update the spatial comp
@@ -190,11 +187,8 @@ Error GlobalIlluminationProbeNode::frameUpdate(Second prevUpdateTime, Second crn
 	const FrustumComponentVisibilityTestFlag testFlags =
 	const FrustumComponentVisibilityTestFlag testFlags =
 		(gic.getMarkedForRendering()) ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
 		(gic.getMarkedForRendering()) ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
 
 
-	const Error err = iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) -> Error {
-		frc.setEnabledVisibilityTests(testFlags);
-		return Error::NONE;
-	});
-	(void)err;
+	iterateComponentsOfType<FrustumComponent>(
+		[testFlags](FrustumComponent& frc) { frc.setEnabledVisibilityTests(testFlags); });
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }

+ 5 - 19
AnKi/Scene/LightNode.cpp

@@ -85,7 +85,7 @@ void LightNode::frameUpdateCommon()
 	const LightComponent& lc = getFirstComponentOfType<LightComponent>();
 	const LightComponent& lc = getFirstComponentOfType<LightComponent>();
 	const Bool castsShadow = lc.getShadowEnabled();
 	const Bool castsShadow = lc.getShadowEnabled();
 
 
-	const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
+	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
 		if(castsShadow)
 		if(castsShadow)
 		{
 		{
 			frc.setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::SHADOW_CASTERS);
 			frc.setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::SHADOW_CASTERS);
@@ -94,10 +94,7 @@ void LightNode::frameUpdateCommon()
 		{
 		{
 			frc.setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 			frc.setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 		}
 		}
-
-		return Error::NONE;
 	});
 	});
-	(void)err;
 }
 }
 
 
 void LightNode::onMoveUpdateCommon(const MoveComponent& move)
 void LightNode::onMoveUpdateCommon(const MoveComponent& move)
@@ -139,25 +136,18 @@ void PointLightNode::onMoved(const MoveComponent& move)
 
 
 	// Update the frustums
 	// Update the frustums
 	U32 count = 0;
 	U32 count = 0;
-	const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr) -> Error {
+	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr) {
 		Transform trf = m_shadowData[count].m_localTrf;
 		Transform trf = m_shadowData[count].m_localTrf;
 		trf.setOrigin(move.getWorldTransform().getOrigin());
 		trf.setOrigin(move.getWorldTransform().getOrigin());
 
 
 		fr.setWorldTransform(trf);
 		fr.setWorldTransform(trf);
 		++count;
 		++count;
-
-		return Error::NONE;
 	});
 	});
-	(void)err;
 }
 }
 
 
 void PointLightNode::onLightShapeUpdated(LightComponent& light)
 void PointLightNode::onLightShapeUpdated(LightComponent& light)
 {
 {
-	const Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr) -> Error {
-		fr.setFar(light.getRadius());
-		return Error::NONE;
-	});
-	(void)err;
+	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr) { fr.setFar(light.getRadius()); });
 
 
 	SpatialComponent& spatialc = getFirstComponentOfType<SpatialComponent>();
 	SpatialComponent& spatialc = getFirstComponentOfType<SpatialComponent>();
 	spatialc.setSphereWorldSpace(Sphere(light.getWorldTransform().getOrigin(), light.getRadius()));
 	spatialc.setSphereWorldSpace(Sphere(light.getWorldTransform().getOrigin(), light.getRadius()));
@@ -260,12 +250,8 @@ SpotLightNode::SpotLightNode(SceneGraph* scene, CString name)
 void SpotLightNode::onMoved(const MoveComponent& move)
 void SpotLightNode::onMoved(const MoveComponent& move)
 {
 {
 	// Update the frustums
 	// Update the frustums
-	Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr) -> Error {
-		fr.setWorldTransform(move.getWorldTransform());
-		return Error::NONE;
-	});
-
-	(void)err;
+	iterateComponentsOfType<FrustumComponent>(
+		[&](FrustumComponent& fr) { fr.setWorldTransform(move.getWorldTransform()); });
 
 
 	onMoveUpdateCommon(move);
 	onMoveUpdateCommon(move);
 }
 }

+ 42 - 4
AnKi/Scene/ModelNode.cpp

@@ -76,7 +76,7 @@ void ModelNode::feedbackUpdate()
 		return;
 		return;
 	}
 	}
 
 
-	const U64 globTimestamp = getGlobalTimestamp();
+	const Timestamp globTimestamp = getGlobalTimestamp();
 	Bool updateSpatial = false;
 	Bool updateSpatial = false;
 
 
 	// Model update
 	// Model update
@@ -92,8 +92,8 @@ void ModelNode::feedbackUpdate()
 		}
 		}
 		else
 		else
 		{
 		{
-			// Need to create more render components, deffer it
-			ANKI_ASSERT(!"TODO");
+			// Need to create more render components, can't do it at the moment, deffer it
+			m_deferredRenderComponentUpdate = true;
 		}
 		}
 	}
 	}
 
 
@@ -119,6 +119,43 @@ void ModelNode::feedbackUpdate()
 	}
 	}
 }
 }
 
 
+Error ModelNode::frameUpdate(Second prevUpdateTime, Second crntTime)
+{
+	if(ANKI_LIKELY(!m_deferredRenderComponentUpdate))
+	{
+		return Error::NONE;
+	}
+
+	m_deferredRenderComponentUpdate = false;
+
+	const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
+	const U32 modelPatchCount = modelc.getModelResource()->getModelPatches().getSize();
+	const U32 renderComponentCount = countComponentsOfType<RenderComponent>();
+
+	if(modelPatchCount > renderComponentCount)
+	{
+		const U32 diff = modelPatchCount - renderComponentCount;
+
+		for(U32 i = 0; i < diff; ++i)
+		{
+			newComponent<RenderComponent>();
+		}
+
+		m_renderProxies.resize(getAllocator(), modelPatchCount);
+	}
+	else
+	{
+		ANKI_ASSERT(!"TODO");
+	}
+
+	ANKI_ASSERT(countComponentsOfType<RenderComponent>() == modelPatchCount);
+
+	// Now you can init the render components
+	initRenderComponents();
+
+	return Error::NONE;
+}
+
 void ModelNode::initRenderComponents()
 void ModelNode::initRenderComponents()
 {
 {
 	const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
 	const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
@@ -249,7 +286,8 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 		cmdb->bindIndexBuffer(modelInf.m_indexBuffer, modelInf.m_indexBufferOffset, IndexType::U16);
 		cmdb->bindIndexBuffer(modelInf.m_indexBuffer, modelInf.m_indexBufferOffset, IndexType::U16);
 
 
 		// Draw
 		// Draw
-		cmdb->drawElements(PrimitiveTopology::TRIANGLES, modelInf.m_indexCount, instanceCount, 0, 0, 0);
+		cmdb->drawElements(PrimitiveTopology::TRIANGLES, modelInf.m_indexCount, instanceCount, modelInf.m_firstIndex, 0,
+						   0);
 	}
 	}
 	else
 	else
 	{
 	{

+ 4 - 0
AnKi/Scene/ModelNode.h

@@ -27,6 +27,8 @@ public:
 
 
 	~ModelNode();
 	~ModelNode();
 
 
+	Error frameUpdate(Second prevUpdateTime, Second crntTime) override;
+
 private:
 private:
 	class FeedbackComponent;
 	class FeedbackComponent;
 	class RenderProxy;
 	class RenderProxy;
@@ -34,6 +36,8 @@ private:
 	Aabb m_aabbLocal;
 	Aabb m_aabbLocal;
 	DynamicArray<RenderProxy> m_renderProxies; ///< The size matches the number of render components.
 	DynamicArray<RenderProxy> m_renderProxies; ///< The size matches the number of render components.
 
 
+	Bool m_deferredRenderComponentUpdate = false;
+
 	void feedbackUpdate();
 	void feedbackUpdate();
 
 
 	void draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData, U32 modelPatchIdx) const;
 	void draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData, U32 modelPatchIdx) const;

+ 4 - 14
AnKi/Scene/ReflectionProbeNode.cpp

@@ -135,18 +135,15 @@ void ReflectionProbeNode::onMoveUpdate(MoveComponent& move)
 {
 {
 	// Update frustum components
 	// Update frustum components
 	U count = 0;
 	U count = 0;
-	Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
+	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
 		Transform trf = m_frustumTransforms[count];
 		Transform trf = m_frustumTransforms[count];
 		trf.setOrigin(move.getWorldTransform().getOrigin());
 		trf.setOrigin(move.getWorldTransform().getOrigin());
 
 
 		frc.setWorldTransform(trf);
 		frc.setWorldTransform(trf);
 		++count;
 		++count;
-
-		return Error::NONE;
 	});
 	});
 
 
 	ANKI_ASSERT(count == 6);
 	ANKI_ASSERT(count == 6);
-	(void)err;
 
 
 	// Update the spatial comp
 	// Update the spatial comp
 	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
@@ -165,11 +162,7 @@ void ReflectionProbeNode::onShapeUpdate(ReflectionProbeComponent& reflc)
 	effectiveDistance = max(effectiveDistance, getSceneGraph().getConfig().m_reflectionProbeEffectiveDistance);
 	effectiveDistance = max(effectiveDistance, getSceneGraph().getConfig().m_reflectionProbeEffectiveDistance);
 
 
 	// Update frustum components
 	// Update frustum components
-	Error err = iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) -> Error {
-		frc.setFar(effectiveDistance);
-		return Error::NONE;
-	});
-	(void)err;
+	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) { frc.setFar(effectiveDistance); });
 
 
 	// Update the spatial comp
 	// Update the spatial comp
 	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
 	SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
@@ -184,11 +177,8 @@ Error ReflectionProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 	const FrustumComponentVisibilityTestFlag testFlags =
 	const FrustumComponentVisibilityTestFlag testFlags =
 		reflc.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
 		reflc.getMarkedForRendering() ? FRUSTUM_TEST_FLAGS : FrustumComponentVisibilityTestFlag::NONE;
 
 
-	const Error err = iterateComponentsOfType<FrustumComponent>([testFlags](FrustumComponent& frc) -> Error {
-		frc.setEnabledVisibilityTests(testFlags);
-		return Error::NONE;
-	});
-	(void)err;
+	iterateComponentsOfType<FrustumComponent>(
+		[testFlags](FrustumComponent& frc) { frc.setEnabledVisibilityTests(testFlags); });
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }

+ 8 - 18
AnKi/Scene/SceneNode.h

@@ -91,7 +91,7 @@ public:
 		Base::addChild(getAllocator(), obj);
 		Base::addChild(getAllocator(), obj);
 	}
 	}
 
 
-	/// This is called by the scene every frame after logic and before rendering. By default it does nothing.
+	/// This is called by the scenegraph every frame after all component updates. By default it does nothing.
 	/// @param prevUpdateTime Timestamp of the previous update
 	/// @param prevUpdateTime Timestamp of the previous update
 	/// @param crntTime Timestamp of this update
 	/// @param crntTime Timestamp of this update
 	virtual ANKI_USE_RESULT Error frameUpdate(Second prevUpdateTime, Second crntTime)
 	virtual ANKI_USE_RESULT Error frameUpdate(Second prevUpdateTime, Second crntTime)
@@ -135,40 +135,34 @@ public:
 
 
 	/// Iterate all components of a specific type
 	/// Iterate all components of a specific type
 	template<typename TComponent, typename TFunct>
 	template<typename TComponent, typename TFunct>
-	ANKI_USE_RESULT Error iterateComponentsOfType(TFunct func) const
+	void iterateComponentsOfType(TFunct func) const
 	{
 	{
-		Error err = Error::NONE;
 		auto it = m_components.getBegin();
 		auto it = m_components.getBegin();
 		auto end = m_components.getEnd();
 		auto end = m_components.getEnd();
-		for(; !err && it != end; ++it)
+		for(; it != end; ++it)
 		{
 		{
 			if(it->getComponentClassId() == TComponent::getStaticClassId())
 			if(it->getComponentClassId() == TComponent::getStaticClassId())
 			{
 			{
 				const SceneComponent* comp = *it;
 				const SceneComponent* comp = *it;
-				err = func(static_cast<const TComponent&>(*comp));
+				func(static_cast<const TComponent&>(*comp));
 			}
 			}
 		}
 		}
-
-		return err;
 	}
 	}
 
 
 	/// Iterate all components of a specific type
 	/// Iterate all components of a specific type
 	template<typename TComponent, typename TFunct>
 	template<typename TComponent, typename TFunct>
-	ANKI_USE_RESULT Error iterateComponentsOfType(TFunct func)
+	void iterateComponentsOfType(TFunct func)
 	{
 	{
-		Error err = Error::NONE;
 		auto it = m_components.getBegin();
 		auto it = m_components.getBegin();
 		auto end = m_components.getEnd();
 		auto end = m_components.getEnd();
-		for(; !err && it != end; ++it)
+		for(; it != end; ++it)
 		{
 		{
 			if(it->getComponentClassId() == TComponent::getStaticClassId())
 			if(it->getComponentClassId() == TComponent::getStaticClassId())
 			{
 			{
 				SceneComponent* comp = *it;
 				SceneComponent* comp = *it;
-				err = func(static_cast<TComponent&>(*comp));
+				func(static_cast<TComponent&>(*comp));
 			}
 			}
 		}
 		}
-
-		return err;
 	}
 	}
 
 
 	/// Try geting a pointer to the first component of the requested type
 	/// Try geting a pointer to the first component of the requested type
@@ -278,11 +272,7 @@ public:
 	U32 countComponentsOfType() const
 	U32 countComponentsOfType() const
 	{
 	{
 		U32 count = 0;
 		U32 count = 0;
-		const Error err = iterateComponentsOfType<TComponent>([&](const TComponent& c) -> Error {
-			++count;
-			return Error::NONE;
-		});
-		(void)err;
+		iterateComponentsOfType<TComponent>([&](const TComponent& c) { ++count; });
 		return count;
 		return count;
 	}
 	}
 
 

+ 17 - 18
AnKi/Scene/Visibility.cpp

@@ -345,10 +345,9 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 		WeakArray<RenderQueue> nextQueues;
 		WeakArray<RenderQueue> nextQueues;
 		WeakArray<FrustumComponent> nextQueueFrustumComponents; // Optional
 		WeakArray<FrustumComponent> nextQueueFrustumComponents; // Optional
 
 
-		if(rc)
-		{
+		node.iterateComponentsOfType<RenderComponent>([&](const RenderComponent& rc) {
 			RenderableQueueElement* el;
 			RenderableQueueElement* el;
-			if(!!(rc->getFlags() & RenderComponentFlag::FORWARD_SHADING))
+			if(!!(rc.getFlags() & RenderComponentFlag::FORWARD_SHADING))
 			{
 			{
 				el = result.m_forwardShadingRenderables.newElement(alloc);
 				el = result.m_forwardShadingRenderables.newElement(alloc);
 			}
 			}
@@ -357,33 +356,35 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 				el = result.m_renderables.newElement(alloc);
 				el = result.m_renderables.newElement(alloc);
 			}
 			}
 
 
-			rc->setupRenderableQueueElement(*el);
+			rc.setupRenderableQueueElement(*el);
 
 
 			// Compute distance from the frustum
 			// Compute distance from the frustum
 			const Plane& nearPlane = primaryFrc.getViewPlanes()[FrustumPlaneType::NEAR];
 			const Plane& nearPlane = primaryFrc.getViewPlanes()[FrustumPlaneType::NEAR];
-			el->m_distanceFromCamera = !!(rc->getFlags() & RenderComponentFlag::SORT_LAST)
+			el->m_distanceFromCamera = !!(rc.getFlags() & RenderComponentFlag::SORT_LAST)
 										   ? primaryFrc.getFar()
 										   ? primaryFrc.getFar()
 										   : max(0.0f, testPlane(nearPlane, spatialc->getAabbWorldSpace()));
 										   : max(0.0f, testPlane(nearPlane, spatialc->getAabbWorldSpace()));
 
 
 			el->m_lod = computeLod(primaryFrc, el->m_distanceFromCamera);
 			el->m_lod = computeLod(primaryFrc, el->m_distanceFromCamera);
 
 
+			// Add to early Z
 			if(wantsEarlyZ && el->m_distanceFromCamera < m_frcCtx->m_visCtx->m_earlyZDist
 			if(wantsEarlyZ && el->m_distanceFromCamera < m_frcCtx->m_visCtx->m_earlyZDist
-			   && !(rc->getFlags() & RenderComponentFlag::FORWARD_SHADING))
+			   && !(rc.getFlags() & RenderComponentFlag::FORWARD_SHADING))
 			{
 			{
 				RenderableQueueElement* el2 = result.m_earlyZRenderables.newElement(alloc);
 				RenderableQueueElement* el2 = result.m_earlyZRenderables.newElement(alloc);
 				*el2 = *el;
 				*el2 = *el;
 			}
 			}
-		}
 
 
-		if(rtRc)
-		{
-			RayTracingInstanceQueueElement* el = result.m_rayTracingInstances.newElement(alloc);
+			// Add to RT
+			if(rtRc)
+			{
+				RayTracingInstanceQueueElement* el = result.m_rayTracingInstances.newElement(alloc);
 
 
-			// Compute the LOD
-			const Plane& nearPlane = primaryFrc.getViewPlanes()[FrustumPlaneType::NEAR];
-			const F32 dist = testPlane(nearPlane, spatialc->getAabbWorldSpace());
-			rtRc->setupRayTracingInstanceQueueElement(computeLod(primaryFrc, dist), *el);
-		}
+				// Compute the LOD
+				const Plane& nearPlane = primaryFrc.getViewPlanes()[FrustumPlaneType::NEAR];
+				const F32 dist = testPlane(nearPlane, spatialc->getAabbWorldSpace());
+				rc.setupRayTracingInstanceQueueElement(computeLod(primaryFrc, dist), *el);
+			}
+		});
 
 
 		if(lc)
 		if(lc)
 		{
 		{
@@ -592,11 +593,9 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 
 
 			if(ANKI_LIKELY(nextQueueFrustumComponents.getSize() == 0))
 			if(ANKI_LIKELY(nextQueueFrustumComponents.getSize() == 0))
 			{
 			{
-				const Error err = node.iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
+				node.iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
 					m_frcCtx->m_visCtx->submitNewWork(frc, primaryFrc, nextQueues[count++], hive);
 					m_frcCtx->m_visCtx->submitNewWork(frc, primaryFrc, nextQueues[count++], hive);
-					return Error::NONE;
 				});
 				});
-				(void)err;
 			}
 			}
 			else
 			else
 			{
 			{