renderer_vulkan: Use VMA for images

This commit is contained in:
GPUCode 2023-05-24 22:39:58 +03:00
parent c60eed36b7
commit 48e39756f1
16 changed files with 119 additions and 91 deletions

View file

@ -210,6 +210,11 @@ public:
return dld;
}
/// Returns the VMA allocator.
VmaAllocator GetAllocator() const {
return allocator;
}
/// Returns the logical device.
const vk::Device& GetLogical() const {
return logical;

View file

@ -15,6 +15,10 @@
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include <vk_mem_alloc.h>
namespace Vulkan {
namespace {
struct Range {
@ -180,6 +184,24 @@ MemoryAllocator::MemoryAllocator(const Device& device_)
MemoryAllocator::~MemoryAllocator() = default;
vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const {
const VmaAllocationCreateInfo alloc_info = {
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
.requiredFlags = 0,
.preferredFlags = 0,
.pool = VK_NULL_HANDLE,
.pUserData = nullptr,
};
VkImage handle{};
VmaAllocation allocation{};
vk::Check(
vmaCreateImage(device.GetAllocator(), &ci, &alloc_info, &handle, &allocation, nullptr));
return vk::Image(handle, *device.GetLogical(), device.GetAllocator(), allocation,
device.GetDispatchLoader());
}
MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) {
// Find the fastest memory flags we can afford with the current requirements
const u32 type_mask = requirements.memoryTypeBits;
@ -205,14 +227,6 @@ MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, MemoryUsage usage
return commit;
}
MemoryCommit MemoryAllocator::Commit(const vk::Image& image, MemoryUsage usage) {
VkMemoryRequirements requirements = device.GetLogical().GetImageMemoryRequirements(*image);
requirements.size = Common::AlignUp(requirements.size, buffer_image_granularity);
auto commit = Commit(requirements, usage);
image.BindMemory(commit.Memory(), commit.Offset());
return commit;
}
bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) {
const u32 type = FindType(flags, type_mask).value();
vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({

View file

@ -80,6 +80,8 @@ public:
MemoryAllocator& operator=(const MemoryAllocator&) = delete;
MemoryAllocator(const MemoryAllocator&) = delete;
vk::Image CreateImage(const VkImageCreateInfo& ci) const;
/**
* Commits a memory with the specified requirements.
*
@ -93,9 +95,6 @@ public:
/// Commits memory required by the buffer and binds it.
MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage);
/// Commits memory required by the image and binds it.
MemoryCommit Commit(const vk::Image& image, MemoryUsage usage);
private:
/// Tries to allocate a chunk of memory.
bool TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size);

View file

@ -12,6 +12,10 @@
#include "video_core/vulkan_common/vulkan_wrapper.h"
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include <vk_mem_alloc.h>
namespace Vulkan::vk {
namespace {
@ -547,6 +551,16 @@ DebugUtilsMessenger Instance::CreateDebugUtilsMessenger(
return DebugUtilsMessenger(object, handle, *dld);
}
void Image::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name);
}
void Image::Release() const noexcept {
if (handle) {
vmaDestroyImage(allocator, handle, allocation);
}
}
void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const {
Check(dld->vkBindBufferMemory(owner, handle, memory, offset));
}
@ -559,14 +573,6 @@ void BufferView::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER_VIEW, name);
}
void Image::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const {
Check(dld->vkBindImageMemory(owner, handle, memory, offset));
}
void Image::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name);
}
void ImageView::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE_VIEW, name);
}
@ -713,12 +719,6 @@ BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const {
return BufferView(object, handle, *dld);
}
Image Device::CreateImage(const VkImageCreateInfo& ci) const {
VkImage object;
Check(dld->vkCreateImage(handle, &ci, nullptr, &object));
return Image(object, handle, *dld);
}
ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const {
VkImageView object;
Check(dld->vkCreateImageView(handle, &ci, nullptr, &object));

View file

@ -32,6 +32,9 @@
#pragma warning(disable : 26812) // Disable prefer enum class over enum
#endif
VK_DEFINE_HANDLE(VmaAllocator)
VK_DEFINE_HANDLE(VmaAllocation)
namespace Vulkan::vk {
/**
@ -616,6 +619,60 @@ public:
}
};
class Image {
public:
explicit Image(VkImage handle_, VkDevice owner_, VmaAllocator allocator_,
VmaAllocation allocation_, const DeviceDispatch& dld_) noexcept
: handle{handle_}, owner{owner_}, allocator{allocator_},
allocation{allocation_}, dld{&dld_} {}
Image() = default;
Image(const Image&) = delete;
Image& operator=(const Image&) = delete;
Image(Image&& rhs) noexcept
: handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, allocator{rhs.allocator},
allocation{rhs.allocation}, dld{rhs.dld} {}
Image& operator=(Image&& rhs) noexcept {
Release();
handle = std::exchange(rhs.handle, nullptr);
owner = rhs.owner;
allocator = rhs.allocator;
allocation = rhs.allocation;
dld = rhs.dld;
return *this;
}
~Image() noexcept {
Release();
}
VkImage operator*() const noexcept {
return handle;
}
void reset() noexcept {
Release();
handle = nullptr;
}
explicit operator bool() const noexcept {
return handle != nullptr;
}
void SetObjectNameEXT(const char* name) const;
private:
void Release() const noexcept;
VkImage handle = nullptr;
VkDevice owner = nullptr;
VmaAllocator allocator = nullptr;
VmaAllocation allocation = nullptr;
const DeviceDispatch* dld = nullptr;
};
class Queue {
public:
/// Construct an empty queue handle.
@ -658,17 +715,6 @@ public:
void SetObjectNameEXT(const char* name) const;
};
class Image : public Handle<VkImage, VkDevice, DeviceDispatch> {
using Handle<VkImage, VkDevice, DeviceDispatch>::Handle;
public:
/// Attaches a memory allocation.
void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const;
/// Set object name.
void SetObjectNameEXT(const char* name) const;
};
class ImageView : public Handle<VkImageView, VkDevice, DeviceDispatch> {
using Handle<VkImageView, VkDevice, DeviceDispatch>::Handle;
@ -844,8 +890,6 @@ public:
BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const;
Image CreateImage(const VkImageCreateInfo& ci) const;
ImageView CreateImageView(const VkImageViewCreateInfo& ci) const;
Semaphore CreateSemaphore() const;