Forráskód Böngészése

Add some class skeletons

Panagiotis Christopoulos Charitos 2 éve
szülő
commit
9d426b7f74

+ 14 - 0
AnKi/Renderer/NonRenderableVisibility.cpp

@@ -0,0 +1,14 @@
+// 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/NonRenderableVisibility.h>
+
+namespace anki {
+
+void NonRenderableVisibility::populateRenderGraph(RenderingContext& rgraph)
+{
+}
+
+} // end namespace anki

+ 27 - 0
AnKi/Renderer/NonRenderableVisibility.h

@@ -0,0 +1,27 @@
+// 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/Gr.h>
+#include <AnKi/Renderer/RendererObject.h>
+#include <AnKi/Shaders/Include/GpuSceneTypes.h>
+
+namespace anki {
+
+/// @addtogroup renderer
+/// @{
+
+/// XXX
+class NonRenderableVisibility : public RendererObject
+{
+public:
+	void populateRenderGraph(RenderingContext& rgraph);
+
+private:
+};
+/// @}
+
+} // end namespace anki

+ 1 - 0
AnKi/Renderer/Renderer.cpp

@@ -291,6 +291,7 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 	}
 
 	ANKI_CHECK(m_visibility.init());
+	ANKI_CHECK(m_nonRenderablesVisibility.init());
 	ANKI_CHECK(m_hzbGenerator.init());
 
 	return Error::kNone;

+ 6 - 0
AnKi/Renderer/Renderer.h

@@ -96,6 +96,11 @@ public:
 		return m_visibility;
 	}
 
+	const GpuVisibilityNonRenderables& getGpuVisibilityNonRenderables() const
+	{
+		return m_nonRenderablesVisibility;
+	}
+
 	const HzbGenerator& getHzbGenerator() const
 	{
 		return m_hzbGenerator;
@@ -200,6 +205,7 @@ private:
 
 	RenderableDrawer m_sceneDrawer;
 	GpuVisibility m_visibility;
+	GpuVisibilityNonRenderables m_nonRenderablesVisibility;
 	HzbGenerator m_hzbGenerator;
 	ReadbackManager m_readbaks;
 

+ 1 - 1
AnKi/Renderer/Utils/GpuVisibility.cpp

@@ -268,7 +268,7 @@ Error GpuVisibilityNonRenderables::init()
 	return Error::kNone;
 }
 
-void GpuVisibilityNonRenderables::populateRenderGraph(GpuVisibilityNonRenderablesInput& in, GpuVisibilityNonRenderablesOutput& out)
+void GpuVisibilityNonRenderables::populateRenderGraph(GpuVisibilityNonRenderablesInput& in, GpuVisibilityNonRenderablesOutput& out) const
 {
 	const GpuSceneContiguousArrayType arrayType = objectTypeToArrayType(in.m_objectType);
 	const U32 objCount = GpuSceneContiguousArrays::getSingleton().getElementCount(arrayType);

+ 1 - 1
AnKi/Renderer/Utils/GpuVisibility.h

@@ -89,7 +89,7 @@ class GpuVisibilityNonRenderables : public RendererObject
 public:
 	Error init();
 
-	void populateRenderGraph(GpuVisibilityNonRenderablesInput& in, GpuVisibilityNonRenderablesOutput& out);
+	void populateRenderGraph(GpuVisibilityNonRenderablesInput& in, GpuVisibilityNonRenderablesOutput& out) const;
 
 private:
 	ShaderProgramResourcePtr m_prog;

+ 1 - 0
AnKi/Util.h

@@ -35,6 +35,7 @@
 #include <AnKi/Util/Visitor.h>
 #include <AnKi/Util/INotify.h>
 #include <AnKi/Util/SparseArray.h>
+#include <AnKi/Util/BlockArray.h>
 #include <AnKi/Util/ObjectAllocator.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Util/Serializer.h>

+ 16 - 0
AnKi/Util/BitSet.h

@@ -264,6 +264,22 @@ public:
 		return kMaxU32;
 	}
 
+	/// Get the least significant bit that is enabled. Or kMaxU32 if all is zero.
+	U32 getLeastSignificantBit() const
+	{
+		for(U32 i = 0; i < kChunkCount; ++i)
+		{
+			const U64 bits = m_chunks[i];
+			if(bits != 0)
+			{
+				const U32 lsb = U32(__builtin_ctzll(bits));
+				return lsb + (i * kChunkBitCount);
+			}
+		}
+
+		return kMaxU32;
+	}
+
 	Array<TChunkType, kChunkCount> getData() const
 	{
 		return m_chunks;

+ 351 - 0
AnKi/Util/BlockArray.h

@@ -0,0 +1,351 @@
+// 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/Util/MemoryPool.h>
+#include <AnKi/Util/Functions.h>
+#include <AnKi/Util/BitSet.h>
+#include <AnKi/Util/DynamicArray.h>
+
+namespace anki {
+
+/// @addtogroup util_containers
+/// @{
+
+/// Config options for a BlockArray.
+/// @tparam T The type of the array.
+template<typename T>
+class BlockArrayDefaultConfig
+{
+public:
+	static constexpr U32 getElementCountPerBlock()
+	{
+		return getAlignedRoundDown(ANKI_CACHE_LINE_SIZE, sizeof(T) * 64) / sizeof(T);
+	}
+};
+
+/// BlockArray iterator.
+template<typename TValuePointer, typename TValueReference, typename TBlockArrayPtr>
+class BlockArrayIterator
+{
+public:
+	/// Default constructor.
+	BlockArrayIterator()
+		: m_array(nullptr)
+		, m_elementIdx(kMaxU32)
+#if ANKI_EXTRA_CHECKS
+		, m_iteratorVer(kMaxU32)
+#endif
+	{
+	}
+
+	/// Copy.
+	BlockArrayIterator(const BlockArrayIterator& b)
+		: m_array(b.m_array)
+		, m_elementIdx(b.m_elementIdx)
+#if ANKI_EXTRA_CHECKS
+		, m_iteratorVer(b.m_iteratorVer)
+#endif
+	{
+	}
+
+	/// Allow conversion from iterator to const iterator.
+	template<typename YValuePointer, typename YValueReference, typename YBlockArrayPtr>
+	BlockArrayIterator(const BlockArrayIterator<YValuePointer, YValueReference, YBlockArrayPtr>& b)
+		: m_array(b.m_array)
+		, m_elementIdx(b.m_elementIdx)
+#if ANKI_EXTRA_CHECKS
+		, m_iteratorVer(b.m_iteratorVer)
+#endif
+	{
+	}
+
+	BlockArrayIterator(TBlockArrayPtr arr, U32 idx
+#if ANKI_EXTRA_CHECKS
+					   ,
+					   U32 ver
+#endif
+					   )
+		: m_array(arr)
+		, m_elementIdx(idx)
+#if ANKI_EXTRA_CHECKS
+		, m_iteratorVer(ver)
+#endif
+	{
+		ANKI_ASSERT(arr);
+	}
+
+	BlockArrayIterator& operator=(const BlockArrayIterator& b)
+	{
+		m_array = b.m_array;
+		m_elementIdx = b.m_elementIdx;
+#if ANKI_EXTRA_CHECKS
+		m_iteratorVer = b.m_iteratorVer;
+#endif
+		return *this;
+	}
+
+	TValueReference operator*() const
+	{
+		check();
+		return (*m_array)[m_elementIdx];
+	}
+
+	TValuePointer operator->() const
+	{
+		check();
+		return &(*m_array)[m_elementIdx];
+	}
+
+	BlockArrayIterator& operator++()
+	{
+		check();
+		m_elementIdx = (m_elementIdx != kMaxU32) ? (m_elementIdx + 1) : kMaxU32;
+		return *this;
+	}
+
+	BlockArrayIterator operator++(int)
+	{
+		check();
+		BlockArrayIterator out = *this;
+		++(*this);
+		return out;
+	}
+
+	BlockArrayIterator operator+(U32 n) const
+	{
+		check();
+		BlockArrayIterator out = *this;
+		out.m_elementIdx = (out.m_elementIdx != kMaxU32) ? (out.m_elementIdx + n) : kMaxU32;
+		return out;
+	}
+
+	BlockArrayIterator& operator+=(U32 n)
+	{
+		check();
+		m_elementIdx = (m_elementIdx != kMaxU32) ? (m_elementIdx + n) : kMaxU32;
+		return *this;
+	}
+
+	Bool operator==(const BlockArrayIterator& b) const
+	{
+		ANKI_ASSERT(m_array == b.m_array);
+		ANKI_ASSERT(m_iteratorVer == b.m_iteratorVer);
+		return m_elementIdx == b.m_elementIdx;
+	}
+
+	Bool operator!=(const BlockArrayIterator& b) const
+	{
+		return !(*this == b);
+	}
+
+private:
+	TBlockArrayPtr m_array;
+	U32 m_elementIdx;
+#if ANKI_EXTRA_CHECKS
+	U32 m_iteratorVer; ///< See BlockArray::m_iteratorVer.
+#endif
+
+	void check() const
+	{
+		ANKI_ASSERT(m_array);
+	}
+};
+
+/// XXX
+/// @tparam T
+/// @tparam TMemoryPool
+/// @tparam TConfig
+template<typename T, typename TMemoryPool = SingletonMemoryPoolWrapper<DefaultMemoryPool>, typename TConfig = BlockArrayDefaultConfig<T>>
+class BlockArray
+{
+public:
+	// Typedefs
+	using Config = TConfig;
+	using Value = T;
+	using Iterator = BlockArrayIterator<T*, T&, BlockArray*>;
+	using ConstIterator = BlockArrayIterator<const T*, const T&, const BlockArray*>;
+	using Reference = Value&;
+	using ConstReference = const Value&;
+
+	static constexpr U32 kElementCountPerBlock = TConfig::getElementCountPerBlock();
+
+	BlockArray(const TMemoryPool& pool = TMemoryPool())
+		: m_blockStorages(pool)
+		, m_blockMetadatas(pool)
+	{
+	}
+
+	/// Copy.
+	BlockArray(const BlockArray& b)
+	{
+		*this = b;
+	}
+
+	/// Move.
+	BlockArray(BlockArray&& b)
+	{
+		*this = std::move(b);
+	}
+
+	/// Destroy.
+	~BlockArray()
+	{
+		destroy();
+	}
+
+	/// Copy.
+	BlockArray& operator=(const BlockArray& b);
+
+	/// Move operator.
+	BlockArray& operator=(BlockArray&& b)
+	{
+		destroy();
+		m_blockStorages = std::move(b.m_blockStorages);
+		m_blockMetadatas = std::move(b.m_blockMetadatas);
+		m_elementCount = b.m_elementCount;
+		b.m_elementCount = 0;
+		m_firstElement = b.m_firstElement;
+		b.m_firstElement = kMaxU32;
+		return *this;
+	}
+
+	ConstReference operator[](U32 idx) const
+	{
+		const U32 blockIdx = idx / kElementCountPerBlock;
+		const U32 localIdx = idx % kElementCountPerBlock;
+		ANKI_ASSERT(blockIdx < m_blockMetadatas.getSize());
+		ANKI_ASSERT(m_blockStorages[blockIdx] != nullptr);
+		ANKI_ASSERT(m_blockMetadatas[blockIdx].m_elementsInUseMask[localIdx].get() == true);
+		return *reinterpret_cast<Value*>(&m_blockStorages[blockIdx]->m_storage[localIdx * sizeof(Value)]);
+	}
+
+	Reference operator[](U32 idx)
+	{
+		const auto& constSelf = *this;
+		return const_cast<Reference>(constSelf[idx]);
+	}
+
+	/// Get begin.
+	Iterator getBegin()
+	{
+		return Iterator(this, m_firstElement
+#if ANKI_EXTRA_CHECKS
+						,
+						m_iteratorVer
+#endif
+		);
+	}
+
+	/// Get begin.
+	ConstIterator getBegin() const
+	{
+		return ConstIterator(this, m_firstElement
+#if ANKI_EXTRA_CHECKS
+							 ,
+							 m_iteratorVer
+#endif
+		);
+	}
+
+	/// Get end.
+	Iterator getEnd()
+	{
+		return Iterator(this, kMaxU32
+#if ANKI_EXTRA_CHECKS
+						,
+						m_iteratorVer
+#endif
+		);
+	}
+
+	/// Get end.
+	ConstIterator getEnd() const
+	{
+		return ConstIterator(this, kMaxU32
+#if ANKI_EXTRA_CHECKS
+							 ,
+							 m_iteratorVer
+#endif
+		);
+	}
+
+	/// Get begin.
+	Iterator begin()
+	{
+		return getBegin();
+	}
+
+	/// Get begin.
+	ConstIterator begin() const
+	{
+		return getBegin();
+	}
+
+	/// Get end.
+	Iterator end()
+	{
+		return getEnd();
+	}
+
+	/// Get end.
+	ConstIterator end() const
+	{
+		return getEnd();
+	}
+
+	U32 getSize() const
+	{
+		return m_elementCount;
+	}
+
+	Bool isEmpty() const
+	{
+		return m_elementCount == 0;
+	}
+
+	/// Destroy the array and free its elements.
+	void destroy();
+
+	/// Emplace somewhere in some block.
+	template<typename... TArgs>
+	Iterator emplace(TArgs&&... args);
+
+	/// Removes one element.
+	/// @param at Points to the position of the element to remove.
+	void erase(ConstIterator at);
+
+	TMemoryPool& getMemoryPool()
+	{
+		return m_blockStorages.getMemoryPool();
+	}
+
+private:
+	class alignas(alignof(T)) BlockStorage
+	{
+	public:
+		U8 m_storage[sizeof(T) * kElementCountPerBlock];
+	};
+
+	class BlockMetadata
+	{
+	public:
+		BitSet<kElementCountPerBlock, U64> m_elementsInUseMask{false};
+	};
+
+	DynamicArray<BlockStorage*, TMemoryPool> m_blockStorages;
+	DynamicArray<BlockMetadata, TMemoryPool> m_blockMetadatas;
+	U32 m_elementCount = 0;
+	U32 m_firstElement = kMaxU32;
+#if ANKI_EXTRA_CHECKS
+	U32 m_iteratorVer = 1;
+#endif
+};
+/// @}
+
+} // end namespace anki
+
+#include <AnKi/Util/BlockArray.inl.h>

+ 10 - 0
AnKi/Util/BlockArray.inl.h

@@ -0,0 +1,10 @@
+// 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/Util/BlockArray.h>
+
+namespace anki {
+
+} // end namespace anki

+ 3 - 0
AnKi/Util/Forward.h

@@ -39,6 +39,9 @@ class List;
 template<typename T, typename TMemoryPool, typename TConfig>
 class SparseArray;
 
+template<typename T, typename TMemoryPool, typename TConfig>
+class BlockArray;
+
 class CString;
 
 template<typename>

+ 57 - 18
Tests/Util/BitSet.cpp

@@ -83,6 +83,55 @@ static void fuzzyTest()
 	}
 }
 
+template<typename TChunkType>
+static void checkMsb()
+{
+	const U N = 256;
+	BitSet<N, TChunkType> a = {false};
+
+	ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), kMaxU32);
+
+	a.set(32);
+	ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 32);
+
+	a.set(33);
+	ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 33);
+
+	a.set(68);
+	ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 68);
+
+	a.unset(68);
+	ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 33);
+
+	a.unsetAll();
+	a.set(255);
+	ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 255);
+}
+
+template<typename TChunkType>
+static void checkLsb()
+{
+	constexpr U32 kCount = 256;
+	BitSet<kCount, TChunkType> a = {false};
+
+	ANKI_TEST_EXPECT_EQ(a.getLeastSignificantBit(), kMaxU32);
+
+	a.set(33);
+	ANKI_TEST_EXPECT_EQ(a.getLeastSignificantBit(), 33);
+
+	a.set(34);
+	ANKI_TEST_EXPECT_EQ(a.getLeastSignificantBit(), 33);
+
+	a.set(2);
+	ANKI_TEST_EXPECT_EQ(a.getLeastSignificantBit(), 2);
+
+	a.unset(2);
+	ANKI_TEST_EXPECT_EQ(a.getLeastSignificantBit(), 33);
+
+	a.setAll();
+	ANKI_TEST_EXPECT_EQ(a.getLeastSignificantBit(), 0);
+}
+
 ANKI_TEST(Util, BitSet)
 {
 	{
@@ -101,23 +150,13 @@ ANKI_TEST(Util, BitSet)
 #undef ANKI_BITSET_TEST
 	}
 
-	{
-		const U N = 256;
-		BitSet<N, U64> a = {false};
-
-		ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), kMaxU32);
-
-		a.set(32);
-		ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 32);
+	checkMsb<U8>();
+	checkMsb<U16>();
+	checkMsb<U32>();
+	checkMsb<U64>();
 
-		a.set(33);
-		ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 33);
-
-		a.set(68);
-		ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 68);
-
-		a.unsetAll();
-		a.set(255);
-		ANKI_TEST_EXPECT_EQ(a.getMostSignificantBit(), 255);
-	}
+	checkLsb<U8>();
+	checkLsb<U16>();
+	checkLsb<U32>();
+	checkLsb<U64>();
 }