Implement UploadPool to efficiently update UBOs

This commit is contained in:
Lynix
2020-03-26 21:13:06 +01:00
parent e53e15d1aa
commit 509c392e05
10 changed files with 302 additions and 50 deletions

View File

@@ -0,0 +1,61 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VULKANRENDERER_VULKANUPLOADPOOL_HPP
#define NAZARA_VULKANRENDERER_VULKANUPLOADPOOL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Buffer.hpp>
#include <Nazara/VulkanRenderer/Wrapper/DeviceMemory.hpp>
#include <optional>
#include <vector>
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanUploadPool
{
public:
struct AllocationData;
inline VulkanUploadPool(Vk::Device& device, UInt64 blockSize);
VulkanUploadPool(const VulkanUploadPool&) = delete;
VulkanUploadPool(VulkanUploadPool&&) noexcept = default;
~VulkanUploadPool() = default;
std::optional<AllocationData> Allocate(UInt64 size);
std::optional<AllocationData> Allocate(UInt64 size, UInt64 alignment);
void Reset();
struct AllocationData
{
VkBuffer buffer;
void* mappedPtr;
UInt64 offset;
UInt64 size;
};
VulkanUploadPool& operator=(const VulkanUploadPool&) = delete;
VulkanUploadPool& operator=(VulkanUploadPool&&) = delete;
private:
struct Block
{
Vk::DeviceMemory blockMemory;
Vk::Buffer buffer;
UInt64 freeOffset;
};
UInt64 m_blockSize;
Vk::Device& m_device;
std::vector<Block> m_blocks;
};
}
#include <Nazara/VulkanRenderer/VulkanUploadPool.inl>
#endif // NAZARA_VULKANRENDERER_VULKANUPLOADPOOL_HPP

View File

@@ -0,0 +1,17 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanUploadPool.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline VulkanUploadPool::VulkanUploadPool(Vk::Device& device, UInt64 blockSize) :
m_blockSize(blockSize),
m_device(device)
{
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@@ -21,7 +21,7 @@ namespace Nz
public:
Buffer() = default;
Buffer(const Buffer&) = delete;
Buffer(Buffer&&) = default;
Buffer(Buffer&&) noexcept = default;
~Buffer() = default;
bool BindBufferMemory(VkDeviceMemory memory, VkDeviceSize offset = 0);

View File

@@ -8,6 +8,7 @@
#define NAZARA_VULKANRENDERER_VKDEVICEMEMORY_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <Nazara/VulkanRenderer/Wrapper/DeviceObject.hpp>
namespace Nz
@@ -19,9 +20,9 @@ namespace Nz
friend DeviceObject;
public:
DeviceMemory();
DeviceMemory() = default;
DeviceMemory(const DeviceMemory&) = delete;
inline DeviceMemory(DeviceMemory&& memory);
DeviceMemory(DeviceMemory&& memory) noexcept = default;
~DeviceMemory() = default;
using DeviceObject::Create;
@@ -33,6 +34,7 @@ namespace Nz
inline void* GetMappedPointer();
inline bool Map(VkMemoryMapFlags flags = 0);
inline bool Map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags = 0);
inline void Unmap();
@@ -44,7 +46,7 @@ namespace Nz
static inline VkResult CreateHelper(Device& device, const VkMemoryAllocateInfo* allocInfo, const VkAllocationCallbacks* allocator, VkDeviceMemory* handle);
static inline void DestroyHelper(Device& device, VkDeviceMemory handle, const VkAllocationCallbacks* allocator);
void* m_mappedPtr;
MovablePtr<void> m_mappedPtr;
};
}
}

View File

@@ -12,18 +12,6 @@ namespace Nz
{
namespace Vk
{
inline DeviceMemory::DeviceMemory() :
m_mappedPtr(nullptr)
{
}
inline DeviceMemory::DeviceMemory(DeviceMemory&& memory) :
DeviceObject(std::move(memory))
{
m_mappedPtr = memory.m_mappedPtr;
memory.m_mappedPtr = nullptr;
}
inline bool DeviceMemory::Create(Device& device, VkDeviceSize size, UInt32 memoryType, const VkAllocationCallbacks* allocator)
{
VkMemoryAllocateInfo allocInfo =
@@ -87,15 +75,23 @@ namespace Nz
return m_mappedPtr;
}
inline bool DeviceMemory::Map(VkMemoryMapFlags flags)
{
return Map(0, VK_WHOLE_SIZE, flags);
}
inline bool DeviceMemory::Map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
{
m_lastErrorCode = m_device->vkMapMemory(*m_device, m_handle, offset, size, flags, &m_mappedPtr);
void* mappedPtr;
m_lastErrorCode = m_device->vkMapMemory(*m_device, m_handle, offset, size, flags, &mappedPtr);
if (m_lastErrorCode != VK_SUCCESS)
{
NazaraError("Failed to map device memory: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
m_mappedPtr = mappedPtr;
return true;
}