diff options
| author | 2023-05-27 17:09:17 +0300 | |
|---|---|---|
| committer | 2023-06-18 12:45:18 +0300 | |
| commit | 7b2f680468bbac206f96b26a1300939be90f5f1b (patch) | |
| tree | c8f506462c6d2b577ab0273e50c530fd7c71abbc /src/video_core/vulkan_common | |
| parent | renderer_vulkan: Use VMA for images (diff) | |
| download | yuzu-7b2f680468bbac206f96b26a1300939be90f5f1b.tar.gz yuzu-7b2f680468bbac206f96b26a1300939be90f5f1b.tar.xz yuzu-7b2f680468bbac206f96b26a1300939be90f5f1b.zip | |
renderer_vulkan: Use VMA for buffers
Diffstat (limited to 'src/video_core/vulkan_common')
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_memory_allocator.cpp | 107 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_memory_allocator.h | 12 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.cpp | 24 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.h | 91 |
5 files changed, 186 insertions, 49 deletions
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 631d5e378..541f0c1da 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -603,6 +603,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 603 | }; | 603 | }; |
| 604 | 604 | ||
| 605 | const VmaAllocatorCreateInfo allocator_info = { | 605 | const VmaAllocatorCreateInfo allocator_info = { |
| 606 | .flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, | ||
| 606 | .physicalDevice = physical, | 607 | .physicalDevice = physical, |
| 607 | .device = *logical, | 608 | .device = *logical, |
| 608 | .pVulkanFunctions = &functions, | 609 | .pVulkanFunctions = &functions, |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 7f860cccd..d2e1ef58e 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp | |||
| @@ -51,11 +51,59 @@ struct Range { | |||
| 51 | case MemoryUsage::Download: | 51 | case MemoryUsage::Download: |
| 52 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | | 52 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | |
| 53 | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; | 53 | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; |
| 54 | case MemoryUsage::Stream: | ||
| 55 | return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | | ||
| 56 | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||
| 54 | } | 57 | } |
| 55 | ASSERT_MSG(false, "Invalid memory usage={}", usage); | 58 | ASSERT_MSG(false, "Invalid memory usage={}", usage); |
| 56 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | 59 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; |
| 57 | } | 60 | } |
| 58 | 61 | ||
| 62 | [[nodiscard]] VkMemoryPropertyFlags MemoryUsageRequiredVmaFlags(MemoryUsage usage) { | ||
| 63 | switch (usage) { | ||
| 64 | case MemoryUsage::DeviceLocal: | ||
| 65 | return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; | ||
| 66 | case MemoryUsage::Upload: | ||
| 67 | case MemoryUsage::Stream: | ||
| 68 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; | ||
| 69 | case MemoryUsage::Download: | ||
| 70 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; | ||
| 71 | } | ||
| 72 | ASSERT_MSG(false, "Invalid memory usage={}", usage); | ||
| 73 | return {}; | ||
| 74 | } | ||
| 75 | |||
| 76 | [[nodiscard]] VkMemoryPropertyFlags MemoryUsagePreferedVmaFlags(MemoryUsage usage) { | ||
| 77 | return usage != MemoryUsage::DeviceLocal ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | ||
| 78 | : VkMemoryPropertyFlags{}; | ||
| 79 | } | ||
| 80 | |||
| 81 | [[nodiscard]] VmaAllocationCreateFlags MemoryUsageVmaFlags(MemoryUsage usage) { | ||
| 82 | switch (usage) { | ||
| 83 | case MemoryUsage::Upload: | ||
| 84 | case MemoryUsage::Stream: | ||
| 85 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; | ||
| 86 | case MemoryUsage::Download: | ||
| 87 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; | ||
| 88 | case MemoryUsage::DeviceLocal: | ||
| 89 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | | ||
| 90 | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT; | ||
| 91 | } | ||
| 92 | return {}; | ||
| 93 | } | ||
| 94 | |||
| 95 | [[nodiscard]] VmaMemoryUsage MemoryUsageVma(MemoryUsage usage) { | ||
| 96 | switch (usage) { | ||
| 97 | case MemoryUsage::DeviceLocal: | ||
| 98 | case MemoryUsage::Stream: | ||
| 99 | return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; | ||
| 100 | case MemoryUsage::Upload: | ||
| 101 | case MemoryUsage::Download: | ||
| 102 | return VMA_MEMORY_USAGE_AUTO_PREFER_HOST; | ||
| 103 | } | ||
| 104 | return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; | ||
| 105 | } | ||
| 106 | |||
| 59 | } // Anonymous namespace | 107 | } // Anonymous namespace |
| 60 | 108 | ||
| 61 | class MemoryAllocation { | 109 | class MemoryAllocation { |
| @@ -178,17 +226,18 @@ void MemoryCommit::Release() { | |||
| 178 | } | 226 | } |
| 179 | 227 | ||
| 180 | MemoryAllocator::MemoryAllocator(const Device& device_) | 228 | MemoryAllocator::MemoryAllocator(const Device& device_) |
| 181 | : device{device_}, properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, | 229 | : device{device_}, allocator{device.GetAllocator()}, |
| 230 | properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, | ||
| 182 | buffer_image_granularity{ | 231 | buffer_image_granularity{ |
| 183 | device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} | 232 | device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} |
| 184 | 233 | ||
| 185 | MemoryAllocator::~MemoryAllocator() = default; | 234 | MemoryAllocator::~MemoryAllocator() = default; |
| 186 | 235 | ||
| 187 | vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const { | 236 | vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const { |
| 188 | const VmaAllocationCreateInfo alloc_info = { | 237 | const VmaAllocationCreateInfo alloc_ci = { |
| 189 | .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT, | 238 | .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT, |
| 190 | .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, | 239 | .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, |
| 191 | .requiredFlags = 0, | 240 | .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, |
| 192 | .preferredFlags = 0, | 241 | .preferredFlags = 0, |
| 193 | .pool = VK_NULL_HANDLE, | 242 | .pool = VK_NULL_HANDLE, |
| 194 | .pUserData = nullptr, | 243 | .pUserData = nullptr, |
| @@ -196,12 +245,40 @@ vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const { | |||
| 196 | 245 | ||
| 197 | VkImage handle{}; | 246 | VkImage handle{}; |
| 198 | VmaAllocation allocation{}; | 247 | VmaAllocation allocation{}; |
| 199 | vk::Check( | 248 | |
| 200 | vmaCreateImage(device.GetAllocator(), &ci, &alloc_info, &handle, &allocation, nullptr)); | 249 | vk::Check(vmaCreateImage(allocator, &ci, &alloc_ci, &handle, &allocation, nullptr)); |
| 201 | return vk::Image(handle, *device.GetLogical(), device.GetAllocator(), allocation, | 250 | |
| 251 | return vk::Image(handle, *device.GetLogical(), allocator, allocation, | ||
| 202 | device.GetDispatchLoader()); | 252 | device.GetDispatchLoader()); |
| 203 | } | 253 | } |
| 204 | 254 | ||
| 255 | vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const { | ||
| 256 | const VmaAllocationCreateInfo alloc_ci = { | ||
| 257 | .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT | | ||
| 258 | MemoryUsageVmaFlags(usage), | ||
| 259 | .usage = MemoryUsageVma(usage), | ||
| 260 | .requiredFlags = MemoryUsageRequiredVmaFlags(usage), | ||
| 261 | .preferredFlags = MemoryUsagePreferedVmaFlags(usage), | ||
| 262 | .pool = VK_NULL_HANDLE, | ||
| 263 | .pUserData = nullptr, | ||
| 264 | }; | ||
| 265 | |||
| 266 | VkBuffer handle{}; | ||
| 267 | VmaAllocationInfo alloc_info{}; | ||
| 268 | VmaAllocation allocation{}; | ||
| 269 | VkMemoryPropertyFlags property_flags{}; | ||
| 270 | |||
| 271 | vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info)); | ||
| 272 | vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags); | ||
| 273 | |||
| 274 | u8* data = reinterpret_cast<u8*>(alloc_info.pMappedData); | ||
| 275 | const std::span<u8> mapped_data = data ? std::span<u8>{data, ci.size} : std::span<u8>{}; | ||
| 276 | const bool is_coherent = property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||
| 277 | |||
| 278 | return vk::Buffer(handle, *device.GetLogical(), allocator, allocation, mapped_data, is_coherent, | ||
| 279 | device.GetDispatchLoader()); | ||
| 280 | } | ||
| 281 | |||
| 205 | MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { | 282 | MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { |
| 206 | // Find the fastest memory flags we can afford with the current requirements | 283 | // Find the fastest memory flags we can afford with the current requirements |
| 207 | const u32 type_mask = requirements.memoryTypeBits; | 284 | const u32 type_mask = requirements.memoryTypeBits; |
| @@ -221,12 +298,6 @@ MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, M | |||
| 221 | return TryCommit(requirements, flags).value(); | 298 | return TryCommit(requirements, flags).value(); |
| 222 | } | 299 | } |
| 223 | 300 | ||
| 224 | MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, MemoryUsage usage) { | ||
| 225 | auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), usage); | ||
| 226 | buffer.BindMemory(commit.Memory(), commit.Offset()); | ||
| 227 | return commit; | ||
| 228 | } | ||
| 229 | |||
| 230 | bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { | 301 | bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { |
| 231 | const u32 type = FindType(flags, type_mask).value(); | 302 | const u32 type = FindType(flags, type_mask).value(); |
| 232 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ | 303 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ |
| @@ -302,16 +373,4 @@ std::optional<u32> MemoryAllocator::FindType(VkMemoryPropertyFlags flags, u32 ty | |||
| 302 | return std::nullopt; | 373 | return std::nullopt; |
| 303 | } | 374 | } |
| 304 | 375 | ||
| 305 | bool IsHostVisible(MemoryUsage usage) noexcept { | ||
| 306 | switch (usage) { | ||
| 307 | case MemoryUsage::DeviceLocal: | ||
| 308 | return false; | ||
| 309 | case MemoryUsage::Upload: | ||
| 310 | case MemoryUsage::Download: | ||
| 311 | return true; | ||
| 312 | } | ||
| 313 | ASSERT_MSG(false, "Invalid memory usage={}", usage); | ||
| 314 | return false; | ||
| 315 | } | ||
| 316 | |||
| 317 | } // namespace Vulkan | 376 | } // namespace Vulkan |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h index f9ee53cfb..f449bc8d0 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.h +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 10 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 11 | 11 | ||
| 12 | VK_DEFINE_HANDLE(VmaAllocator) | ||
| 13 | |||
| 12 | namespace Vulkan { | 14 | namespace Vulkan { |
| 13 | 15 | ||
| 14 | class Device; | 16 | class Device; |
| @@ -17,9 +19,11 @@ class MemoryAllocation; | |||
| 17 | 19 | ||
| 18 | /// Hints and requirements for the backing memory type of a commit | 20 | /// Hints and requirements for the backing memory type of a commit |
| 19 | enum class MemoryUsage { | 21 | enum class MemoryUsage { |
| 20 | DeviceLocal, ///< Hints device local usages, fastest memory type to read and write from the GPU | 22 | DeviceLocal, ///< Requests device local host visible buffer, falling back to device local |
| 23 | ///< memory. | ||
| 21 | Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads | 24 | Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads |
| 22 | Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks | 25 | Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks |
| 26 | Stream, ///< Requests device local host visible buffer, falling back host memory. | ||
| 23 | }; | 27 | }; |
| 24 | 28 | ||
| 25 | /// Ownership handle of a memory commitment. | 29 | /// Ownership handle of a memory commitment. |
| @@ -82,6 +86,8 @@ public: | |||
| 82 | 86 | ||
| 83 | vk::Image CreateImage(const VkImageCreateInfo& ci) const; | 87 | vk::Image CreateImage(const VkImageCreateInfo& ci) const; |
| 84 | 88 | ||
| 89 | vk::Buffer CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const; | ||
| 90 | |||
| 85 | /** | 91 | /** |
| 86 | * Commits a memory with the specified requirements. | 92 | * Commits a memory with the specified requirements. |
| 87 | * | 93 | * |
| @@ -113,13 +119,11 @@ private: | |||
| 113 | std::optional<u32> FindType(VkMemoryPropertyFlags flags, u32 type_mask) const; | 119 | std::optional<u32> FindType(VkMemoryPropertyFlags flags, u32 type_mask) const; |
| 114 | 120 | ||
| 115 | const Device& device; ///< Device handle. | 121 | const Device& device; ///< Device handle. |
| 122 | VmaAllocator allocator; ///< Vma allocator. | ||
| 116 | const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties. | 123 | const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties. |
| 117 | std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. | 124 | std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. |
| 118 | VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers | 125 | VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers |
| 119 | // and optimal images | 126 | // and optimal images |
| 120 | }; | 127 | }; |
| 121 | 128 | ||
| 122 | /// Returns true when a memory usage is guaranteed to be host visible. | ||
| 123 | bool IsHostVisible(MemoryUsage usage) noexcept; | ||
| 124 | |||
| 125 | } // namespace Vulkan | 129 | } // namespace Vulkan |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 5d088dc58..c01a9478e 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -561,14 +561,28 @@ void Image::Release() const noexcept { | |||
| 561 | } | 561 | } |
| 562 | } | 562 | } |
| 563 | 563 | ||
| 564 | void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const { | 564 | void Buffer::Flush() const { |
| 565 | Check(dld->vkBindBufferMemory(owner, handle, memory, offset)); | 565 | if (!is_coherent) { |
| 566 | vmaFlushAllocation(allocator, allocation, 0, VK_WHOLE_SIZE); | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | void Buffer::Invalidate() const { | ||
| 571 | if (!is_coherent) { | ||
| 572 | vmaInvalidateAllocation(allocator, allocation, 0, VK_WHOLE_SIZE); | ||
| 573 | } | ||
| 566 | } | 574 | } |
| 567 | 575 | ||
| 568 | void Buffer::SetObjectNameEXT(const char* name) const { | 576 | void Buffer::SetObjectNameEXT(const char* name) const { |
| 569 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER, name); | 577 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER, name); |
| 570 | } | 578 | } |
| 571 | 579 | ||
| 580 | void Buffer::Release() const noexcept { | ||
| 581 | if (handle) { | ||
| 582 | vmaDestroyBuffer(allocator, handle, allocation); | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 572 | void BufferView::SetObjectNameEXT(const char* name) const { | 586 | void BufferView::SetObjectNameEXT(const char* name) const { |
| 573 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER_VIEW, name); | 587 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER_VIEW, name); |
| 574 | } | 588 | } |
| @@ -707,12 +721,6 @@ Queue Device::GetQueue(u32 family_index) const noexcept { | |||
| 707 | return Queue(queue, *dld); | 721 | return Queue(queue, *dld); |
| 708 | } | 722 | } |
| 709 | 723 | ||
| 710 | Buffer Device::CreateBuffer(const VkBufferCreateInfo& ci) const { | ||
| 711 | VkBuffer object; | ||
| 712 | Check(dld->vkCreateBuffer(handle, &ci, nullptr, &object)); | ||
| 713 | return Buffer(object, handle, *dld); | ||
| 714 | } | ||
| 715 | |||
| 716 | BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const { | 724 | BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const { |
| 717 | VkBufferView object; | 725 | VkBufferView object; |
| 718 | Check(dld->vkCreateBufferView(handle, &ci, nullptr, &object)); | 726 | Check(dld->vkCreateBufferView(handle, &ci, nullptr, &object)); |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 8ec708774..44fce47a5 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -673,6 +673,84 @@ private: | |||
| 673 | const DeviceDispatch* dld = nullptr; | 673 | const DeviceDispatch* dld = nullptr; |
| 674 | }; | 674 | }; |
| 675 | 675 | ||
| 676 | class Buffer { | ||
| 677 | public: | ||
| 678 | explicit Buffer(VkBuffer handle_, VkDevice owner_, VmaAllocator allocator_, | ||
| 679 | VmaAllocation allocation_, std::span<u8> mapped_, bool is_coherent_, | ||
| 680 | const DeviceDispatch& dld_) noexcept | ||
| 681 | : handle{handle_}, owner{owner_}, allocator{allocator_}, | ||
| 682 | allocation{allocation_}, mapped{mapped_}, is_coherent{is_coherent_}, dld{&dld_} {} | ||
| 683 | Buffer() = default; | ||
| 684 | |||
| 685 | Buffer(const Buffer&) = delete; | ||
| 686 | Buffer& operator=(const Buffer&) = delete; | ||
| 687 | |||
| 688 | Buffer(Buffer&& rhs) noexcept | ||
| 689 | : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, allocator{rhs.allocator}, | ||
| 690 | allocation{rhs.allocation}, mapped{rhs.mapped}, | ||
| 691 | is_coherent{rhs.is_coherent}, dld{rhs.dld} {} | ||
| 692 | |||
| 693 | Buffer& operator=(Buffer&& rhs) noexcept { | ||
| 694 | Release(); | ||
| 695 | handle = std::exchange(rhs.handle, nullptr); | ||
| 696 | owner = rhs.owner; | ||
| 697 | allocator = rhs.allocator; | ||
| 698 | allocation = rhs.allocation; | ||
| 699 | mapped = rhs.mapped; | ||
| 700 | is_coherent = rhs.is_coherent; | ||
| 701 | dld = rhs.dld; | ||
| 702 | return *this; | ||
| 703 | } | ||
| 704 | |||
| 705 | ~Buffer() noexcept { | ||
| 706 | Release(); | ||
| 707 | } | ||
| 708 | |||
| 709 | VkBuffer operator*() const noexcept { | ||
| 710 | return handle; | ||
| 711 | } | ||
| 712 | |||
| 713 | void reset() noexcept { | ||
| 714 | Release(); | ||
| 715 | handle = nullptr; | ||
| 716 | } | ||
| 717 | |||
| 718 | explicit operator bool() const noexcept { | ||
| 719 | return handle != nullptr; | ||
| 720 | } | ||
| 721 | |||
| 722 | /// Returns the host mapped memory, an empty span otherwise. | ||
| 723 | std::span<u8> Mapped() noexcept { | ||
| 724 | return mapped; | ||
| 725 | } | ||
| 726 | |||
| 727 | std::span<const u8> Mapped() const noexcept { | ||
| 728 | return mapped; | ||
| 729 | } | ||
| 730 | |||
| 731 | /// Returns true if the buffer is mapped to the host. | ||
| 732 | bool IsHostVisible() const noexcept { | ||
| 733 | return !mapped.empty(); | ||
| 734 | } | ||
| 735 | |||
| 736 | void Flush() const; | ||
| 737 | |||
| 738 | void Invalidate() const; | ||
| 739 | |||
| 740 | void SetObjectNameEXT(const char* name) const; | ||
| 741 | |||
| 742 | private: | ||
| 743 | void Release() const noexcept; | ||
| 744 | |||
| 745 | VkBuffer handle = nullptr; | ||
| 746 | VkDevice owner = nullptr; | ||
| 747 | VmaAllocator allocator = nullptr; | ||
| 748 | VmaAllocation allocation = nullptr; | ||
| 749 | std::span<u8> mapped = {}; | ||
| 750 | bool is_coherent = false; | ||
| 751 | const DeviceDispatch* dld = nullptr; | ||
| 752 | }; | ||
| 753 | |||
| 676 | class Queue { | 754 | class Queue { |
| 677 | public: | 755 | public: |
| 678 | /// Construct an empty queue handle. | 756 | /// Construct an empty queue handle. |
| @@ -696,17 +774,6 @@ private: | |||
| 696 | const DeviceDispatch* dld = nullptr; | 774 | const DeviceDispatch* dld = nullptr; |
| 697 | }; | 775 | }; |
| 698 | 776 | ||
| 699 | class Buffer : public Handle<VkBuffer, VkDevice, DeviceDispatch> { | ||
| 700 | using Handle<VkBuffer, VkDevice, DeviceDispatch>::Handle; | ||
| 701 | |||
| 702 | public: | ||
| 703 | /// Attaches a memory allocation. | ||
| 704 | void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const; | ||
| 705 | |||
| 706 | /// Set object name. | ||
| 707 | void SetObjectNameEXT(const char* name) const; | ||
| 708 | }; | ||
| 709 | |||
| 710 | class BufferView : public Handle<VkBufferView, VkDevice, DeviceDispatch> { | 777 | class BufferView : public Handle<VkBufferView, VkDevice, DeviceDispatch> { |
| 711 | using Handle<VkBufferView, VkDevice, DeviceDispatch>::Handle; | 778 | using Handle<VkBufferView, VkDevice, DeviceDispatch>::Handle; |
| 712 | 779 | ||
| @@ -886,8 +953,6 @@ public: | |||
| 886 | 953 | ||
| 887 | Queue GetQueue(u32 family_index) const noexcept; | 954 | Queue GetQueue(u32 family_index) const noexcept; |
| 888 | 955 | ||
| 889 | Buffer CreateBuffer(const VkBufferCreateInfo& ci) const; | ||
| 890 | |||
| 891 | BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const; | 956 | BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const; |
| 892 | 957 | ||
| 893 | ImageView CreateImageView(const VkImageViewCreateInfo& ci) const; | 958 | ImageView CreateImageView(const VkImageViewCreateInfo& ci) const; |