Browse Source

Remove the old CPU visibility

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
8841d62b15
55 changed files with 22 additions and 2498 deletions
  1. 1 5
      AnKi/Core/App.cpp
  2. 0 1
      AnKi/Renderer.h
  3. 0 1
      AnKi/Renderer/AccelerationStructureBuilder.cpp
  4. 0 1
      AnKi/Renderer/Common.h
  5. 0 1
      AnKi/Renderer/Dbg.cpp
  6. 0 1
      AnKi/Renderer/Dbg.h
  7. 0 1
      AnKi/Renderer/ForwardShading.cpp
  8. 0 1
      AnKi/Renderer/GBuffer.cpp
  9. 1 1
      AnKi/Renderer/GBuffer.h
  10. 0 1
      AnKi/Renderer/GBufferPost.cpp
  11. 0 1
      AnKi/Renderer/IndirectDiffuseProbes.cpp
  12. 0 1
      AnKi/Renderer/IndirectDiffuseProbes.h
  13. 0 1
      AnKi/Renderer/IndirectSpecular.cpp
  14. 0 1
      AnKi/Renderer/LensFlare.cpp
  15. 0 1
      AnKi/Renderer/LightShading.cpp
  16. 1 3
      AnKi/Renderer/MainRenderer.cpp
  17. 1 1
      AnKi/Renderer/MainRenderer.h
  18. 0 1
      AnKi/Renderer/MotionVectors.cpp
  19. 2 1
      AnKi/Renderer/PrimaryNonRenderableVisibility.cpp
  20. 0 1
      AnKi/Renderer/ProbeReflections.cpp
  21. 0 49
      AnKi/Renderer/RenderQueue.cpp
  22. 0 437
      AnKi/Renderer/RenderQueue.h
  23. 0 1
      AnKi/Renderer/Renderer.cpp
  24. 3 4
      AnKi/Renderer/RtShadows.cpp
  25. 0 24
      AnKi/Renderer/ShadowMapping.cpp
  26. 0 4
      AnKi/Renderer/ShadowMapping.h
  27. 0 1
      AnKi/Renderer/UiStage.cpp
  28. 0 1
      AnKi/Renderer/Utils/Drawer.cpp
  29. 0 1
      AnKi/Renderer/Utils/TraditionalDeferredShading.cpp
  30. 0 1
      AnKi/Renderer/Utils/TraditionalDeferredShading.h
  31. 0 1
      AnKi/Renderer/VolumetricFog.cpp
  32. 0 1
      AnKi/Scene.h
  33. 0 2
      AnKi/Scene/Components/DecalComponent.h
  34. 0 2
      AnKi/Scene/Components/FogDensityComponent.h
  35. 2 0
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp
  36. 1 2
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.h
  37. 0 2
      AnKi/Scene/Components/LensFlareComponent.h
  38. 0 1
      AnKi/Scene/Components/LightComponent.cpp
  39. 1 2
      AnKi/Scene/Components/LightComponent.h
  40. 2 2
      AnKi/Scene/Components/ModelComponent.h
  41. 0 1
      AnKi/Scene/Components/ParticleEmitterComponent.cpp
  42. 0 1
      AnKi/Scene/Components/ParticleEmitterComponent.h
  43. 2 0
      AnKi/Scene/Components/ReflectionProbeComponent.cpp
  44. 1 2
      AnKi/Scene/Components/ReflectionProbeComponent.h
  45. 1 28
      AnKi/Scene/Components/SkyboxComponent.cpp
  46. 0 4
      AnKi/Scene/Components/SkyboxComponent.h
  47. 3 2
      AnKi/Scene/Components/UiComponent.h
  48. 0 391
      AnKi/Scene/Octree.cpp
  49. 0 323
      AnKi/Scene/Octree.h
  50. 0 17
      AnKi/Scene/SceneGraph.cpp
  51. 0 14
      AnKi/Scene/SceneGraph.h
  52. 0 157
      AnKi/Scene/Spatial.h
  53. 0 620
      AnKi/Scene/Visibility.cpp
  54. 0 290
      AnKi/Scene/VisibilityInternal.h
  55. 0 84
      Tests/Scene/Octree.cpp

+ 1 - 5
AnKi/Core/App.cpp

@@ -23,7 +23,6 @@
 #include <AnKi/Core/MaliHwCounters.h>
 #include <AnKi/Window/Input.h>
 #include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Physics/PhysicsWorld.h>
 #include <AnKi/Renderer/MainRenderer.h>
@@ -456,12 +455,9 @@ Error App::mainLoop()
 
 			ANKI_CHECK(SceneGraph::getSingleton().update(prevUpdateTime, crntTime));
 
-			RenderQueue rqueue;
-			SceneGraph::getSingleton().doVisibilityTests(rqueue);
-
 			// Render
 			TexturePtr presentableTex = GrManager::getSingleton().acquireNextPresentableTexture();
-			ANKI_CHECK(MainRenderer::getSingleton().render(rqueue, presentableTex.get()));
+			ANKI_CHECK(MainRenderer::getSingleton().render(presentableTex.get()));
 
 			// If we get stats exclude the time of GR because it forces some GPU-CPU serialization. We don't want to count that
 			Second grTime = 0.0;

+ 0 - 1
AnKi/Renderer.h

@@ -18,7 +18,6 @@
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/TemporalAA.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/IndirectSpecular.h>
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/Dbg.h>

+ 0 - 1
AnKi/Renderer/AccelerationStructureBuilder.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Renderer/AccelerationStructureBuilder.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Core/App.h>

+ 0 - 1
AnKi/Renderer/Common.h

@@ -82,7 +82,6 @@ class RenderingContext
 {
 public:
 	StackMemoryPool* m_tempPool = nullptr;
-	RenderQueue* m_renderQueue = nullptr;
 
 	RenderGraphDescription m_renderGraphDescr;
 

+ 0 - 1
AnKi/Renderer/Dbg.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/FinalComposite.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/ForwardShading.h>
 #include <AnKi/Renderer/ClusterBinning2.h>
 #include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>

+ 0 - 1
AnKi/Renderer/Dbg.h

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/RendererObject.h>
 #include <AnKi/Gr.h>
 #include <AnKi/Util/Enum.h>
-#include <AnKi/Renderer/RenderQueue.h>
 
 namespace anki {
 

+ 0 - 1
AnKi/Renderer/ForwardShading.cpp

@@ -5,7 +5,6 @@
 
 #include <AnKi/Renderer/ForwardShading.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/ShadowMapping.h>

+ 0 - 1
AnKi/Renderer/GBuffer.cpp

@@ -5,7 +5,6 @@
 
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/VrsSriGeneration.h>
 #include <AnKi/Renderer/Scale.h>
 #include <AnKi/Renderer/Dbg.h>

+ 1 - 1
AnKi/Renderer/GBuffer.h

@@ -51,7 +51,7 @@ public:
 		return m_runCtx.m_prevFrameDepthRt;
 	}
 
-	RenderTargetHandle getHzbRt() const
+	const RenderTargetHandle& getHzbRt() const
 	{
 		return m_runCtx.m_hzbRt;
 	}

+ 0 - 1
AnKi/Renderer/GBufferPost.cpp

@@ -6,7 +6,6 @@
 #include <AnKi/Renderer/GBufferPost.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/ClusterBinning2.h>
 
 namespace anki {

+ 0 - 1
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -5,7 +5,6 @@
 
 #include <AnKi/Renderer/IndirectDiffuseProbes.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Scene/Components/GlobalIlluminationProbeComponent.h>

+ 0 - 1
AnKi/Renderer/IndirectDiffuseProbes.h

@@ -7,7 +7,6 @@
 
 #include <AnKi/Renderer/RendererObject.h>
 #include <AnKi/Renderer/Utils/TraditionalDeferredShading.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Collision/Forward.h>
 
 namespace anki {

+ 0 - 1
AnKi/Renderer/IndirectSpecular.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/DownscaleBlur.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/VrsSriGeneration.h>

+ 0 - 1
AnKi/Renderer/LensFlare.cpp

@@ -5,7 +5,6 @@
 
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/DepthDownscale.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Core/CVarSet.h>
 #include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>

+ 0 - 1
AnKi/Renderer/LightShading.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/ShadowMapping.h>
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/ForwardShading.h>
 #include <AnKi/Renderer/VolumetricFog.h>
 #include <AnKi/Renderer/DepthDownscale.h>

+ 1 - 3
AnKi/Renderer/MainRenderer.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/FinalComposite.h>
 #include <AnKi/Renderer/Dbg.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/File.h>
 #include <AnKi/Util/Filesystem.h>
@@ -81,7 +80,7 @@ Error MainRenderer::init(const MainRendererInitInfo& inf)
 	return Error::kNone;
 }
 
-Error MainRenderer::render(RenderQueue& rqueue, Texture* presentTex)
+Error MainRenderer::render(Texture* presentTex)
 {
 	ANKI_TRACE_SCOPED_EVENT(Render);
 
@@ -109,7 +108,6 @@ Error MainRenderer::render(RenderQueue& rqueue, Texture* presentTex)
 		ctx.m_outRenderTarget = ctx.m_renderGraphDescr.newRenderTarget(m_tmpRtDesc);
 	}
 
-	ctx.m_renderQueue = &rqueue;
 	ANKI_CHECK(m_r->populateRenderGraph(ctx));
 
 	// Blit renderer's result to default FB if needed

+ 1 - 1
AnKi/Renderer/MainRenderer.h

@@ -32,7 +32,7 @@ class MainRenderer : public MakeSingleton<MainRenderer>
 public:
 	Error init(const MainRendererInitInfo& inf);
 
-	Error render(RenderQueue& rqueue, Texture* presentTex);
+	Error render(Texture* presentTex);
 
 	Dbg& getDbg();
 

+ 0 - 1
AnKi/Renderer/MotionVectors.cpp

@@ -6,7 +6,6 @@
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Core/CVarSet.h>
 
 namespace anki {

+ 2 - 1
AnKi/Renderer/PrimaryNonRenderableVisibility.cpp

@@ -5,6 +5,7 @@
 
 #include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>
 #include <AnKi/Renderer/Renderer.h>
+#include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Shaders/Include/GpuSceneFunctions.h>
 #include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Scene/Components/LightComponent.h>
@@ -92,7 +93,7 @@ void PrimaryNonRenderableVisibility::populateRenderGraph(RenderingContext& ctx)
 			in.m_passesName = passName;
 			in.m_objectType = type;
 			in.m_viewProjectionMat = ctx.m_matrices.m_viewProjection;
-			in.m_hzbRt = nullptr; // TODO
+			in.m_hzbRt = &getRenderer().getGBuffer().getHzbRt();
 			in.m_rgraph = &rgraph;
 
 			const GpuSceneNonRenderableObjectTypeWithFeedback feedbackType = toGpuSceneNonRenderableObjectTypeWithFeedback(type);

+ 0 - 1
AnKi/Renderer/ProbeReflections.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/FinalComposite.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>
 #include <AnKi/Core/CVarSet.h>
 #include <AnKi/Util/Tracer.h>

+ 0 - 49
AnKi/Renderer/RenderQueue.cpp

@@ -1,49 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Renderer/RenderQueue.h>
-
-namespace anki {
-
-U32 RenderQueue::countAllRenderables() const
-{
-	U32 drawableCount = 0;
-	drawableCount += m_renderables.getSize();
-	drawableCount += m_forwardShadingRenderables.getSize();
-
-	for(const SpotLightQueueElement& slight : m_spotLights)
-	{
-		if(slight.m_shadowRenderQueue)
-		{
-			drawableCount += slight.m_shadowRenderQueue->countAllRenderables();
-		}
-	}
-
-	for(const PointLightQueueElement& plight : m_pointLights)
-	{
-		for(U i = 0; i < 6; ++i)
-		{
-			if(plight.m_shadowRenderQueues[i])
-			{
-				drawableCount += plight.m_shadowRenderQueues[i]->countAllRenderables();
-			}
-		}
-	}
-
-	if(m_reflectionProbeForRefresh)
-	{
-		for(U i = 0; i < 6; ++i)
-		{
-			if(m_reflectionProbeForRefresh->m_renderQueues[i])
-			{
-				drawableCount += m_reflectionProbeForRefresh->m_renderQueues[i]->countAllRenderables();
-			}
-		}
-	}
-
-	return drawableCount;
-}
-
-} // end namespace anki

+ 0 - 437
AnKi/Renderer/RenderQueue.h

@@ -1,437 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Renderer/Common.h>
-#include <AnKi/Resource/RenderingKey.h>
-#include <AnKi/Ui/Canvas.h>
-#include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
-#include <AnKi/Shaders/Include/ModelTypes.h>
-
-namespace anki {
-
-/// @addtogroup renderer
-/// @{
-
-class RenderingMatrices
-{
-public:
-	Mat3x4 m_cameraTransform;
-	Mat3x4 m_viewMatrix;
-	Mat4 m_projectionMatrix;
-	Mat4 m_viewProjectionMatrix;
-	Mat4 m_previousViewProjectionMatrix;
-};
-
-/// Render queue element that contains info on items that populate the G-buffer or the forward shading buffer etc.
-class RenderableQueueElement final
-{
-public:
-	U64 m_mergeKey;
-
-	ShaderProgram* m_program;
-
-	U32 m_worldTransformsOffset;
-	U32 m_uniformsOffset;
-	U32 m_meshLodOffset;
-	U32 m_boneTransformsOffset;
-	U32 m_particleEmitterOffset;
-	U32 m_instanceCount;
-
-	union
-	{
-		U32 m_indexCount;
-		U32 m_vertexCount;
-	};
-
-	union
-	{
-		U32 m_firstIndex;
-		U32 m_firstVertex;
-	};
-
-	F32 m_distanceFromCamera; ///< Don't set this. Visibility will.
-
-	Vec3 m_aabbMin;
-	Vec3 m_aabbMax;
-
-	Bool m_indexed;
-	PrimitiveTopology m_primitiveTopology;
-
-	RenderableQueueElement()
-	{
-	}
-
-	void computeMergeKey()
-	{
-		Array<U64, 5> toHash;
-		toHash[0] = ptrToNumber(m_program);
-		toHash[1] = m_indexed;
-		toHash[2] = m_indexCount;
-		toHash[3] = m_firstIndex;
-		toHash[4] = U64(m_primitiveTopology);
-		m_mergeKey = computeHash(toHash.getBegin(), toHash.getSizeInBytes());
-	}
-
-	Bool canMergeWith(const RenderableQueueElement& b) const
-	{
-		return m_mergeKey != 0 && m_mergeKey == b.m_mergeKey;
-	}
-};
-static_assert(std::is_trivially_destructible<RenderableQueueElement>::value == true);
-
-/// Context that contains variables for the GenericGpuComputeJobQueueElement.
-class GenericGpuComputeJobQueueElementContext final : public RenderingMatrices
-{
-public:
-	CommandBufferPtr m_commandBuffer;
-	class RebarTransientMemoryPool* m_rebarStagingPool ANKI_DEBUG_CODE(= nullptr);
-};
-
-/// Callback for GenericGpuComputeJobQueueElement.
-using GenericGpuComputeJobQueueElementCallback = void (*)(GenericGpuComputeJobQueueElementContext& ctx, const void* userData);
-
-/// It has enough info to execute generic compute on the GPU.
-class GenericGpuComputeJobQueueElement final
-{
-public:
-	GenericGpuComputeJobQueueElementCallback m_callback;
-	const void* m_userData;
-
-	GenericGpuComputeJobQueueElement()
-	{
-	}
-};
-static_assert(std::is_trivially_destructible<GenericGpuComputeJobQueueElement>::value == true);
-
-/// Point light render queue element.
-class PointLightQueueElement final
-{
-public:
-	U64 m_uuid;
-	Vec3 m_worldPosition;
-	F32 m_radius;
-	Vec3 m_diffuseColor;
-	Array<RenderQueue*, 6> m_shadowRenderQueues;
-
-	Array<Vec2, 6> m_shadowAtlasTileOffsets; ///< Renderer internal.
-	F32 m_shadowAtlasTileSize; ///< Renderer internal.
-	U8 m_shadowLayer; ///< Renderer internal.
-
-	U32 m_index;
-
-	PointLightQueueElement()
-	{
-	}
-
-	Bool hasShadow() const
-	{
-		return m_shadowRenderQueues[0] != nullptr;
-	}
-};
-static_assert(std::is_trivially_destructible<PointLightQueueElement>::value == true);
-
-/// Spot light render queue element.
-class SpotLightQueueElement final
-{
-public:
-	U64 m_uuid;
-	Mat4 m_worldTransform;
-	Mat4 m_textureMatrix;
-	F32 m_distance;
-	F32 m_outerAngle;
-	F32 m_innerAngle;
-	Vec3 m_diffuseColor;
-	Array<Vec3, 4> m_edgePoints;
-	RenderQueue* m_shadowRenderQueue;
-
-	U8 m_shadowLayer; ///< Renderer internal.
-
-	U32 m_index;
-
-	SpotLightQueueElement()
-	{
-	}
-
-	Bool hasShadow() const
-	{
-		return m_shadowRenderQueue != nullptr;
-	}
-};
-static_assert(std::is_trivially_destructible<SpotLightQueueElement>::value == true);
-
-/// Directional light render queue element.
-class DirectionalLightQueueElement final
-{
-public:
-	Array<Mat4, kMaxShadowCascades> m_textureMatrices;
-	Array<Mat4, kMaxShadowCascades> m_viewProjectionMatrices;
-	Array<RenderQueue*, kMaxShadowCascades> m_shadowRenderQueues;
-	U64 m_uuid; ///< Zero means that there is no dir light
-	Vec3 m_diffuseColor;
-	Vec3 m_direction;
-	Array<F32, kMaxShadowCascades> m_shadowCascadesDistances;
-	U8 m_shadowCascadeCount; ///< Zero means that it doesn't cast any shadows.
-	U8 m_shadowLayer; ///< Renderer internal.
-
-	DirectionalLightQueueElement()
-	{
-	}
-
-	[[nodiscard]] Bool isEnabled() const
-	{
-		return m_uuid != 0;
-	}
-
-	[[nodiscard]] Bool hasShadow() const
-	{
-		return isEnabled() && m_shadowCascadeCount > 0;
-	}
-};
-static_assert(std::is_trivially_destructible<DirectionalLightQueueElement>::value == true);
-
-/// Reflection probe render queue element.
-class ReflectionProbeQueueElement final
-{
-public:
-	Vec3 m_worldPosition;
-	Vec3 m_aabbMin;
-	Vec3 m_aabbMax;
-	U32 m_textureBindlessIndex;
-
-	U32 m_index;
-
-	ReflectionProbeQueueElement()
-	{
-	}
-};
-static_assert(std::is_trivially_destructible<ReflectionProbeQueueElement>::value == true);
-
-/// Contains info for a reflection probe that the renderer will have to refresh.
-class ReflectionProbeQueueElementForRefresh final
-{
-public:
-	Array<RenderQueue*, 6> m_renderQueues;
-	Vec3 m_worldPosition;
-	Texture* m_reflectionTexture;
-};
-
-// Probe for global illumination.
-class GlobalIlluminationProbeQueueElement final
-{
-public:
-	Vec3 m_aabbMin;
-	Vec3 m_aabbMax;
-	UVec3 m_cellCounts;
-	U32 m_totalCellCount;
-	Vec3 m_cellSizes; ///< The cells might not be cubes so have different sizes per dimension.
-	F32 m_fadeDistance;
-	U32 m_volumeTextureBindlessIndex;
-
-	U32 m_index;
-
-	GlobalIlluminationProbeQueueElement()
-	{
-	}
-
-	Bool operator<(const GlobalIlluminationProbeQueueElement& b) const
-	{
-		if(m_cellSizes.x() != b.m_cellSizes.x())
-		{
-			return m_cellSizes.x() < b.m_cellSizes.x();
-		}
-		else
-		{
-			return m_totalCellCount < b.m_totalCellCount;
-		}
-	}
-};
-static_assert(std::is_trivially_destructible<GlobalIlluminationProbeQueueElement>::value == true);
-
-/// Contains info for a GI probe that the renderer will have to refresh.
-class GlobalIlluminationProbeQueueElementForRefresh final
-{
-public:
-	Array<RenderQueue*, 6> m_renderQueues;
-	Texture* m_volumeTexture;
-	UVec3 m_cellToRefresh;
-	UVec3 m_cellCounts;
-
-	GlobalIlluminationProbeQueueElementForRefresh()
-	{
-	}
-};
-
-/// Lens flare render queue element.
-class LensFlareQueueElement final
-{
-public:
-	/// Totaly unsafe but we can't have a smart ptr in here since there will be no deletion.
-	TextureView* m_textureView;
-	Vec3 m_worldPosition;
-	Vec2 m_firstFlareSize;
-	Vec4 m_colorMultiplier;
-
-	LensFlareQueueElement()
-	{
-	}
-};
-static_assert(std::is_trivially_destructible<LensFlareQueueElement>::value == true);
-
-/// Decal render queue element.
-class DecalQueueElement final
-{
-public:
-	U32 m_diffuseBindlessTextureIndex;
-	U32 m_roughnessMetalnessBindlessTextureIndex;
-	F32 m_diffuseBlendFactor;
-	F32 m_roughnessMetalnessBlendFactor;
-	Mat4 m_textureMatrix;
-	Vec3 m_obbCenter;
-	Vec3 m_obbExtend;
-	Mat3 m_obbRotation;
-
-	U32 m_index;
-
-	DecalQueueElement()
-	{
-	}
-};
-static_assert(std::is_trivially_destructible<DecalQueueElement>::value == true);
-
-/// Draw callback for drawing.
-using UiQueueElementDrawCallback = void (*)(CanvasPtr& canvas, void* userData);
-
-/// UI element render queue element.
-class UiQueueElement final
-{
-public:
-	void* m_userData;
-	UiQueueElementDrawCallback m_drawCallback;
-
-	UiQueueElement()
-	{
-	}
-};
-static_assert(std::is_trivially_destructible<UiQueueElement>::value == true);
-
-/// Fog density queue element.
-class FogDensityQueueElement final
-{
-public:
-	union
-	{
-		Vec3 m_aabbMin;
-		Vec3 m_sphereCenter;
-	};
-
-	union
-	{
-		Vec3 m_aabbMax;
-		F32 m_sphereRadius;
-	};
-
-	F32 m_density;
-	U32 m_index;
-	Bool m_isBox;
-
-	FogDensityQueueElement()
-	{
-	}
-};
-static_assert(std::is_trivially_destructible<FogDensityQueueElement>::value == true);
-
-/// A callback to fill a coverage buffer.
-using FillCoverageBufferCallback = void (*)(void* userData, F32* depthValues, U32 width, U32 height);
-
-/// Ray tracing queue element.
-class RayTracingInstanceQueueElement final
-{
-public:
-	AccelerationStructure* m_bottomLevelAccelerationStructure;
-	U32 m_shaderGroupHandleIndex;
-
-	U32 m_worldTransformsOffset;
-	U32 m_uniformsOffset;
-	U32 m_geometryOffset;
-
-	U32 m_indexBufferOffset;
-
-	Mat3x4 m_transform;
-};
-static_assert(std::is_trivially_destructible<RayTracingInstanceQueueElement>::value == true);
-
-/// Skybox info.
-class SkyboxQueueElement final
-{
-public:
-	TextureView* m_skyboxTexture;
-	Vec3 m_solidColor;
-
-	class
-	{
-	public:
-		F32 m_minDensity;
-		F32 m_maxDensity;
-		F32 m_heightOfMinDensity; ///< The height (meters) where fog density is max.
-		F32 m_heightOfMaxDensity; ///< The height (meters) where fog density is the min value.
-		F32 m_scatteringCoeff;
-		F32 m_absorptionCoeff;
-		Vec3 m_diffuseColor;
-	} m_fog;
-};
-static_assert(std::is_trivially_destructible<SkyboxQueueElement>::value == true);
-
-/// The render queue. This is what the renderer is fed to render.
-class RenderQueue : public RenderingMatrices
-{
-public:
-	WeakArray<RenderableQueueElement> m_renderables; ///< Deferred shading or shadow renderables.
-	WeakArray<RenderableQueueElement> m_forwardShadingRenderables;
-	WeakArray<PointLightQueueElement> m_pointLights; ///< Those who cast shadows are first.
-	WeakArray<SpotLightQueueElement> m_spotLights; ///< Those who cast shadows are first.
-	DirectionalLightQueueElement m_directionalLight;
-	WeakArray<ReflectionProbeQueueElement> m_reflectionProbes;
-	WeakArray<GlobalIlluminationProbeQueueElement> m_giProbes;
-	WeakArray<LensFlareQueueElement> m_lensFlares;
-	WeakArray<DecalQueueElement> m_decals;
-	WeakArray<FogDensityQueueElement> m_fogDensityVolumes;
-	WeakArray<UiQueueElement> m_uis;
-	WeakArray<GenericGpuComputeJobQueueElement> m_genericGpuComputeJobs;
-	WeakArray<RayTracingInstanceQueueElement> m_rayTracingInstances;
-
-	/// Contains the ray tracing elements. The rest of the members are unused. It's separate to avoid multithreading bugs.
-	RenderQueue* m_rayTracingQueue = nullptr;
-
-	SkyboxQueueElement m_skybox;
-
-	/// Applies only if the RenderQueue holds shadow casters. It's the max timesamp of all shadow casters
-	Timestamp m_shadowRenderablesLastUpdateTimestamp = 0;
-
-	F32 m_cameraNear;
-	F32 m_cameraFar;
-	F32 m_cameraFovX;
-	F32 m_cameraFovY;
-
-	FillCoverageBufferCallback m_fillCoverageBufferCallback = nullptr;
-	void* m_fillCoverageBufferCallbackUserData = nullptr;
-
-	ReflectionProbeQueueElementForRefresh* m_reflectionProbeForRefresh = nullptr;
-	GlobalIlluminationProbeQueueElementForRefresh* m_giProbeForRefresh = nullptr;
-
-	RenderQueue()
-	{
-		zeroMemory(m_directionalLight);
-		zeroMemory(m_skybox);
-	}
-
-	U32 countAllRenderables() const;
-};
-
-static_assert(std::is_trivially_destructible<RenderQueue>::value == true);
-/// @}
-
-} // end namespace anki

+ 0 - 1
AnKi/Renderer/Renderer.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Util/ThreadHive.h>
 #include <AnKi/Core/CVarSet.h>

+ 3 - 4
AnKi/Renderer/RtShadows.cpp

@@ -10,7 +10,6 @@
 #include <AnKi/Renderer/AccelerationStructureBuilder.h>
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/DepthDownscale.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/ClusterBinning2.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Core/CVarSet.h>
@@ -457,7 +456,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 			rpass.setWork([this, &ctx, passIdx = i](RenderPassWorkContext& rgraphCtx) {
 				CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-				const Bool lastPass = passIdx == m_atrousPassCount - 1;
+				const Bool lastPass = passIdx == U32(m_atrousPassCount - 1);
 				const U32 readRtIdx = (passIdx + 1) & 1;
 
 				if(lastPass)
@@ -544,8 +543,8 @@ void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& r
 	dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2);
 }
 
-void RtShadows::getDebugRenderTarget(CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
-									 ShaderProgramPtr& optionalShaderProgram) const
+void RtShadows::getDebugRenderTarget([[maybe_unused]] CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
+									 [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const
 {
 	handles[0] = m_runCtx.m_upscaledRt;
 }

+ 0 - 24
AnKi/Renderer/ShadowMapping.cpp

@@ -310,30 +310,6 @@ TileAllocatorResult2 ShadowMapping::allocateAtlasTiles(U32 lightUuid, U32 compon
 	return goodResult;
 }
 
-template<typename TMemoryPool>
-void ShadowMapping::newWorkItem(const UVec4& atlasViewport, const RenderQueue& queue, RenderGraphDescription& rgraph,
-								DynamicArray<ViewportWorkItem, TMemoryPool>& workItems, RenderTargetHandle* hzbRt)
-{
-	ViewportWorkItem& work = *workItems.emplaceBack();
-
-	const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
-
-	FrustumGpuVisibilityInput visIn;
-	visIn.m_passesName = "Shadows visibility";
-	visIn.m_technique = RenderingTechnique::kDepth;
-	visIn.m_viewProjectionMatrix = queue.m_viewProjectionMatrix;
-	visIn.m_lodReferencePoint = queue.m_cameraTransform.getTranslationPart().xyz();
-	visIn.m_lodDistances = lodDistances;
-	visIn.m_hzbRt = hzbRt;
-	visIn.m_rgraph = &rgraph;
-
-	getRenderer().getGpuVisibility().populateRenderGraph(visIn, work.m_visOut);
-
-	work.m_viewport = atlasViewport;
-	work.m_mvp = queue.m_viewProjectionMatrix;
-	work.m_viewMatrix = queue.m_viewMatrix;
-}
-
 void ShadowMapping::processLights(RenderingContext& ctx)
 {
 	m_runCtx.m_renderAreaMin = UVec2(kMaxU32, kMaxU32);

+ 0 - 4
AnKi/Renderer/ShadowMapping.h

@@ -73,10 +73,6 @@ private:
 
 	void chooseDetail(const Vec3& cameraOrigin, const LightComponent& lightc, U32& tileAllocatorHierarchy) const;
 
-	template<typename TMemoryPool>
-	void newWorkItem(const UVec4& atlasViewport, const RenderQueue& queue, RenderGraphDescription& rgraph,
-					 DynamicArray<ViewportWorkItem, TMemoryPool>& workItems, RenderTargetHandle* hzbRt = nullptr);
-
 	void runShadowMapping(RenderPassWorkContext& rgraphCtx);
 };
 /// @}

+ 0 - 1
AnKi/Renderer/UiStage.cpp

@@ -5,7 +5,6 @@
 
 #include <AnKi/Renderer/UiStage.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Ui/Font.h>
 #include <AnKi/Ui/UiManager.h>
 #include <AnKi/Scene/Components/UiComponent.h>

+ 0 - 1
AnKi/Renderer/Utils/Drawer.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Renderer/Utils/Drawer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Util/Tracer.h>

+ 0 - 1
AnKi/Renderer/Utils/TraditionalDeferredShading.cpp

@@ -5,7 +5,6 @@
 
 #include <AnKi/Renderer/Utils/TraditionalDeferredShading.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Resource/MeshResource.h>
 #include <AnKi/Resource/ImageResource.h>

+ 0 - 1
AnKi/Renderer/Utils/TraditionalDeferredShading.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Renderer/RendererObject.h>
-#include <AnKi/Renderer/RenderQueue.h>
 
 namespace anki {
 

+ 0 - 1
AnKi/Renderer/VolumetricFog.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/ShadowMapping.h>
 #include <AnKi/Renderer/LightShading.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
 #include <AnKi/Core/CVarSet.h>
 #include <AnKi/Scene/Components/SkyboxComponent.h>

+ 0 - 1
AnKi/Scene.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Scene/Octree.h>
 
 #include <AnKi/Scene/Components/BodyComponent.h>
 #include <AnKi/Scene/Components/CameraComponent.h>

+ 0 - 2
AnKi/Scene/Components/DecalComponent.h

@@ -6,11 +6,9 @@
 #pragma once
 
 #include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Scene/Spatial.h>
 #include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Resource/ImageAtlasResource.h>
 #include <AnKi/Collision/Obb.h>
-#include <AnKi/Renderer/RenderQueue.h>
 
 namespace anki {
 

+ 0 - 2
AnKi/Scene/Components/FogDensityComponent.h

@@ -6,9 +6,7 @@
 #pragma once
 
 #include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Scene/Spatial.h>
 #include <AnKi/Scene/GpuSceneArray.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Collision/Aabb.h>
 #include <AnKi/Collision/Sphere.h>
 

+ 2 - 0
AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp

@@ -9,6 +9,8 @@
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Core/CVarSet.h>
 #include <AnKi/Resource/ResourceManager.h>
+#include <AnKi/Gr/Texture.h>
+#include <AnKi/Gr/CommandBuffer.h>
 
 namespace anki {
 

+ 1 - 2
AnKi/Scene/Components/GlobalIlluminationProbeComponent.h

@@ -7,8 +7,7 @@
 
 #include <AnKi/Scene/Components/SceneComponent.h>
 #include <AnKi/Scene/Frustum.h>
-#include <AnKi/Scene/Spatial.h>
-#include <AnKi/Renderer/RenderQueue.h>
+#include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Collision/Aabb.h>
 
 namespace anki {

+ 0 - 2
AnKi/Scene/Components/LensFlareComponent.h

@@ -6,9 +6,7 @@
 #pragma once
 
 #include <AnKi/Scene/SceneNode.h>
-#include <AnKi/Scene/Spatial.h>
 #include <AnKi/Resource/ImageResource.h>
-#include <AnKi/Renderer/RenderQueue.h>
 
 namespace anki {
 

+ 0 - 1
AnKi/Scene/Components/LightComponent.cpp

@@ -8,7 +8,6 @@
 #include <AnKi/Scene/Frustum.h>
 #include <AnKi/Scene/SceneNode.h>
 #include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Scene/Octree.h>
 #include <AnKi/Collision.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Resource/ImageResource.h>

+ 1 - 2
AnKi/Scene/Components/LightComponent.h

@@ -6,9 +6,8 @@
 #pragma once
 
 #include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Scene/Spatial.h>
+#include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Math.h>
-#include <AnKi/Renderer/RenderQueue.h>
 
 namespace anki {
 

+ 2 - 2
AnKi/Scene/Components/ModelComponent.h

@@ -7,10 +7,10 @@
 
 #include <AnKi/Scene/Components/SceneComponent.h>
 #include <AnKi/Scene/RenderStateBucket.h>
-#include <AnKi/Scene/Spatial.h>
+#include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Resource/Forward.h>
 #include <AnKi/Util/WeakArray.h>
-#include <AnKi/Renderer/RenderQueue.h>
+#include <AnKi/Collision/Aabb.h>
 
 namespace anki {
 

+ 0 - 1
AnKi/Scene/Components/ParticleEmitterComponent.cpp

@@ -13,7 +13,6 @@
 #include <AnKi/Physics/PhysicsCollisionShape.h>
 #include <AnKi/Physics/PhysicsWorld.h>
 #include <AnKi/Math.h>
-#include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Shaders/Include/GpuSceneFunctions.h>
 #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
 

+ 0 - 1
AnKi/Scene/Components/ParticleEmitterComponent.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Scene/Spatial.h>
 #include <AnKi/Scene/RenderStateBucket.h>
 #include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Resource/ParticleEmitterResource.h>

+ 2 - 0
AnKi/Scene/Components/ReflectionProbeComponent.cpp

@@ -8,6 +8,8 @@
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Scene/SceneNode.h>
 #include <AnKi/Core/CVarSet.h>
+#include <AnKi/Gr/Texture.h>
+#include <AnKi/Gr/TextureView.h>
 
 namespace anki {
 

+ 1 - 2
AnKi/Scene/Components/ReflectionProbeComponent.h

@@ -7,8 +7,7 @@
 
 #include <AnKi/Scene/Components/SceneComponent.h>
 #include <AnKi/Scene/Frustum.h>
-#include <AnKi/Scene/Spatial.h>
-#include <AnKi/Renderer/RenderQueue.h>
+#include <AnKi/Scene/GpuSceneArray.h>
 #include <AnKi/Collision/Aabb.h>
 
 namespace anki {

+ 1 - 28
AnKi/Scene/Components/SkyboxComponent.cpp

@@ -8,23 +8,17 @@
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Resource/ResourceManager.h>
-#include <AnKi/Renderer/RenderQueue.h>
 
 namespace anki {
 
 SkyboxComponent::SkyboxComponent(SceneNode* node)
 	: SceneComponent(node, kClassType)
-	, m_spatial(this)
 {
-	m_spatial.setAlwaysVisible(true);
-	m_spatial.setUpdatesOctreeBounds(false);
-
 	SceneGraph::getSingleton().addSkybox(this);
 }
 
 SkyboxComponent::~SkyboxComponent()
 {
-	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 	SceneGraph::getSingleton().removeSkybox(this);
 }
 
@@ -44,29 +38,8 @@ void SkyboxComponent::loadImageResource(CString filename)
 
 Error SkyboxComponent::update([[maybe_unused]] SceneComponentUpdateInfo& info, Bool& updated)
 {
-	updated = m_spatial.update(SceneGraph::getSingleton().getOctree());
+	updated = false;
 	return Error::kNone;
 }
 
-void SkyboxComponent::setupSkyboxQueueElement(SkyboxQueueElement& queueElement) const
-{
-	if(m_type == SkyboxType::kImage2D)
-	{
-		queueElement.m_skyboxTexture = &m_image->getTextureView();
-	}
-	else
-	{
-		queueElement.m_skyboxTexture = nullptr;
-		queueElement.m_solidColor = m_color;
-	}
-
-	queueElement.m_fog.m_minDensity = m_fog.m_minDensity;
-	queueElement.m_fog.m_maxDensity = m_fog.m_maxDensity;
-	queueElement.m_fog.m_heightOfMinDensity = m_fog.m_heightOfMinDensity;
-	queueElement.m_fog.m_heightOfMaxDensity = m_fog.m_heightOfMaxDensity;
-	queueElement.m_fog.m_scatteringCoeff = m_fog.m_scatteringCoeff;
-	queueElement.m_fog.m_absorptionCoeff = m_fog.m_absorptionCoeff;
-	queueElement.m_fog.m_diffuseColor = m_fog.m_diffuseColor;
-}
-
 } // end namespace anki

+ 0 - 4
AnKi/Scene/Components/SkyboxComponent.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Scene/Spatial.h>
 #include <AnKi/Resource/Forward.h>
 #include <AnKi/Math.h>
 
@@ -132,10 +131,7 @@ public:
 		return m_fog.m_diffuseColor;
 	}
 
-	void setupSkyboxQueueElement(SkyboxQueueElement& queueElement) const;
-
 private:
-	Spatial m_spatial;
 	SkyboxType m_type = SkyboxType::kSolidColor;
 	Vec3 m_color = Vec3(0.0f, 0.0f, 0.5f);
 	ImageResourcePtr m_image;

+ 3 - 2
AnKi/Scene/Components/UiComponent.h

@@ -6,14 +6,15 @@
 #pragma once
 
 #include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Scene/Spatial.h>
-#include <AnKi/Renderer/RenderQueue.h>
+#include <AnKi/Ui/Canvas.h>
 
 namespace anki {
 
 /// @addtogroup scene
 /// @{
 
+using UiQueueElementDrawCallback = void (*)(CanvasPtr& canvas, void* userData);
+
 /// UI scene component.
 class UiComponent : public SceneComponent
 {

+ 0 - 391
AnKi/Scene/Octree.cpp

@@ -1,391 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Scene/Octree.h>
-#include <AnKi/Collision/Aabb.h>
-#include <AnKi/Collision/Functions.h>
-#include <AnKi/Util/ThreadHive.h>
-
-namespace anki {
-
-/// Return a heatmap color.
-static Vec3 heatmap(F32 factor)
-{
-	F32 intPart;
-	const F32 fractional = modf(factor * 4.0f, intPart);
-
-	if(intPart < 1.0)
-	{
-		return mix(Vec3(0.0, 0.0, 0.0), Vec3(0.0, 0.0, 1.0), fractional);
-	}
-	else if(intPart < 2.0)
-	{
-		return mix(Vec3(0.0, 0.0, 1.0), Vec3(0.0, 1.0, 0.0), fractional);
-	}
-	else if(intPart < 3.0)
-	{
-		return mix(Vec3(0.0, 1.0, 0.0), Vec3(1.0, 1.0, 0.0), fractional);
-	}
-	else
-	{
-		return mix(Vec3(1.0, 1.0, 0.0), Vec3(1.0, 0.0, 0.0), fractional);
-	}
-}
-
-Octree::~Octree()
-{
-	ANKI_ASSERT(m_placeableCount == 0);
-	cleanupInternal();
-	ANKI_ASSERT(m_rootLeaf == nullptr);
-}
-
-void Octree::init(const Vec3& sceneAabbMin, const Vec3& sceneAabbMax, U32 maxDepth)
-{
-	ANKI_ASSERT(sceneAabbMin < sceneAabbMax);
-	ANKI_ASSERT(maxDepth > 0);
-
-	m_maxDepth = maxDepth;
-	m_sceneAabbMin = sceneAabbMin;
-	m_sceneAabbMax = sceneAabbMax;
-}
-
-void Octree::place(const Aabb& volume, OctreePlaceable* placeable, Bool updateActualSceneBounds)
-{
-	ANKI_ASSERT(placeable);
-	ANKI_ASSERT(testCollision(volume, Aabb(m_sceneAabbMin, m_sceneAabbMax)) && "volume is outside the scene");
-
-	LockGuard<Mutex> lock(m_globalMtx);
-
-	// Remove the placeable from the Octree
-	removeInternal(*placeable);
-
-	// Create the root leaf
-	if(!m_rootLeaf)
-	{
-		m_rootLeaf = newLeaf();
-		m_rootLeaf->m_aabbMin = m_sceneAabbMin;
-		m_rootLeaf->m_aabbMax = m_sceneAabbMax;
-	}
-
-	// And re-place it
-	placeRecursive(volume, placeable, m_rootLeaf, 0);
-	++m_placeableCount;
-
-	// Update the actual scene bounds
-	if(updateActualSceneBounds)
-	{
-		m_actualSceneAabbMin = m_actualSceneAabbMin.min(volume.getMin().xyz());
-		m_actualSceneAabbMax = m_actualSceneAabbMax.max(volume.getMax().xyz());
-	}
-}
-
-void Octree::placeAlwaysVisible(OctreePlaceable* placeable)
-{
-	ANKI_ASSERT(placeable);
-
-	LockGuard<Mutex> lock(m_globalMtx);
-
-	// Remove the placeable from the Octree
-	removeInternal(*placeable);
-
-	// Create the root leaf
-	if(!m_rootLeaf)
-	{
-		m_rootLeaf = newLeaf();
-		m_rootLeaf->m_aabbMin = m_sceneAabbMin;
-		m_rootLeaf->m_aabbMax = m_sceneAabbMax;
-	}
-
-	// Connect placeable and leaf
-	placeable->m_leafs.pushBack(newLeafNode(m_rootLeaf));
-	m_rootLeaf->m_placeables.pushBack(newPlaceableNode(placeable));
-
-	++m_placeableCount;
-}
-
-void Octree::remove(OctreePlaceable& placeable)
-{
-	LockGuard<Mutex> lock(m_globalMtx);
-	removeInternal(placeable);
-}
-
-Bool Octree::volumeTotallyInsideLeaf(const Aabb& volume, const Leaf& leaf)
-{
-	const Vec4& amin = volume.getMin();
-	const Vec4& amax = volume.getMax();
-	const Vec3& bmin = leaf.m_aabbMin;
-	const Vec3& bmax = leaf.m_aabbMax;
-
-	Bool superset = true;
-	superset = superset && amin.x() <= bmin.x();
-	superset = superset && amax.x() >= bmax.x();
-	superset = superset && amin.y() <= bmin.y();
-	superset = superset && amax.y() >= bmax.y();
-	superset = superset && amin.z() <= bmin.z();
-	superset = superset && amax.z() >= bmax.z();
-
-	return superset;
-}
-
-void Octree::placeRecursive(const Aabb& volume, OctreePlaceable* placeable, Leaf* parent, U32 depth)
-{
-	ANKI_ASSERT(placeable);
-	ANKI_ASSERT(parent);
-	ANKI_ASSERT(testCollision(volume, Aabb(parent->m_aabbMin, parent->m_aabbMax)) && "Should be inside");
-
-	if(depth == m_maxDepth || volumeTotallyInsideLeaf(volume, *parent))
-	{
-		// Need to stop and bin the placeable to the leaf
-
-		// Checks
-#if ANKI_ASSERTIONS_ENABLED
-		for(const LeafNode& node : placeable->m_leafs)
-		{
-			ANKI_ASSERT(node.m_leaf != parent && "Already binned. That's wrong");
-		}
-
-		for(const PlaceableNode& node : parent->m_placeables)
-		{
-			ANKI_ASSERT(node.m_placeable != placeable);
-		}
-#endif
-
-		// Connect placeable and leaf
-		placeable->m_leafs.pushBack(newLeafNode(parent));
-		parent->m_placeables.pushBack(newPlaceableNode(placeable));
-
-		return;
-	}
-
-	const Vec4& vMin = volume.getMin();
-	const Vec4& vMax = volume.getMax();
-	const Vec3 center = (parent->m_aabbMax + parent->m_aabbMin) / 2.0f;
-
-	LeafMask maskX;
-	if(vMin.x() > center.x())
-	{
-		// Only right
-		maskX = LeafMask::kRight;
-	}
-	else if(vMax.x() < center.x())
-	{
-		// Only left
-		maskX = LeafMask::kLeft;
-	}
-	else
-	{
-		maskX = LeafMask::kAll;
-	}
-
-	LeafMask maskY;
-	if(vMin.y() > center.y())
-	{
-		// Only top
-		maskY = LeafMask::kTop;
-	}
-	else if(vMax.y() < center.y())
-	{
-		// Only bottom
-		maskY = LeafMask::kBottom;
-	}
-	else
-	{
-		maskY = LeafMask::kAll;
-	}
-
-	LeafMask maskZ;
-	if(vMin.z() > center.z())
-	{
-		// Only front
-		maskZ = LeafMask::kFront;
-	}
-	else if(vMax.z() < center.z())
-	{
-		// Only back
-		maskZ = LeafMask::kBack;
-	}
-	else
-	{
-		maskZ = LeafMask::kAll;
-	}
-
-	const LeafMask maskUnion = maskX & maskY & maskZ;
-	ANKI_ASSERT(!!maskUnion && "Should be inside at least one leaf");
-
-	for(U i = 0; i < 8; ++i)
-	{
-		const LeafMask crntBit = LeafMask(1u << i);
-
-		if(!!(maskUnion & crntBit))
-		{
-			// Inside the leaf, move deeper
-
-			// Create the leaf
-			if(parent->m_children[i] == nullptr)
-			{
-				Leaf* child = newLeaf();
-
-				// Compute AABB
-				Vec3 childAabbMin, childAabbMax;
-				computeChildAabb(crntBit, parent->m_aabbMin, parent->m_aabbMax, center, child->m_aabbMin, child->m_aabbMax);
-
-				parent->m_children[i] = child;
-			}
-
-			// Move deeper
-			placeRecursive(volume, placeable, parent->m_children[i], depth + 1);
-		}
-	}
-}
-
-void Octree::computeChildAabb(LeafMask child, const Vec3& parentAabbMin, const Vec3& parentAabbMax, const Vec3& parentAabbCenter, Vec3& childAabbMin,
-							  Vec3& childAabbMax)
-{
-	ANKI_ASSERT(__builtin_popcount(U32(child)) == 1);
-
-	const Vec3& m = parentAabbMin;
-	const Vec3& M = parentAabbMax;
-	const Vec3& c = parentAabbCenter;
-
-	if(!!(child & LeafMask::kRight))
-	{
-		// Right
-		childAabbMin.x() = c.x();
-		childAabbMax.x() = M.x();
-	}
-	else
-	{
-		// Left
-		childAabbMin.x() = m.x();
-		childAabbMax.x() = c.x();
-	}
-
-	if(!!(child & LeafMask::kTop))
-	{
-		// Top
-		childAabbMin.y() = c.y();
-		childAabbMax.y() = M.y();
-	}
-	else
-	{
-		// Bottom
-		childAabbMin.y() = m.y();
-		childAabbMax.y() = c.y();
-	}
-
-	if(!!(child & LeafMask::kFront))
-	{
-		// Front
-		childAabbMin.z() = c.z();
-		childAabbMax.z() = M.z();
-	}
-	else
-	{
-		// Back
-		childAabbMin.z() = m.z();
-		childAabbMax.z() = c.z();
-	}
-}
-
-void Octree::removeInternal(OctreePlaceable& placeable)
-{
-	const Bool isPlaced = !placeable.m_leafs.isEmpty();
-	if(isPlaced)
-	{
-		while(!placeable.m_leafs.isEmpty())
-		{
-			// Pop a leaf node
-			LeafNode* leafNode = placeable.m_leafs.popFront();
-
-			// Iterate the placeables of the leaf
-			[[maybe_unused]] Bool found = false;
-			for(PlaceableNode& placeableNode : leafNode->m_leaf->m_placeables)
-			{
-				if(placeableNode.m_placeable == &placeable)
-				{
-					found = true;
-					leafNode->m_leaf->m_placeables.erase(&placeableNode);
-					releasePlaceableNode(&placeableNode);
-					break;
-				}
-			}
-			ANKI_ASSERT(found);
-
-			// Delete the leaf node
-			releaseLeafNode(leafNode);
-		}
-
-		// Cleanup the tree if there are no placeables
-		ANKI_ASSERT(m_placeableCount > 0);
-		--m_placeableCount;
-		if(m_placeableCount == 0)
-		{
-			cleanupInternal();
-			ANKI_ASSERT(m_rootLeaf == nullptr);
-		}
-	}
-}
-
-void Octree::cleanupRecursive(Leaf* leaf, Bool& canDeleteLeafUponReturn)
-{
-	ANKI_ASSERT(leaf);
-	canDeleteLeafUponReturn = leaf->m_placeables.getSize() == 0;
-
-	// Do the children
-	for(U i = 0; i < 8; ++i)
-	{
-		Leaf* const child = leaf->m_children[i];
-		if(child)
-		{
-			Bool canDeleteChild;
-			cleanupRecursive(child, canDeleteChild);
-
-			if(canDeleteChild)
-			{
-				releaseLeaf(child);
-				leaf->m_children[i] = nullptr;
-			}
-			else
-			{
-				canDeleteLeafUponReturn = false;
-			}
-		}
-	}
-}
-
-void Octree::cleanupInternal()
-{
-	if(m_rootLeaf)
-	{
-		Bool canDeleteLeaf;
-		cleanupRecursive(m_rootLeaf, canDeleteLeaf);
-
-		if(canDeleteLeaf)
-		{
-			releaseLeaf(m_rootLeaf);
-			m_rootLeaf = nullptr;
-		}
-	}
-}
-
-void Octree::debugDrawRecursive(const Leaf& leaf, OctreeDebugDrawer& drawer) const
-{
-	const U32 placeableCount = U32(leaf.m_placeables.getSize());
-	const Vec3 color = (placeableCount > 0) ? heatmap(10.0f / F32(placeableCount)) : Vec3(0.25f);
-
-	const Aabb box(leaf.m_aabbMin, leaf.m_aabbMax);
-	drawer.drawCube(box, Vec4(color, 1.0f));
-
-	for(U i = 0; i < 8; ++i)
-	{
-		Leaf* const child = leaf.m_children[i];
-		if(child)
-		{
-			debugDrawRecursive(*child, drawer);
-		}
-	}
-}
-
-} // end namespace anki

+ 0 - 323
AnKi/Scene/Octree.h

@@ -1,323 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Scene/Common.h>
-#include <AnKi/Math.h>
-#include <AnKi/Collision/Aabb.h>
-#include <AnKi/Util/WeakArray.h>
-#include <AnKi/Util/Enum.h>
-#include <AnKi/Util/ObjectAllocator.h>
-#include <AnKi/Util/List.h>
-#include <AnKi/Util/Tracer.h>
-
-namespace anki {
-
-// Forward
-class OctreePlaceable;
-class ThreadHive;
-class ThreadHiveSemaphore;
-
-/// @addtogroup scene
-/// @{
-
-/// Callback to determine if an octree node is visible.
-using OctreeNodeVisibilityTestCallback = Bool (*)(void* userData, const Aabb& box);
-
-/// Octree debug drawer.
-class OctreeDebugDrawer
-{
-public:
-	virtual void drawCube(const Aabb& box, const Vec4& color) = 0;
-};
-
-/// Octree for visibility tests.
-class Octree
-{
-	friend class OctreePlaceable;
-
-public:
-	Octree() = default;
-
-	Octree(const Octree&) = delete; // Non-copyable
-
-	~Octree();
-
-	Octree& operator=(const Octree&) = delete; // Non-copyable
-
-	void init(const Vec3& sceneAabbMin, const Vec3& sceneAabbMax, U32 maxDepth);
-
-	/// Place or re-place an element in the tree.
-	/// @note It's thread-safe against place and remove methods.
-	void place(const Aabb& volume, OctreePlaceable* placeable, Bool updateActualSceneBounds);
-
-	/// Place the placeable somewhere where it's always visible.
-	/// @note It's thread-safe against place and remove methods.
-	void placeAlwaysVisible(OctreePlaceable* placeable);
-
-	/// Remove an element from the tree.
-	/// @note It's thread-safe against place and remove methods.
-	void remove(OctreePlaceable& placeable);
-
-	/// Walk the tree.
-	/// @tparam TTestAabbFunc The lambda that will test an Aabb. Signature of lambda: Bool(*)(const Aabb& leafBox)
-	/// @tparam TNewPlaceableFunc The lambda to do something with a visible placeable.
-	///                           Signature: void(*)(void* placeableUserData).
-	/// @param testId The test index.
-	/// @param testFunc See TTestAabbFunc.
-	/// @param newPlaceableFunc See TNewPlaceableFunc.
-	template<typename TTestAabbFunc, typename TNewPlaceableFunc>
-	void walkTree(U32 testId, TTestAabbFunc testFunc, TNewPlaceableFunc newPlaceableFunc)
-	{
-		if(m_rootLeaf) [[likely]]
-		{
-			walkTreeInternal(*m_rootLeaf, testId, testFunc, newPlaceableFunc);
-		}
-	}
-
-	/// Debug draw.
-	void debugDraw(OctreeDebugDrawer& drawer) const
-	{
-		ANKI_ASSERT(m_rootLeaf);
-		debugDrawRecursive(*m_rootLeaf, drawer);
-	}
-
-	/// Get the bounds of the scene as calculated by the objects that were placed inside the Octree.
-	void getActualSceneBounds(Vec3& min, Vec3& max) const
-	{
-		LockGuard<Mutex> lock(m_globalMtx);
-		ANKI_ASSERT(m_actualSceneAabbMin.x() < kMaxF32);
-		ANKI_ASSERT(m_actualSceneAabbMax.x() > kMinF32);
-		min = m_actualSceneAabbMin;
-		max = m_actualSceneAabbMax;
-	}
-
-private:
-	/// List node.
-	class PlaceableNode : public IntrusiveListEnabled<PlaceableNode>
-	{
-	public:
-		OctreePlaceable* m_placeable = nullptr;
-
-#if ANKI_ASSERTIONS_ENABLED
-		~PlaceableNode()
-		{
-			m_placeable = nullptr;
-		}
-#endif
-	};
-
-	/// Octree leaf.
-	/// @warning Keept its size as small as possible.
-	class Leaf
-	{
-	public:
-		IntrusiveList<PlaceableNode> m_placeables;
-		Vec3 m_aabbMin;
-		Vec3 m_aabbMax;
-		Array<Leaf*, 8> m_children = {};
-
-#if ANKI_ASSERTIONS_ENABLED
-		~Leaf()
-		{
-			ANKI_ASSERT(m_placeables.isEmpty());
-			m_children = {};
-			m_aabbMin = m_aabbMax = Vec3(0.0f);
-		}
-#endif
-
-		Bool hasChildren() const
-		{
-			return m_children[0] != nullptr || m_children[1] != nullptr || m_children[2] != nullptr || m_children[3] != nullptr
-				   || m_children[4] != nullptr || m_children[5] != nullptr || m_children[6] != nullptr || m_children[7] != nullptr;
-		}
-	};
-
-	/// Used so that OctreePlaceable knows which leafs it belongs to.
-	class LeafNode : public IntrusiveListEnabled<LeafNode>
-	{
-	public:
-		Leaf* m_leaf = nullptr;
-
-#if ANKI_ASSERTIONS_ENABLED
-		~LeafNode()
-		{
-			m_leaf = nullptr;
-		}
-#endif
-	};
-
-	/// Pos: Stands for positive and Neg: Negative
-	enum class LeafMask : U8
-	{
-		kPosXPosYPosZ = 1 << 0,
-		kPosXPosYNegZ = 1 << 1,
-		kPosXNegYPosZ = 1 << 2,
-		kPosXNegYNegZ = 1 << 3,
-		kNegXPosYPosZ = 1 << 4,
-		kNegXPosYNegZ = 1 << 5,
-		kNegXNegYPosZ = 1 << 6,
-		kNegXNegYNegZ = 1 << 7,
-
-		kNone = 0,
-		kAll = kPosXPosYPosZ | kPosXPosYNegZ | kPosXNegYPosZ | kPosXNegYNegZ | kNegXPosYPosZ | kNegXPosYNegZ | kNegXNegYPosZ | kNegXNegYNegZ,
-		kRight = kPosXPosYPosZ | kPosXPosYNegZ | kPosXNegYPosZ | kPosXNegYNegZ,
-		kLeft = kNegXPosYPosZ | kNegXPosYNegZ | kNegXNegYPosZ | kNegXNegYNegZ,
-		kTop = kPosXPosYPosZ | kPosXPosYNegZ | kNegXPosYPosZ | kNegXPosYNegZ,
-		kBottom = kPosXNegYPosZ | kPosXNegYNegZ | kNegXNegYPosZ | kNegXNegYNegZ,
-		kFront = kPosXPosYPosZ | kPosXNegYPosZ | kNegXPosYPosZ | kNegXNegYPosZ,
-		kBack = kPosXPosYNegZ | kPosXNegYNegZ | kNegXPosYNegZ | kNegXNegYNegZ,
-	};
-	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS_FRIEND(LeafMask)
-
-	U32 m_maxDepth = 0;
-	Vec3 m_sceneAabbMin = Vec3(0.0f);
-	Vec3 m_sceneAabbMax = Vec3(0.0f);
-	mutable Mutex m_globalMtx;
-
-	ObjectAllocatorSameType<Leaf, SingletonMemoryPoolWrapper<SceneMemoryPool>, 256> m_leafAlloc;
-	ObjectAllocatorSameType<LeafNode, SingletonMemoryPoolWrapper<SceneMemoryPool>, 128> m_leafNodeAlloc;
-	ObjectAllocatorSameType<PlaceableNode, SingletonMemoryPoolWrapper<SceneMemoryPool>, 256> m_placeableNodeAlloc;
-
-	Leaf* m_rootLeaf = nullptr;
-	U32 m_placeableCount = 0;
-
-	/// Compute the min of the scene bounds based on what is placed inside the octree.
-	Vec3 m_actualSceneAabbMin = Vec3(kMaxF32);
-	Vec3 m_actualSceneAabbMax = Vec3(kMinF32);
-
-	Leaf* newLeaf()
-	{
-		return m_leafAlloc.newInstance();
-	}
-
-	void releaseLeaf(Leaf* leaf)
-	{
-		m_leafAlloc.deleteInstance(leaf);
-	}
-
-	PlaceableNode* newPlaceableNode(OctreePlaceable* placeable)
-	{
-		ANKI_ASSERT(placeable);
-		PlaceableNode* out = m_placeableNodeAlloc.newInstance();
-		out->m_placeable = placeable;
-		return out;
-	}
-
-	void releasePlaceableNode(PlaceableNode* placeable)
-	{
-		m_placeableNodeAlloc.deleteInstance(placeable);
-	}
-
-	LeafNode* newLeafNode(Leaf* leaf)
-	{
-		ANKI_ASSERT(leaf);
-		LeafNode* out = m_leafNodeAlloc.newInstance();
-		out->m_leaf = leaf;
-		return out;
-	}
-
-	void releaseLeafNode(LeafNode* node)
-	{
-		m_leafNodeAlloc.deleteInstance(node);
-	}
-
-	void placeRecursive(const Aabb& volume, OctreePlaceable* placeable, Leaf* parent, U32 depth);
-
-	static Bool volumeTotallyInsideLeaf(const Aabb& volume, const Leaf& leaf);
-
-	static void computeChildAabb(LeafMask child, const Vec3& parentAabbMin, const Vec3& parentAabbMax, const Vec3& parentAabbCenter,
-								 Vec3& childAabbMin, Vec3& childAabbMax);
-
-	/// Remove a placeable from the tree.
-	void removeInternal(OctreePlaceable& placeable);
-
-	/// Remove a leaf.
-	void cleanupRecursive(Leaf* leaf, Bool& canDeleteLeafUponReturn);
-
-	/// Cleanup the tree.
-	void cleanupInternal();
-
-	/// Debug draw.
-	void debugDrawRecursive(const Leaf& leaf, OctreeDebugDrawer& drawer) const;
-
-	template<typename TTestAabbFunc, typename TNewPlaceableFunc>
-	void walkTreeInternal(Leaf& leaf, U32 testId, TTestAabbFunc testFunc, TNewPlaceableFunc newPlaceableFunc);
-};
-
-/// An entity that can be placed in octrees.
-class OctreePlaceable
-{
-	friend class Octree;
-
-public:
-	void* m_userData = nullptr;
-
-	OctreePlaceable() = default;
-
-	OctreePlaceable(const OctreePlaceable&) = delete; // Non-copyable
-
-	OctreePlaceable& operator=(const OctreePlaceable&) = delete; // Non-copyable
-
-	void reset()
-	{
-		for(Atomic<U64>& mask : m_visitedMasks)
-		{
-			mask.setNonAtomically(0);
-		}
-	}
-
-private:
-	static constexpr U32 kMaxTests = 128;
-	Array<Atomic<U64>, kMaxTests / 64> m_visitedMasks = {0u, 0u};
-	IntrusiveList<Octree::LeafNode> m_leafs; ///< A list of leafs this placeable belongs.
-
-	/// Check if already visited.
-	/// @note It's thread-safe.
-	Bool alreadyVisited(U32 testId)
-	{
-		ANKI_ASSERT(testId < kMaxTests);
-		const U32 group = testId / 64;
-		const U64 testMask = U64(1u) << U64(testId % 64);
-		const U64 prev = m_visitedMasks[group].fetchOr(testMask);
-		return !!(testMask & prev);
-	}
-};
-
-template<typename TTestAabbFunc, typename TNewPlaceableFunc>
-inline void Octree::walkTreeInternal(Leaf& leaf, U32 testId, TTestAabbFunc testFunc, TNewPlaceableFunc newPlaceableFunc)
-{
-	// Visit the placeables that belong to that leaf
-	for(PlaceableNode& placeableNode : leaf.m_placeables)
-	{
-		if(!placeableNode.m_placeable->alreadyVisited(testId))
-		{
-			ANKI_ASSERT(placeableNode.m_placeable->m_userData);
-			newPlaceableFunc(placeableNode.m_placeable->m_userData);
-		}
-	}
-
-	Aabb aabb;
-	[[maybe_unused]] U visibleLeafs = 0;
-	for(Leaf* child : leaf.m_children)
-	{
-		if(child)
-		{
-			aabb.setMin(child->m_aabbMin);
-			aabb.setMax(child->m_aabbMax);
-			if(testFunc(aabb))
-			{
-				++visibleLeafs;
-				walkTreeInternal(*child, testId, testFunc, newPlaceableFunc);
-			}
-		}
-	}
-
-	ANKI_TRACE_INC_COUNTER(SceneOctreeVisibleLeafs, visibleLeafs);
-}
-/// @}
-
-} // end namespace anki

+ 0 - 17
AnKi/Scene/SceneGraph.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Scene/Octree.h>
 #include <AnKi/Scene/RenderStateBucket.h>
 #include <AnKi/Physics/PhysicsWorld.h>
 #include <AnKi/Resource/ResourceManager.h>
@@ -40,7 +39,6 @@
 namespace anki {
 
 static StatCounter g_sceneUpdateTime(StatCategory::kTime, "All scene update", StatFlag::kMilisecond | StatFlag::kShowAverage);
-static StatCounter g_sceneVisibilityTime(StatCategory::kTime, "Scene visibility", StatFlag::kMilisecond | StatFlag::kShowAverage);
 static StatCounter g_scenePhysicsTime(StatCategory::kTime, "Physics", StatFlag::kMilisecond | StatFlag::kShowAverage);
 
 static NumericCVar<U32> g_octreeMaxDepthCVar(CVarSubsystem::kScene, "OctreeMaxDepth", 5, 2, 10, "The max depth of the octree");
@@ -97,11 +95,6 @@ SceneGraph::~SceneGraph()
 
 	deleteNodesMarkedForDeletion();
 
-	if(m_octree)
-	{
-		deleteInstance(SceneMemoryPool::getSingleton(), m_octree);
-	}
-
 #define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) GpuSceneArrays::arrayName::freeSingleton();
 #include <AnKi/Scene/GpuSceneArrays.def.h>
 
@@ -114,9 +107,6 @@ Error SceneGraph::init(AllocAlignedCallback allocCallback, void* allocCallbackDa
 
 	m_framePool.init(allocCallback, allocCallbackData, 1_MB, 2.0, 0, true, ANKI_SAFE_ALIGNMENT, "SceneGraphFramePool");
 
-	m_octree = newInstance<Octree>(SceneMemoryPool::getSingleton());
-	m_octree->init(Vec3(-1000.0f, -200.0f, -1000.0f), Vec3(1000.0f, 200.0f, 1000.0f), g_octreeMaxDepthCVar.get());
-
 	// Init the default main camera
 	ANKI_CHECK(newSceneNode<SceneNode>("mainCamera", m_defaultMainCam));
 	CameraComponent* camc = m_defaultMainCam->newComponent<CameraComponent>();
@@ -289,13 +279,6 @@ Error SceneGraph::update(Second prevUpdateTime, Second crntTime)
 	return Error::kNone;
 }
 
-void SceneGraph::doVisibilityTests(RenderQueue& rqueue)
-{
-	const Second startTime = HighRezTimer::getCurrentTime();
-	doVisibilityTests(*m_mainCam, *this, rqueue);
-	g_sceneVisibilityTime.set((HighRezTimer::getCurrentTime() - startTime) * 1000.0);
-}
-
 Error SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)
 {
 	ANKI_TRACE_INC_COUNTER(SceneNodeUpdated, 1);

+ 0 - 14
AnKi/Scene/SceneGraph.h

@@ -17,7 +17,6 @@
 namespace anki {
 
 // Forward
-class Octree;
 class RenderQueue;
 extern NumericCVar<F32> g_probeEffectiveDistanceCVar;
 extern NumericCVar<F32> g_probeShadowEffectiveDistanceCVar;
@@ -93,8 +92,6 @@ public:
 
 	Error update(Second prevUpdateTime, Second crntTime);
 
-	void doVisibilityTests(RenderQueue& rqueue);
-
 	SceneNode& findSceneNode(const CString& name);
 	SceneNode* tryFindSceneNode(const CString& name);
 
@@ -150,12 +147,6 @@ public:
 		return m_nodesUuid.fetchAdd(1);
 	}
 
-	Octree& getOctree()
-	{
-		ANKI_ASSERT(m_octree);
-		return *m_octree;
-	}
-
 	SceneComponentArrays& getComponentArrays()
 	{
 		return m_componentArrays;
@@ -242,8 +233,6 @@ private:
 
 	EventManager m_events;
 
-	Octree* m_octree = nullptr;
-
 	Vec3 m_sceneMin = Vec3(kMaxF32);
 	Vec3 m_sceneMax = Vec3(kMinF32);
 	mutable SpinLock m_sceneBoundsMtx;
@@ -270,9 +259,6 @@ private:
 
 	Error updateNodes(UpdateSceneNodesCtx& ctx);
 	Error updateNode(Second prevTime, Second crntTime, SceneNode& node);
-
-	/// Do visibility tests.
-	static void doVisibilityTests(SceneNode& frustumable, SceneGraph& scene, RenderQueue& rqueue);
 };
 
 template<typename Node, typename... Args>

+ 0 - 157
AnKi/Scene/Spatial.h

@@ -1,157 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Scene/Octree.h>
-#include <AnKi/Scene/Components/SceneComponent.h>
-#include <AnKi/Collision.h>
-
-namespace anki {
-
-/// @addtogroup scene
-/// @{
-
-/// A class that assists with visibility testing.
-class Spatial
-{
-public:
-	Spatial(SceneComponent* owner)
-		: m_owner(owner)
-		, m_sceneComponentType(owner->getType())
-	{
-		ANKI_ASSERT(owner);
-		m_octreeInfo.m_userData = this;
-	}
-
-	Spatial(const Spatial&) = delete;
-
-	~Spatial()
-	{
-		ANKI_ASSERT(!m_placed && "Forgot to call removeFromOctree");
-	}
-
-	Spatial& operator=(const Spatial&) = delete;
-
-	const SceneComponent& getSceneComponent() const
-	{
-		return *m_owner;
-	}
-
-	SceneComponent& getSceneComponent()
-	{
-		return *m_owner;
-	}
-
-	SceneComponentType getSceneComponentClassId() const
-	{
-		return m_sceneComponentType;
-	}
-
-	const Aabb& getAabbWorldSpace() const
-	{
-		ANKI_ASSERT(!m_alwaysVisible || !m_dirty);
-		return m_aabb;
-	}
-
-	/// Update the "actual scene bounds" of the octree or not.
-	void setUpdatesOctreeBounds(Bool update)
-	{
-		m_updatesOctreeBounds = update;
-	}
-
-	/// Make it or not always visible.
-	void setAlwaysVisible(Bool alwaysVisible)
-	{
-		m_alwaysVisible = alwaysVisible;
-	}
-
-	/// Check if it's always visible or not.
-	Bool getAlwaysVisible() const
-	{
-		return m_alwaysVisible;
-	}
-
-	template<typename TCollisionShape>
-	void setBoundingShape(const TCollisionShape& shape)
-	{
-		m_aabb = computeAabb(shape);
-		m_dirty = true;
-	}
-
-	template<typename TVec>
-	void setBoundingShape(ConstWeakArray<TVec> points)
-	{
-		ANKI_ASSERT(points.getSize() > 0);
-		TVec min(kMaxF32), max(kMinF32);
-		for(const TVec& point : points)
-		{
-			min = min.min(point);
-			max = max.max(point);
-		}
-		m_aabb.setMin(min.xyz());
-		m_aabb.setMax(max.xyz());
-		m_dirty = true;
-	}
-
-	/// Should be called each frame.
-	/// @return True if updated.
-	Bool update(Octree& octree)
-	{
-		const Bool updated = m_dirty;
-
-		if(m_dirty)
-		{
-			if(!m_alwaysVisible) [[likely]]
-			{
-				octree.place(m_aabb, &m_octreeInfo, m_updatesOctreeBounds);
-			}
-			else
-			{
-				octree.placeAlwaysVisible(&m_octreeInfo);
-			}
-
-			m_placed = true;
-			m_dirty = false;
-		}
-
-		ANKI_ASSERT(m_placed);
-		m_octreeInfo.reset();
-		return updated;
-	}
-
-	void removeFromOctree(Octree& octree)
-	{
-		if(m_placed)
-		{
-			octree.remove(m_octreeInfo);
-			m_placed = false;
-			m_dirty = true;
-		}
-	}
-
-private:
-	Aabb m_aabb = Aabb(Vec3(-1.0f), Vec3(1.0f)); ///< A faster shape.
-
-	OctreePlaceable m_octreeInfo;
-
-	SceneComponent* m_owner;
-	SceneComponentType m_sceneComponentType; ///< Cache it.
-
-	Bool m_placed : 1 = false;
-	Bool m_updatesOctreeBounds : 1 = true;
-	Bool m_alwaysVisible : 1 = false;
-	Bool m_dirty : 1 = true;
-};
-
-template<>
-inline void Spatial::setBoundingShape<Aabb>(const Aabb& shape)
-{
-	m_aabb = shape;
-	m_dirty = true;
-}
-/// @}
-
-} // end namespace anki

+ 0 - 620
AnKi/Scene/Visibility.cpp

@@ -1,620 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Scene/VisibilityInternal.h>
-#include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Scene/Components/LensFlareComponent.h>
-#include <AnKi/Scene/Components/ModelComponent.h>
-#include <AnKi/Scene/Components/ReflectionProbeComponent.h>
-#include <AnKi/Scene/Components/DecalComponent.h>
-#include <AnKi/Scene/Components/MoveComponent.h>
-#include <AnKi/Scene/Components/FogDensityComponent.h>
-#include <AnKi/Scene/Components/LightComponent.h>
-#include <AnKi/Scene/Components/GlobalIlluminationProbeComponent.h>
-#include <AnKi/Scene/Components/ParticleEmitterComponent.h>
-#include <AnKi/Scene/Components/UiComponent.h>
-#include <AnKi/Scene/Components/SkyboxComponent.h>
-#include <AnKi/Scene/Components/CameraComponent.h>
-#include <AnKi/Renderer/MainRenderer.h>
-#include <AnKi/Util/Logger.h>
-#include <AnKi/Util/ThreadHive.h>
-#include <AnKi/Core/CVarSet.h>
-
-namespace anki {
-
-static U8 computeLod(const Frustum& frustum, F32 distanceFromTheNearPlane)
-{
-	static_assert(kMaxLodCount == 3, "Wrong assumption");
-	U8 lod;
-	if(distanceFromTheNearPlane < 0.0f)
-	{
-		// In RT objects may fall behind the camera, use the max LOD on those
-		lod = 2;
-	}
-	else if(distanceFromTheNearPlane <= frustum.getLodDistance(0))
-	{
-		lod = 0;
-	}
-	else if(distanceFromTheNearPlane <= frustum.getLodDistance(1))
-	{
-		lod = 1;
-	}
-	else
-	{
-		lod = 2;
-	}
-
-	return lod;
-}
-
-static FrustumFlags getCameraFrustumFlags()
-{
-	FrustumFlags flags;
-	flags.m_gatherParticleComponents = true;
-	flags.m_gatherProbeComponents = true;
-	flags.m_gatherLightComponents = true;
-	flags.m_gatherLensFlareComponents = true;
-	flags.m_gatherDecalComponents = true;
-	flags.m_gatherFogDensityComponents = true;
-	flags.m_gatherUiComponents = true;
-	flags.m_gatherSkyComponents = true;
-	flags.m_coverageBuffer = true;
-	flags.m_nonDirectionalLightsCastShadow = true;
-	flags.m_directionalLightsCastShadow = true;
-	return flags;
-}
-
-static FrustumFlags getCameraExtendedFrustumFlags()
-{
-	FrustumFlags flags;
-	flags.m_gatherRayTracingModelComponents = true;
-	flags.m_gatherLightComponents = true;
-	flags.m_gatherSkyComponents = true;
-	return flags;
-}
-
-void VisibilityContext::submitNewWork(const VisibilityFrustum& frustum, const VisibilityFrustum& primaryFrustum, RenderQueue& rqueue,
-									  ThreadHive& hive)
-{
-	ANKI_TRACE_SCOPED_EVENT(SceneVisSubmitWork);
-
-	rqueue.m_cameraTransform = Mat3x4(frustum.m_frustum->getWorldTransform());
-	rqueue.m_viewMatrix = frustum.m_frustum->getViewMatrix();
-	rqueue.m_projectionMatrix = frustum.m_frustum->getProjectionMatrix();
-	rqueue.m_viewProjectionMatrix = frustum.m_frustum->getViewProjectionMatrix();
-	rqueue.m_previousViewProjectionMatrix = frustum.m_frustum->getPreviousViewProjectionMatrix();
-	rqueue.m_cameraNear = frustum.m_frustum->getNear();
-	rqueue.m_cameraFar = frustum.m_frustum->getFar();
-	if(frustum.m_frustum->getFrustumType() == FrustumType::kPerspective)
-	{
-		rqueue.m_cameraFovX = frustum.m_frustum->getFovX();
-		rqueue.m_cameraFovY = frustum.m_frustum->getFovY();
-	}
-	else
-	{
-		rqueue.m_cameraFovX = rqueue.m_cameraFovY = 0.0f;
-	}
-
-	// Check if this frc was tested before
-	{
-		LockGuard<Mutex> l(m_testedFrustumsMtx);
-
-		// Check if already in the list
-		for(const Frustum* x : m_testedFrustums)
-		{
-			if(x == frustum.m_frustum)
-			{
-				return;
-			}
-		}
-
-		// Not there, push it
-		m_testedFrustums.pushBack(frustum.m_frustum);
-	}
-
-	// Prepare the ctx
-	FrustumVisibilityContext* frcCtx = newInstance<FrustumVisibilityContext>(SceneGraph::getSingleton().getFrameMemoryPool());
-	frcCtx->m_visCtx = this;
-	frcCtx->m_frustum = frustum;
-	frcCtx->m_primaryFrustum = primaryFrustum;
-	frcCtx->m_queueViews.resize(hive.getThreadCount());
-	frcCtx->m_visTestsSignalSem = hive.newSemaphore(1);
-	frcCtx->m_renderQueue = &rqueue;
-
-	// Submit new work
-	//
-
-	// Software rasterizer task
-	ThreadHiveSemaphore* prepareRasterizerSem = nullptr;
-	if(frustum.m_coverageBuffer && frustum.m_frustum->hasCoverageBuffer())
-	{
-		// Gather triangles task
-		ThreadHiveTask fillDepthTask = ANKI_THREAD_HIVE_TASK(
-			{ self->fill(); }, newInstance<FillRasterizerWithCoverageTask>(SceneGraph::getSingleton().getFrameMemoryPool(), frcCtx), nullptr,
-			hive.newSemaphore(1));
-
-		hive.submitTasks(&fillDepthTask, 1);
-
-		prepareRasterizerSem = fillDepthTask.m_signalSemaphore;
-	}
-
-	if(frustum.m_coverageBuffer)
-	{
-		rqueue.m_fillCoverageBufferCallback = [](void* ud, F32* depthValues, U32 width, U32 height) {
-			static_cast<Frustum*>(ud)->setCoverageBuffer(depthValues, width, height);
-		};
-		rqueue.m_fillCoverageBufferCallbackUserData = static_cast<Frustum*>(frustum.m_frustum);
-	}
-
-	// Gather visibles from the octree. No need to signal anything because it will spawn new tasks
-	ThreadHiveTask gatherTask = ANKI_THREAD_HIVE_TASK(
-		{ self->gather(hive); }, newInstance<GatherVisiblesFromOctreeTask>(SceneGraph::getSingleton().getFrameMemoryPool(), frcCtx),
-		prepareRasterizerSem, nullptr);
-	hive.submitTasks(&gatherTask, 1);
-
-	// Combind results task
-	ANKI_ASSERT(frcCtx->m_visTestsSignalSem);
-	ThreadHiveTask combineTask =
-		ANKI_THREAD_HIVE_TASK({ self->combine(); }, newInstance<CombineResultsTask>(SceneGraph::getSingleton().getFrameMemoryPool(), frcCtx),
-							  frcCtx->m_visTestsSignalSem, nullptr);
-	hive.submitTasks(&combineTask, 1);
-}
-
-void FillRasterizerWithCoverageTask::fill()
-{
-	ANKI_TRACE_SCOPED_EVENT(SceneVisFillDepth);
-
-	// Get the C-Buffer
-	ConstWeakArray<F32> depthBuff;
-	U32 width;
-	U32 height;
-	m_frcCtx->m_frustum.m_frustum->getCoverageBufferInfo(depthBuff, width, height);
-	ANKI_ASSERT(width > 0 && height > 0 && depthBuff.getSize() > 0);
-
-	// Init the rasterizer
-	if(true)
-	{
-		m_frcCtx->m_r = newInstance<SoftwareRasterizer>(SceneGraph::getSingleton().getFrameMemoryPool());
-		m_frcCtx->m_r->prepare(Mat4(m_frcCtx->m_frustum.m_frustum->getPreviousViewMatrix(1), Vec4(0.0f, 0.0f, 0.0f, 1.0f)),
-							   m_frcCtx->m_frustum.m_frustum->getPreviousProjectionMatrix(1), width, height);
-
-		// Do the work
-		m_frcCtx->m_r->fillDepthBuffer(depthBuff);
-	}
-}
-
-void GatherVisiblesFromOctreeTask::gather(ThreadHive& hive)
-{
-	ANKI_TRACE_SCOPED_EVENT(SceneVisOctreeGather);
-
-	U32 testIdx = m_frcCtx->m_visCtx->m_testsCount.fetchAdd(1);
-
-	// Walk the tree
-	SceneGraph::getSingleton().getOctree().walkTree(
-		testIdx,
-		[&](const Aabb& box) {
-			Bool visible = m_frcCtx->m_frustum.m_frustum->insideFrustum(box);
-			if(visible && m_frcCtx->m_r)
-			{
-				// visible = m_frcCtx->m_r->visibilityTest(box);
-			}
-
-			return visible;
-		},
-		[&](void* placeableUserData) {
-			ANKI_ASSERT(placeableUserData);
-			Spatial* spatial = static_cast<Spatial*>(placeableUserData);
-			const SceneComponentType compType = spatial->getSceneComponentClassId();
-			const FrustumFlags frustumFlags = m_frcCtx->m_frustum;
-
-			Bool gather = false;
-
-			if(compType == ModelComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherModelComponents || frustumFlags.m_gatherShadowCasterModelComponents
-						 || frustumFlags.m_gatherRayTracingModelComponents;
-			}
-			else if(compType == ParticleEmitterComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherParticleComponents;
-			}
-			else if(compType == LightComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherLightComponents;
-			}
-			else if(compType == LensFlareComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherLensFlareComponents;
-			}
-			else if(compType == ReflectionProbeComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherProbeComponents;
-			}
-			else if(compType == DecalComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherDecalComponents;
-			}
-			else if(compType == FogDensityComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherFogDensityComponents;
-			}
-			else if(compType == GlobalIlluminationProbeComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherProbeComponents;
-			}
-			else if(compType == UiComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherUiComponents;
-			}
-			else if(compType == SkyboxComponent::kClassType)
-			{
-				gather = frustumFlags.m_gatherSkyComponents;
-			}
-			else
-			{
-				ANKI_ASSERT(0);
-			}
-
-			if(!gather)
-			{
-				return;
-			}
-
-			ANKI_ASSERT(m_spatialCount < m_spatials.getSize());
-			m_spatials[m_spatialCount++] = spatial;
-
-			if(m_spatialCount == m_spatials.getSize())
-			{
-				flush(hive);
-			}
-		});
-
-	// Flush the remaining
-	flush(hive);
-
-	// Fire an additional dummy task to decrease the semaphore to zero
-	GatherVisiblesFromOctreeTask* pself = this; // MSVC workaround
-	ThreadHiveTask task = ANKI_THREAD_HIVE_TASK({}, pself, nullptr, m_frcCtx->m_visTestsSignalSem);
-	hive.submitTasks(&task, 1);
-}
-
-void GatherVisiblesFromOctreeTask::flush(ThreadHive& hive)
-{
-	if(m_spatialCount)
-	{
-		// Create the task
-		VisibilityTestTask* vis = newInstance<VisibilityTestTask>(SceneGraph::getSingleton().getFrameMemoryPool(), m_frcCtx);
-		memcpy(&vis->m_spatialsToTest[0], &m_spatials[0], sizeof(m_spatials[0]) * m_spatialCount);
-		vis->m_spatialToTestCount = m_spatialCount;
-
-		// Increase the semaphore to block the CombineResultsTask
-		m_frcCtx->m_visTestsSignalSem->increaseSemaphore(1);
-
-		// Submit task
-		ThreadHiveTask task = ANKI_THREAD_HIVE_TASK({ self->test(hive, threadId); }, vis, nullptr, m_frcCtx->m_visTestsSignalSem);
-		hive.submitTasks(&task, 1);
-
-		// Clear count
-		m_spatialCount = 0;
-	}
-}
-
-void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
-{
-	ANKI_TRACE_SCOPED_EVENT(SceneVisTest);
-
-	const Frustum& testedFrustum = *m_frcCtx->m_frustum.m_frustum;
-	ANKI_ASSERT(m_frcCtx->m_primaryFrustum.m_frustum);
-	const FrustumFlags frustumFlags = m_frcCtx->m_frustum;
-	const Frustum& primaryFrustum = *m_frcCtx->m_primaryFrustum.m_frustum;
-
-	WeakArray<RenderQueue> nextQueues;
-	WeakArray<VisibilityFrustum> nextFrustums;
-
-	// Iterate
-	RenderQueueView& result = m_frcCtx->m_queueViews[taskId];
-	for(U i = 0; i < m_spatialToTestCount; ++i)
-	{
-		Spatial* spatial = m_spatialsToTest[i];
-		ANKI_ASSERT(spatial);
-		SceneComponent& comp = spatial->getSceneComponent();
-		const SceneComponentType compType = spatial->getSceneComponentClassId();
-		const Aabb& aabb = spatial->getAabbWorldSpace();
-
-		auto isInside = [&] {
-			return spatial->getAlwaysVisible() || (testedFrustum.insideFrustum(aabb) && testAgainstRasterizer(aabb));
-		};
-
-		if(compType == ModelComponent::kClassType)
-		{
-			ANKI_ASSERT(0);
-		}
-		else if(compType == ParticleEmitterComponent::kClassType)
-		{
-			ANKI_ASSERT(0);
-		}
-		else if(compType == LightComponent::kClassType)
-		{
-			ANKI_ASSERT(!"Lights use GPU visibility from now on");
-		}
-		else if(compType == LensFlareComponent::kClassType)
-		{
-		}
-		else if(compType == ReflectionProbeComponent::kClassType)
-		{
-			ANKI_ASSERT(!"Refl probes use GPU visibility from now on");
-		}
-		else if(compType == DecalComponent::kClassType)
-		{
-		}
-		else if(compType == FogDensityComponent::kClassType)
-		{
-		}
-		else if(compType == GlobalIlluminationProbeComponent::kClassType)
-		{
-			ANKI_ASSERT(!"GI probes use GPU visibility from now on");
-		}
-		else if(compType == UiComponent::kClassType)
-		{
-			ANKI_ASSERT(0);
-		}
-		else if(compType == SkyboxComponent::kClassType)
-		{
-			if(!isInside())
-			{
-				continue;
-			}
-
-			const SkyboxComponent& skyboxc = static_cast<SkyboxComponent&>(comp);
-			skyboxc.setupSkyboxQueueElement(result.m_skybox);
-			result.m_skyboxSet = true;
-		}
-		else
-		{
-			ANKI_ASSERT(0);
-		}
-
-		// Add more frustums to the list
-		if(nextQueues.getSize() > 0)
-		{
-			ANKI_ASSERT(nextFrustums.getSize() == nextQueues.getSize());
-			for(U32 i = 0; i < nextQueues.getSize(); ++i)
-			{
-				m_frcCtx->m_visCtx->submitNewWork(nextFrustums[i], m_frcCtx->m_primaryFrustum, nextQueues[i], hive);
-			}
-		}
-	} // end for
-}
-
-void CombineResultsTask::combine()
-{
-	ANKI_TRACE_SCOPED_EVENT(SceneVisCombine);
-
-	RenderQueue& results = *m_frcCtx->m_renderQueue;
-
-	// Compute the timestamp
-	const U32 threadCount = m_frcCtx->m_queueViews.getSize();
-	results.m_shadowRenderablesLastUpdateTimestamp = 0;
-	U32 renderableCount = 0;
-	for(U32 i = 0; i < threadCount; ++i)
-	{
-		results.m_shadowRenderablesLastUpdateTimestamp = max(results.m_shadowRenderablesLastUpdateTimestamp, m_frcCtx->m_queueViews[i].m_timestamp);
-
-		renderableCount += m_frcCtx->m_queueViews[i].m_renderables.m_elementCount;
-	}
-
-	if(renderableCount)
-	{
-		ANKI_ASSERT(results.m_shadowRenderablesLastUpdateTimestamp > 0);
-	}
-	else
-	{
-		ANKI_ASSERT(results.m_shadowRenderablesLastUpdateTimestamp == 0);
-	}
-
-	if(m_frcCtx->m_frustum.m_frustum->getUpdatedThisFrame())
-	{
-		results.m_shadowRenderablesLastUpdateTimestamp = GlobalFrameIndex::getSingleton().m_value;
-	}
-
-#define ANKI_VIS_COMBINE(t_, member_) \
-	{ \
-		Array<TRenderQueueElementStorage<t_>, 64> subStorages; \
-		for(U32 i = 0; i < threadCount; ++i) \
-		{ \
-			subStorages[i] = m_frcCtx->m_queueViews[i].member_; \
-		} \
-		combineQueueElements<t_>(WeakArray<TRenderQueueElementStorage<t_>>(&subStorages[0], threadCount), nullptr, results.member_, nullptr); \
-	}
-
-	ANKI_VIS_COMBINE(RenderableQueueElement, m_renderables);
-	ANKI_VIS_COMBINE(RenderableQueueElement, m_forwardShadingRenderables);
-	ANKI_VIS_COMBINE(PointLightQueueElement, m_pointLights);
-	ANKI_VIS_COMBINE(SpotLightQueueElement, m_spotLights);
-	ANKI_VIS_COMBINE(ReflectionProbeQueueElement, m_reflectionProbes);
-	ANKI_VIS_COMBINE(LensFlareQueueElement, m_lensFlares);
-	ANKI_VIS_COMBINE(DecalQueueElement, m_decals);
-	ANKI_VIS_COMBINE(FogDensityQueueElement, m_fogDensityVolumes);
-	ANKI_VIS_COMBINE(GlobalIlluminationProbeQueueElement, m_giProbes);
-	ANKI_VIS_COMBINE(GenericGpuComputeJobQueueElement, m_genericGpuComputeJobs);
-	ANKI_VIS_COMBINE(RayTracingInstanceQueueElement, m_rayTracingInstances);
-	ANKI_VIS_COMBINE(UiQueueElement, m_uis);
-
-#undef ANKI_VIS_COMBINE
-
-	results.m_reflectionProbeForRefresh = m_frcCtx->m_reflectionProbeForRefresh;
-	results.m_giProbeForRefresh = m_frcCtx->m_giProbeForRefresh;
-
-	for(U32 i = 0; i < threadCount; ++i)
-	{
-		if(m_frcCtx->m_queueViews[i].m_directionalLight.m_uuid != 0)
-		{
-			results.m_directionalLight = m_frcCtx->m_queueViews[i].m_directionalLight;
-		}
-
-		if(m_frcCtx->m_queueViews[i].m_skyboxSet)
-		{
-			results.m_skybox = m_frcCtx->m_queueViews[i].m_skybox;
-		}
-	}
-
-	const Bool isShadowFrustum = m_frcCtx->m_frustum.m_gatherShadowCasterModelComponents;
-
-	// Sort some of the arrays
-	if(!isShadowFrustum)
-	{
-		std::sort(results.m_renderables.getBegin(), results.m_renderables.getEnd(), MaterialDistanceSortFunctor());
-
-		std::sort(results.m_forwardShadingRenderables.getBegin(), results.m_forwardShadingRenderables.getEnd(),
-				  RevDistanceSortFunctor<RenderableQueueElement>());
-	}
-
-	std::sort(results.m_giProbes.getBegin(), results.m_giProbes.getEnd());
-
-	// Sort the ligths as well because some rendering effects expect the same order from frame to frame
-	std::sort(results.m_pointLights.getBegin(), results.m_pointLights.getEnd(),
-			  [](const PointLightQueueElement& a, const PointLightQueueElement& b) -> Bool {
-				  if(a.hasShadow() != b.hasShadow())
-				  {
-					  return a.hasShadow() < b.hasShadow();
-				  }
-				  else
-				  {
-					  return a.m_uuid < b.m_uuid;
-				  }
-			  });
-
-	std::sort(results.m_spotLights.getBegin(), results.m_spotLights.getEnd(),
-			  [](const SpotLightQueueElement& a, const SpotLightQueueElement& b) -> Bool {
-				  if(a.hasShadow() != b.hasShadow())
-				  {
-					  return a.hasShadow() > b.hasShadow();
-				  }
-				  else
-				  {
-					  return a.m_uuid < b.m_uuid;
-				  }
-			  });
-
-	// Cleanup
-	if(m_frcCtx->m_r)
-	{
-		m_frcCtx->m_r->~SoftwareRasterizer();
-	}
-}
-
-template<typename T>
-void CombineResultsTask::combineQueueElements(WeakArray<TRenderQueueElementStorage<T>> subStorages,
-											  WeakArray<TRenderQueueElementStorage<U32>>* ptrSubStorages, WeakArray<T>& combined,
-											  WeakArray<T*>* ptrCombined)
-{
-	StackMemoryPool& framePool = SceneGraph::getSingleton().getFrameMemoryPool();
-
-	U32 totalElCount = subStorages[0].m_elementCount;
-	U32 biggestSubStorageIdx = 0;
-	for(U32 i = 1; i < subStorages.getSize(); ++i)
-	{
-		totalElCount += subStorages[i].m_elementCount;
-
-		if(subStorages[i].m_elementStorage > subStorages[biggestSubStorageIdx].m_elementStorage)
-		{
-			biggestSubStorageIdx = i;
-		}
-	}
-
-	if(totalElCount == 0)
-	{
-		return;
-	}
-
-	// Count ptrSubStorage elements
-	T** ptrIt = nullptr;
-	if(ptrSubStorages != nullptr)
-	{
-		ANKI_ASSERT(ptrCombined);
-		U32 ptrTotalElCount = (*ptrSubStorages)[0].m_elementCount;
-
-		for(U32 i = 1; i < ptrSubStorages->getSize(); ++i)
-		{
-			ptrTotalElCount += (*ptrSubStorages)[i].m_elementCount;
-		}
-
-		// Create the new storage
-		if(ptrTotalElCount > 0)
-		{
-			ptrIt = newArray<T*>(framePool, ptrTotalElCount);
-			*ptrCombined = WeakArray<T*>(ptrIt, ptrTotalElCount);
-		}
-	}
-
-	T* it;
-	if(totalElCount > subStorages[biggestSubStorageIdx].m_elementStorage)
-	{
-		// Can't reuse any of the existing storage, will allocate a brand new one
-
-		it = newArray<T>(framePool, totalElCount);
-		biggestSubStorageIdx = kMaxU32;
-
-		combined = WeakArray<T>(it, totalElCount);
-	}
-	else
-	{
-		// Will reuse existing storage
-
-		it = subStorages[biggestSubStorageIdx].m_elements + subStorages[biggestSubStorageIdx].m_elementCount;
-
-		combined = WeakArray<T>(subStorages[biggestSubStorageIdx].m_elements, totalElCount);
-	}
-
-	for(U32 i = 0; i < subStorages.getSize(); ++i)
-	{
-		if(subStorages[i].m_elementCount == 0)
-		{
-			continue;
-		}
-
-		// Copy the pointers
-		if(ptrIt)
-		{
-			T* base = (i != biggestSubStorageIdx) ? it : subStorages[biggestSubStorageIdx].m_elements;
-
-			for(U32 x = 0; x < (*ptrSubStorages)[i].m_elementCount; ++x)
-			{
-				ANKI_ASSERT((*ptrSubStorages)[i].m_elements[x] < subStorages[i].m_elementCount);
-
-				*ptrIt = base + (*ptrSubStorages)[i].m_elements[x];
-
-				++ptrIt;
-			}
-
-			ANKI_ASSERT(ptrIt <= ptrCombined->getEnd());
-		}
-
-		// Copy the elements
-		if(i != biggestSubStorageIdx)
-		{
-			memcpy(it, subStorages[i].m_elements, sizeof(T) * subStorages[i].m_elementCount);
-			it += subStorages[i].m_elementCount;
-		}
-	}
-}
-
-void SceneGraph::doVisibilityTests(SceneNode& camera, SceneGraph& scene, RenderQueue& rqueue)
-{
-	ANKI_TRACE_SCOPED_EVENT(SceneVisTests);
-
-	ThreadHive& hive = CoreThreadHive::getSingleton();
-
-	VisibilityContext ctx;
-	CameraComponent& camerac = camera.getFirstComponentOfType<CameraComponent>();
-	VisibilityFrustum visFrustum;
-	visFrustum.m_frustum = &camerac.getFrustum();
-	static_cast<FrustumFlags&>(visFrustum) = getCameraFrustumFlags();
-	ctx.submitNewWork(visFrustum, visFrustum, rqueue, hive);
-
-	hive.waitAllTasks();
-}
-
-} // end namespace anki

+ 0 - 290
AnKi/Scene/VisibilityInternal.h

@@ -1,290 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Scene/SoftwareRasterizer.h>
-#include <AnKi/Scene/Octree.h>
-#include <AnKi/Scene/Frustum.h>
-#include <AnKi/Scene/Spatial.h>
-#include <AnKi/Util/Thread.h>
-#include <AnKi/Util/Tracer.h>
-#include <AnKi/Renderer/RenderQueue.h>
-
-namespace anki {
-
-/// @addtogroup scene
-/// @{
-
-constexpr U32 kMaxSpatialsPerVisTest = 48; ///< Num of spatials to test in a single ThreadHive task.
-
-class FrameMemoryPoolWrapper
-{
-public:
-	StackMemoryPool* operator&()
-	{
-		return &SceneGraph::getSingleton().getFrameMemoryPool();
-	}
-
-	operator StackMemoryPool&()
-	{
-		return SceneGraph::getSingleton().getFrameMemoryPool();
-	}
-
-	void* allocate(PtrSize size, PtrSize alignmentBytes)
-	{
-		return SceneGraph::getSingleton().getFrameMemoryPool().allocate(size, alignmentBytes);
-	}
-
-	void free(void* ptr)
-	{
-		SceneGraph::getSingleton().getFrameMemoryPool().free(ptr);
-	}
-};
-
-/// Sort objects on distance
-template<typename T>
-class DistanceSortFunctor
-{
-public:
-	Bool operator()(const T& a, const T& b)
-	{
-		return a.m_distanceFromCamera < b.m_distanceFromCamera;
-	}
-};
-
-template<typename T>
-class RevDistanceSortFunctor
-{
-public:
-	Bool operator()(const T& a, const T& b)
-	{
-		return a.m_distanceFromCamera > b.m_distanceFromCamera;
-	}
-};
-
-/// Sorts first by LOD and then by material (merge key).
-class MaterialDistanceSortFunctor
-{
-public:
-	Bool operator()(const RenderableQueueElement& a, const RenderableQueueElement& b)
-	{
-		return a.m_mergeKey < b.m_mergeKey;
-	}
-};
-
-/// Storage for a single element type.
-template<typename T, U32 kInitialStorage = 32, U32 kStorageGrowRate = 4>
-class TRenderQueueElementStorage
-{
-public:
-	T* m_elements = nullptr;
-	U32 m_elementCount = 0;
-	U32 m_elementStorage = 0;
-
-	T* newElement()
-	{
-		if(m_elementCount + 1 > m_elementStorage) [[unlikely]]
-		{
-			m_elementStorage = max(kInitialStorage, m_elementStorage * kStorageGrowRate);
-
-			const T* oldElements = m_elements;
-			m_elements = static_cast<T*>(SceneGraph::getSingleton().getFrameMemoryPool().allocate(m_elementStorage * sizeof(T), alignof(T)));
-
-			if(oldElements)
-			{
-				memcpy(m_elements, oldElements, sizeof(T) * m_elementCount);
-			}
-		}
-
-		return &m_elements[m_elementCount++];
-	}
-};
-
-class RenderQueueView
-{
-public:
-	TRenderQueueElementStorage<RenderableQueueElement> m_renderables; ///< Deferred shading or shadow renderables.
-	TRenderQueueElementStorage<RenderableQueueElement> m_forwardShadingRenderables;
-	TRenderQueueElementStorage<PointLightQueueElement> m_pointLights;
-	TRenderQueueElementStorage<SpotLightQueueElement> m_spotLights;
-	DirectionalLightQueueElement m_directionalLight;
-	TRenderQueueElementStorage<ReflectionProbeQueueElement> m_reflectionProbes;
-	TRenderQueueElementStorage<LensFlareQueueElement> m_lensFlares;
-	TRenderQueueElementStorage<DecalQueueElement> m_decals;
-	TRenderQueueElementStorage<FogDensityQueueElement> m_fogDensityVolumes;
-	TRenderQueueElementStorage<GlobalIlluminationProbeQueueElement> m_giProbes;
-	TRenderQueueElementStorage<GenericGpuComputeJobQueueElement> m_genericGpuComputeJobs;
-	TRenderQueueElementStorage<RayTracingInstanceQueueElement> m_rayTracingInstances;
-	TRenderQueueElementStorage<UiQueueElement> m_uis;
-	SkyboxQueueElement m_skybox;
-	Bool m_skyboxSet = false;
-
-	Timestamp m_timestamp = 0;
-
-	RenderQueueView()
-	{
-		zeroMemory(m_directionalLight);
-		zeroMemory(m_skybox);
-	}
-};
-
-static_assert(std::is_trivially_destructible<RenderQueueView>::value == true, "Should be trivially destructible");
-
-class FrustumFlags
-{
-public:
-	Bool m_gatherModelComponents : 1 = false;
-	Bool m_gatherShadowCasterModelComponents : 1 = false;
-	Bool m_gatherRayTracingModelComponents : 1 = false;
-	Bool m_gatherParticleComponents : 1 = false;
-	Bool m_gatherProbeComponents : 1 = false;
-	Bool m_gatherLightComponents : 1 = false;
-	Bool m_gatherLensFlareComponents : 1 = false;
-	Bool m_gatherDecalComponents : 1 = false;
-	Bool m_gatherFogDensityComponents : 1 = false;
-	Bool m_gatherUiComponents : 1 = false;
-	Bool m_gatherSkyComponents : 1 = false;
-
-	Bool m_coverageBuffer : 1 = false;
-	Bool m_nonDirectionalLightsCastShadow : 1 = false;
-	Bool m_directionalLightsCastShadow : 1 = false;
-};
-
-class VisibilityFrustum : public FrustumFlags
-{
-public:
-	Frustum* m_frustum = nullptr;
-};
-
-/// Data common for all tasks.
-class VisibilityContext
-{
-public:
-	Atomic<U32> m_testsCount = {0};
-
-	List<const Frustum*, FrameMemoryPoolWrapper> m_testedFrustums;
-	Mutex m_testedFrustumsMtx;
-
-	void submitNewWork(const VisibilityFrustum& frustum, const VisibilityFrustum& primaryFrustum, RenderQueue& result, ThreadHive& hive);
-};
-
-/// A context for a specific test of a frustum component.
-/// @note Should be trivially destructible.
-class FrustumVisibilityContext
-{
-public:
-	VisibilityContext* m_visCtx = nullptr;
-
-	VisibilityFrustum m_frustum; ///< This is the frustum to be tested.
-	VisibilityFrustum m_primaryFrustum; ///< This is the primary camera frustum.
-
-	// S/W rasterizer members
-	SoftwareRasterizer* m_r = nullptr;
-	DynamicArray<Vec3, FrameMemoryPoolWrapper> m_verts;
-	Atomic<U32> m_rasterizedVertCount = {0}; ///< That will be used by the RasterizeTrianglesTask.
-
-	// Visibility test members
-	DynamicArray<RenderQueueView, FrameMemoryPoolWrapper> m_queueViews; ///< Sub result. Will be combined later.
-	ThreadHiveSemaphore* m_visTestsSignalSem = nullptr;
-
-	// Gather results members
-	RenderQueue* m_renderQueue = nullptr;
-
-	ReflectionProbeQueueElementForRefresh* m_reflectionProbeForRefresh = nullptr;
-	Atomic<U32> m_reflectionProbesForRefreshCount = {0};
-
-	Atomic<U32> m_giProbesForRefreshCount = {0};
-	GlobalIlluminationProbeQueueElementForRefresh* m_giProbeForRefresh = nullptr;
-};
-
-/// ThreadHive task to set the depth map of the S/W rasterizer.
-class FillRasterizerWithCoverageTask
-{
-public:
-	FrustumVisibilityContext* m_frcCtx = nullptr;
-
-	FillRasterizerWithCoverageTask(FrustumVisibilityContext* frcCtx)
-		: m_frcCtx(frcCtx)
-	{
-		ANKI_ASSERT(m_frcCtx);
-	}
-
-	void fill();
-};
-static_assert(std::is_trivially_destructible<FillRasterizerWithCoverageTask>::value == true, "Should be trivially destructible");
-
-/// ThreadHive task to get visible nodes from the octree.
-class GatherVisiblesFromOctreeTask
-{
-public:
-	FrustumVisibilityContext* m_frcCtx = nullptr;
-
-	GatherVisiblesFromOctreeTask(FrustumVisibilityContext* frcCtx)
-		: m_frcCtx(frcCtx)
-	{
-		ANKI_ASSERT(m_frcCtx);
-	}
-
-	void gather(ThreadHive& hive);
-
-private:
-	Array<Spatial*, kMaxSpatialsPerVisTest> m_spatials;
-	U32 m_spatialCount = 0;
-
-	/// Submit tasks to test the m_spatials.
-	void flush(ThreadHive& hive);
-};
-static_assert(std::is_trivially_destructible<GatherVisiblesFromOctreeTask>::value == true, "Should be trivially destructible");
-
-/// ThreadHive task that does the actual visibility tests.
-class VisibilityTestTask
-{
-public:
-	FrustumVisibilityContext* m_frcCtx = nullptr;
-
-	Array<Spatial*, kMaxSpatialsPerVisTest> m_spatialsToTest;
-	U32 m_spatialToTestCount = 0;
-
-	VisibilityTestTask(FrustumVisibilityContext* frcCtx)
-		: m_frcCtx(frcCtx)
-	{
-		ANKI_ASSERT(m_frcCtx);
-	}
-
-	void test(ThreadHive& hive, U32 taskId);
-
-private:
-	[[nodiscard]] Bool testAgainstRasterizer(const Aabb& aabb) const
-	{
-		return (m_frcCtx->m_r) ? m_frcCtx->m_r->visibilityTest(aabb) : true;
-	}
-};
-static_assert(std::is_trivially_destructible<VisibilityTestTask>::value == true, "Should be trivially destructible");
-
-/// Task that combines and sorts the results.
-class CombineResultsTask
-{
-public:
-	FrustumVisibilityContext* m_frcCtx = nullptr;
-
-	CombineResultsTask(FrustumVisibilityContext* frcCtx)
-		: m_frcCtx(frcCtx)
-	{
-		ANKI_ASSERT(m_frcCtx);
-	}
-
-	void combine();
-
-private:
-	template<typename T>
-	static void combineQueueElements(WeakArray<TRenderQueueElementStorage<T>> subStorages, WeakArray<TRenderQueueElementStorage<U32>>* ptrSubStorage,
-									 WeakArray<T>& combined, WeakArray<T*>* ptrCombined);
-};
-static_assert(std::is_trivially_destructible<CombineResultsTask>::value == true, "Should be trivially destructible");
-/// @}
-
-} // end namespace anki

+ 0 - 84
Tests/Scene/Octree.cpp

@@ -1,84 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <Tests/Framework/Framework.h>
-#include <AnKi/Scene/Octree.h>
-
-ANKI_TEST(Scene, Octree)
-{
-	HeapAllocator<U8> alloc(allocAligned, nullptr);
-
-	// Fuzzy
-#if 0
-	{
-		Octree octree(alloc);
-		octree.init(Vec3(-100.0f), Vec3(100.0f), 4);
-
-		OrthographicFrustum frustum(-200.0f, 200.0f, -200.0f, 200.0f, 200.0f, -200.0f);
-		frustum.resetTransform(Transform::getIdentity());
-
-		const U ITERATION_COUNT = 1000;
-		Array<OctreePlaceable, ITERATION_COUNT> placeables;
-		std::vector<U32> placed;
-		for(U i = 0; i < ITERATION_COUNT; ++i)
-		{
-			F32 min = randRange(-100.0f, 100.0f - 1.0f);
-			F32 max = randRange(min + 1.0f, 100.0f);
-			Aabb volume(Vec4(Vec3(min), 0.0f), Vec4(Vec3(max), 0.0f));
-
-			I mode = rand() % 3;
-			if(mode == 0)
-			{
-				// Place
-				placeables[i].m_userData = &placeables[i];
-				octree.place(volume, &placeables[i], true);
-				placed.push_back(i);
-			}
-			else if(mode == 1 && placed.size() > 0)
-			{
-				// Remove
-				octree.remove(placeables[placed.back()]);
-				placed.pop_back();
-			}
-			else if(placed.size() > 0)
-			{
-				// Gather
-
-				// Reset the placed
-				for(U32 idx : placed)
-				{
-					placeables[idx].reset();
-				}
-
-				DynamicArrayRaii<void*> arr(alloc);
-				octree.gatherVisible(frustum, 0, nullptr, nullptr, arr);
-
-				ANKI_TEST_EXPECT_EQ(arr.getSize(), placed.size());
-				for(U32 idx : placed)
-				{
-					Bool found = false;
-					for(void* placeable : arr)
-					{
-						if(&placeables[idx] == static_cast<OctreePlaceable*>(placeable))
-						{
-							found = true;
-							break;
-						}
-					}
-
-					ANKI_TEST_EXPECT_EQ(found, true);
-				}
-			}
-		}
-
-		// Remove all
-		while(!placed.empty())
-		{
-			octree.remove(placeables[placed.back()]);
-			placed.pop_back();
-		}
-	}
-#endif
-}