Browse Source

Vulkan: Adding the replacement of GpuMemoryAllocator

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
c7f21e9668
2 changed files with 189 additions and 0 deletions
  1. 129 0
      src/anki/gr/vulkan/GpuMemoryManager.cpp
  2. 60 0
      src/anki/gr/vulkan/GpuMemoryManager.h

+ 129 - 0
src/anki/gr/vulkan/GpuMemoryManager.cpp

@@ -0,0 +1,129 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/gr/vulkan/GpuMemoryManager.h>
+#include <anki/util/List.h>
+
+namespace anki
+{
+
+const U CLASS_COUNT = 7;
+
+class ClassInf
+{
+public:
+	PtrSize m_slotSize;
+	PtrSize m_chunkSize;
+};
+
+static unsigned long long int operator"" _B(unsigned long long int x)
+{
+	return x;
+}
+
+static unsigned long long int operator"" _KB(unsigned long long int x)
+{
+	return x * 1024;
+}
+
+static unsigned long long int operator"" _MB(unsigned long long int x)
+{
+	return x * 1024 * 1024;
+}
+
+static const Array<ClassInf, CLASS_COUNT> CLASSES = {{{256_B, 16_KB},
+	{4_KB, 256_KB},
+	{128_KB, 8_MB},
+	{1_MB, 64_MB},
+	{16_MB, 128_MB},
+	{64_MB, 256_MB},
+	{128_MB, 256_MB}}};
+
+class GpuMemoryManager::Memory : public ClassAllocatorMemory, public IntrusiveListEnabled<GpuMemoryManager::Memory>
+{
+public:
+	VkDeviceMemory m_handle = VK_NULL_HANDLE;
+	U8 m_classIdx = MAX_U8;
+};
+
+class GpuMemoryManager::Interface : public ClassAllocatorInterface
+{
+public:
+	uint32_t m_memTypeIdx = MAX_U32;
+	MemoryTypeCommon* m_memTypeCommon = nullptr;
+	GrAllocator<U8> m_alloc;
+	VkDevice m_dev = VK_NULL_HANDLE;
+
+	Interface() = default;
+
+	Error allocate(U classIdx, ClassAllocatorMemory*& mem);
+
+	void free(ClassAllocatorMemory* mem);
+
+	U getClassCount() const
+	{
+		return CLASS_COUNT;
+	}
+
+	void getClassInfo(U classIdx, PtrSize& slotSize, PtrSize& chunkSize) const
+	{
+		slotSize = CLASSES[classIdx].m_slotSize;
+		chunkSize = CLASSES[classIdx].m_chunkSize;
+	}
+};
+
+class GpuMemoryManager::MemoryTypeCommon
+{
+public:
+	Array<IntrusiveList<Memory>, CLASS_COUNT> m_vacantMemory;
+	Mutex m_mtx;
+};
+
+Error GpuMemoryManager::Interface::allocate(U classIdx, ClassAllocatorMemory*& mem)
+{
+	const PtrSize chunkSize = CLASSES[classIdx].m_chunkSize;
+
+	LockGuard<Mutex> lock(m_memTypeCommon->m_mtx);
+
+	Memory* pmem = nullptr;
+
+	if(!m_memTypeCommon->m_vacantMemory[classIdx].isEmpty())
+	{
+		pmem = &m_memTypeCommon->m_vacantMemory[classIdx].getFront();
+		m_memTypeCommon->m_vacantMemory[classIdx].popFront();
+	}
+	else
+	{
+		pmem = m_alloc.newInstance<Memory>();
+
+		VkMemoryAllocateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+		ci.allocationSize = chunkSize;
+		ci.memoryTypeIndex = m_memTypeIdx;
+		ANKI_VK_CHECKF(vkAllocateMemory(m_dev, &ci, nullptr, &pmem->m_handle));
+
+		pmem->m_classIdx = classIdx;
+	}
+
+	ANKI_ASSERT(pmem);
+	mem = pmem;
+	return ErrorCode::NONE;
+}
+
+void GpuMemoryManager::Interface::free(ClassAllocatorMemory* mem)
+{
+	ANKI_ASSERT(mem);
+	Memory* pmem = static_cast<Memory*>(mem);
+	ANKI_ASSERT(pmem->m_handle);
+
+	LockGuard<Mutex> lock(m_memTypeCommon->m_mtx);
+	m_memTypeCommon->m_vacantMemory[pmem->m_classIdx].pushBack(pmem);
+}
+
+void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, GrAllocator<U8> alloc)
+{
+}
+
+} // end namespace anki

+ 60 - 0
src/anki/gr/vulkan/GpuMemoryManager.h

@@ -0,0 +1,60 @@
+// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/gr/common/ClassAllocator.h>
+#include <anki/gr/vulkan/Common.h>
+
+namespace anki
+{
+
+/// @addtorgoup vulkan
+/// @{
+
+/// The handle that is returned from GpuMemoryManager's allocations.
+class GpuMemoryHandle : public ClassAllocatorHandle
+{
+public:
+	VkDeviceMemory m_memory = VK_NULL_HANDLE;
+};
+
+/// Dynamic GPU memory allocator for all types.
+class GpuMemoryManager : public NonCopyable
+{
+public:
+	GpuMemoryManager() = default;
+
+	~GpuMemoryManager();
+
+	void init(VkPhysicalDevice pdev, VkDevice dev, GrAllocator<U8> alloc);
+
+	void destroy();
+
+	/// Allocate memory.
+	void allocateMemory(U memTypeIdx, PtrSize size, U alignment, Bool linearResource, GpuMemoryHandle& handle);
+
+	/// Free memory.
+	void freeMemory(GpuMemoryHandle& handle);
+
+	/// Map memory.
+	ANKI_USE_RESULT void* getMappedAddress(GpuMemoryHandle& handle);
+
+	/// Find a suitable memory type.
+	U findMemoryType(U resourceMemTypeBits, VkMemoryPropertyFlags preferFlags, VkMemoryPropertyFlags avoidFlags) const;
+
+private:
+	class Memory;
+	class MemoryTypeCommon;
+	class Interface;
+
+	GrAllocator<U8> m_alloc;
+	VkDevice m_dev;
+	DynamicArray<MemoryTypeCommon> m_memType;
+	VkPhysicalDeviceMemoryProperties m_memoryProperties;
+};
+/// @}
+
+} // end namespace anki