summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp42
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp6
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp24
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.h24
9 files changed, 86 insertions, 45 deletions
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index f06af06c8..3e3b895e0 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -657,7 +657,7 @@ void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuff
657 }; 657 };
658 658
659 buffer = device.GetLogical().CreateBuffer(ci); 659 buffer = device.GetLogical().CreateBuffer(ci);
660 buffer_commit = memory_allocator.Commit(buffer, true); 660 buffer_commit = memory_allocator.Commit(buffer, MemoryUsage::Upload);
661} 661}
662 662
663void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { 663void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
@@ -688,7 +688,7 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
688 .pQueueFamilyIndices = nullptr, 688 .pQueueFamilyIndices = nullptr,
689 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 689 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
690 }); 690 });
691 raw_buffer_commits[i] = memory_allocator.Commit(raw_images[i], false); 691 raw_buffer_commits[i] = memory_allocator.Commit(raw_images[i], MemoryUsage::DeviceLocal);
692 raw_image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ 692 raw_image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{
693 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 693 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
694 .pNext = nullptr, 694 .pNext = nullptr,
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 94d3a9134..d8ad40a0f 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -50,13 +50,13 @@ Buffer::Buffer(const Device& device_, MemoryAllocator& memory_allocator, VKSched
50 .queueFamilyIndexCount = 0, 50 .queueFamilyIndexCount = 0,
51 .pQueueFamilyIndices = nullptr, 51 .pQueueFamilyIndices = nullptr,
52 }); 52 });
53 commit = memory_allocator.Commit(buffer, false); 53 commit = memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
54} 54}
55 55
56Buffer::~Buffer() = default; 56Buffer::~Buffer() = default;
57 57
58void Buffer::Upload(std::size_t offset, std::size_t data_size, const u8* data) { 58void Buffer::Upload(std::size_t offset, std::size_t data_size, const u8* data) {
59 const auto& staging = staging_pool.Request(data_size, true); 59 const auto& staging = staging_pool.Request(data_size, MemoryUsage::Upload);
60 std::memcpy(staging.mapped_span.data(), data, data_size); 60 std::memcpy(staging.mapped_span.data(), data, data_size);
61 61
62 scheduler.RequestOutsideRenderPassOperationContext(); 62 scheduler.RequestOutsideRenderPassOperationContext();
@@ -98,7 +98,7 @@ void Buffer::Upload(std::size_t offset, std::size_t data_size, const u8* data) {
98} 98}
99 99
100void Buffer::Download(std::size_t offset, std::size_t data_size, u8* data) { 100void Buffer::Download(std::size_t offset, std::size_t data_size, u8* data) {
101 auto staging = staging_pool.Request(data_size, true); 101 auto staging = staging_pool.Request(data_size, MemoryUsage::Download);
102 scheduler.RequestOutsideRenderPassOperationContext(); 102 scheduler.RequestOutsideRenderPassOperationContext();
103 103
104 const VkBuffer handle = Handle(); 104 const VkBuffer handle = Handle();
@@ -179,7 +179,7 @@ std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t s
179 179
180VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) { 180VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) {
181 size = std::max(size, std::size_t(4)); 181 size = std::max(size, std::size_t(4));
182 const auto& empty = staging_pool.Request(size, false); 182 const auto& empty = staging_pool.Request(size, MemoryUsage::DeviceLocal);
183 scheduler.RequestOutsideRenderPassOperationContext(); 183 scheduler.RequestOutsideRenderPassOperationContext();
184 scheduler.Record([size, buffer = empty.buffer](vk::CommandBuffer cmdbuf) { 184 scheduler.Record([size, buffer = empty.buffer](vk::CommandBuffer cmdbuf) {
185 cmdbuf.FillBuffer(buffer, 0, size, 0); 185 cmdbuf.FillBuffer(buffer, 0, size, 0);
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index d38087f41..5eb6a54be 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -177,7 +177,7 @@ QuadArrayPass::~QuadArrayPass() = default;
177std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) { 177std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) {
178 const u32 num_triangle_vertices = (num_vertices / 4) * 6; 178 const u32 num_triangle_vertices = (num_vertices / 4) * 6;
179 const std::size_t staging_size = num_triangle_vertices * sizeof(u32); 179 const std::size_t staging_size = num_triangle_vertices * sizeof(u32);
180 const auto staging_ref = staging_buffer_pool.Request(staging_size, false); 180 const auto staging_ref = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
181 181
182 update_descriptor_queue.Acquire(); 182 update_descriptor_queue.Acquire();
183 update_descriptor_queue.AddBuffer(staging_ref.buffer, 0, staging_size); 183 update_descriptor_queue.AddBuffer(staging_ref.buffer, 0, staging_size);
@@ -224,7 +224,7 @@ Uint8Pass::~Uint8Pass() = default;
224std::pair<VkBuffer, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer, 224std::pair<VkBuffer, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
225 u64 src_offset) { 225 u64 src_offset) {
226 const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16)); 226 const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
227 const auto staging_ref = staging_buffer_pool.Request(staging_size, false); 227 const auto staging_ref = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
228 228
229 update_descriptor_queue.Acquire(); 229 update_descriptor_queue.Acquire();
230 update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices); 230 update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
@@ -286,7 +286,7 @@ std::pair<VkBuffer, u64> QuadIndexedPass::Assemble(
286 const u32 num_tri_vertices = (num_vertices / 4) * 6; 286 const u32 num_tri_vertices = (num_vertices / 4) * 6;
287 287
288 const std::size_t staging_size = num_tri_vertices * sizeof(u32); 288 const std::size_t staging_size = num_tri_vertices * sizeof(u32);
289 const auto staging_ref = staging_buffer_pool.Request(staging_size, false); 289 const auto staging_ref = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
290 290
291 update_descriptor_queue.Acquire(); 291 update_descriptor_queue.Acquire();
292 update_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size); 292 update_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index f38ead9c2..f0a111829 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -1445,7 +1445,7 @@ VkBuffer RasterizerVulkan::DefaultBuffer() {
1445 .queueFamilyIndexCount = 0, 1445 .queueFamilyIndexCount = 0,
1446 .pQueueFamilyIndices = nullptr, 1446 .pQueueFamilyIndices = nullptr,
1447 }); 1447 });
1448 default_buffer_commit = memory_allocator.Commit(default_buffer, false); 1448 default_buffer_commit = memory_allocator.Commit(default_buffer, MemoryUsage::DeviceLocal);
1449 1449
1450 scheduler.RequestOutsideRenderPassOperationContext(); 1450 scheduler.RequestOutsideRenderPassOperationContext();
1451 scheduler.Record([buffer = *default_buffer](vk::CommandBuffer cmdbuf) { 1451 scheduler.Record([buffer = *default_buffer](vk::CommandBuffer cmdbuf) {
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 44d332ed2..97fd41cc1 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -8,6 +8,7 @@
8 8
9#include <fmt/format.h> 9#include <fmt/format.h>
10 10
11#include "common/assert.h"
11#include "common/bit_util.h" 12#include "common/bit_util.h"
12#include "common/common_types.h" 13#include "common/common_types.h"
13#include "video_core/renderer_vulkan/vk_scheduler.h" 14#include "video_core/renderer_vulkan/vk_scheduler.h"
@@ -23,23 +24,24 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
23 24
24StagingBufferPool::~StagingBufferPool() = default; 25StagingBufferPool::~StagingBufferPool() = default;
25 26
26StagingBufferRef StagingBufferPool::Request(size_t size, bool host_visible) { 27StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage) {
27 if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, host_visible)) { 28 if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) {
28 return *ref; 29 return *ref;
29 } 30 }
30 return CreateStagingBuffer(size, host_visible); 31 return CreateStagingBuffer(size, usage);
31} 32}
32 33
33void StagingBufferPool::TickFrame() { 34void StagingBufferPool::TickFrame() {
34 current_delete_level = (current_delete_level + 1) % NUM_LEVELS; 35 current_delete_level = (current_delete_level + 1) % NUM_LEVELS;
35 36
36 ReleaseCache(true); 37 ReleaseCache(MemoryUsage::DeviceLocal);
37 ReleaseCache(false); 38 ReleaseCache(MemoryUsage::Upload);
39 ReleaseCache(MemoryUsage::Download);
38} 40}
39 41
40std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, 42std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
41 bool host_visible) { 43 MemoryUsage usage) {
42 StagingBuffers& cache_level = GetCache(host_visible)[Common::Log2Ceil64(size)]; 44 StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)];
43 45
44 const auto is_free = [this](const StagingBuffer& entry) { 46 const auto is_free = [this](const StagingBuffer& entry) {
45 return scheduler.IsFree(entry.tick); 47 return scheduler.IsFree(entry.tick);
@@ -58,7 +60,7 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s
58 return it->Ref(); 60 return it->Ref();
59} 61}
60 62
61StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, bool host_visible) { 63StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage) {
62 const u32 log2 = Common::Log2Ceil64(size); 64 const u32 log2 = Common::Log2Ceil64(size);
63 vk::Buffer buffer = device.GetLogical().CreateBuffer({ 65 vk::Buffer buffer = device.GetLogical().CreateBuffer({
64 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 66 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@@ -76,10 +78,10 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, bool host_v
76 ++buffer_index; 78 ++buffer_index;
77 buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str()); 79 buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str());
78 } 80 }
79 MemoryCommit commit = memory_allocator.Commit(buffer, host_visible); 81 MemoryCommit commit = memory_allocator.Commit(buffer, usage);
80 const std::span<u8> mapped_span = host_visible ? commit.Map() : std::span<u8>{}; 82 const std::span<u8> mapped_span = IsHostVisible(usage) ? commit.Map() : std::span<u8>{};
81 83
82 StagingBuffer& entry = GetCache(host_visible)[log2].entries.emplace_back(StagingBuffer{ 84 StagingBuffer& entry = GetCache(usage)[log2].entries.emplace_back(StagingBuffer{
83 .buffer = std::move(buffer), 85 .buffer = std::move(buffer),
84 .commit = std::move(commit), 86 .commit = std::move(commit),
85 .mapped_span = mapped_span, 87 .mapped_span = mapped_span,
@@ -88,12 +90,22 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, bool host_v
88 return entry.Ref(); 90 return entry.Ref();
89} 91}
90 92
91StagingBufferPool::StagingBuffersCache& StagingBufferPool::GetCache(bool host_visible) { 93StagingBufferPool::StagingBuffersCache& StagingBufferPool::GetCache(MemoryUsage usage) {
92 return host_visible ? host_staging_buffers : device_staging_buffers; 94 switch (usage) {
95 case MemoryUsage::DeviceLocal:
96 return device_local_cache;
97 case MemoryUsage::Upload:
98 return upload_cache;
99 case MemoryUsage::Download:
100 return download_cache;
101 default:
102 UNREACHABLE_MSG("Invalid memory usage={}", usage);
103 return upload_cache;
104 }
93} 105}
94 106
95void StagingBufferPool::ReleaseCache(bool host_visible) { 107void StagingBufferPool::ReleaseCache(MemoryUsage usage) {
96 ReleaseLevel(GetCache(host_visible), current_delete_level); 108 ReleaseLevel(GetCache(usage), current_delete_level);
97} 109}
98 110
99void StagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, size_t log2) { 111void StagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, size_t log2) {
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
index 1a4338609..d42918a47 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -28,7 +28,7 @@ public:
28 VKScheduler& scheduler); 28 VKScheduler& scheduler);
29 ~StagingBufferPool(); 29 ~StagingBufferPool();
30 30
31 StagingBufferRef Request(size_t size, bool host_visible); 31 StagingBufferRef Request(size_t size, MemoryUsage usage);
32 32
33 void TickFrame(); 33 void TickFrame();
34 34
@@ -56,13 +56,13 @@ private:
56 static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT; 56 static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT;
57 using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>; 57 using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>;
58 58
59 std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, bool host_visible); 59 std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage);
60 60
61 StagingBufferRef CreateStagingBuffer(size_t size, bool host_visible); 61 StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage);
62 62
63 StagingBuffersCache& GetCache(bool host_visible); 63 StagingBuffersCache& GetCache(MemoryUsage usage);
64 64
65 void ReleaseCache(bool host_visible); 65 void ReleaseCache(MemoryUsage usage);
66 66
67 void ReleaseLevel(StagingBuffersCache& cache, size_t log2); 67 void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
68 68
@@ -70,8 +70,9 @@ private:
70 MemoryAllocator& memory_allocator; 70 MemoryAllocator& memory_allocator;
71 VKScheduler& scheduler; 71 VKScheduler& scheduler;
72 72
73 StagingBuffersCache host_staging_buffers; 73 StagingBuffersCache device_local_cache;
74 StagingBuffersCache device_staging_buffers; 74 StagingBuffersCache upload_cache;
75 StagingBuffersCache download_cache;
75 76
76 size_t current_delete_level = 0; 77 size_t current_delete_level = 0;
77 u64 buffer_index = 0; 78 u64 buffer_index = 0;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 15cd50c24..a55f84045 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -554,7 +554,7 @@ void TextureCacheRuntime::Finish() {
554} 554}
555 555
556ImageBufferMap TextureCacheRuntime::MapUploadBuffer(size_t size) { 556ImageBufferMap TextureCacheRuntime::MapUploadBuffer(size_t size) {
557 const auto staging_ref = staging_buffer_pool.Request(size, true); 557 const auto staging_ref = staging_buffer_pool.Request(size, MemoryUsage::Upload);
558 return ImageBufferMap{ 558 return ImageBufferMap{
559 .handle = staging_ref.buffer, 559 .handle = staging_ref.buffer,
560 .span = staging_ref.mapped_span, 560 .span = staging_ref.mapped_span,
@@ -788,9 +788,9 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_
788 image(MakeImage(runtime.device, info)), buffer(MakeBuffer(runtime.device, info)), 788 image(MakeImage(runtime.device, info)), buffer(MakeBuffer(runtime.device, info)),
789 aspect_mask(ImageAspectMask(info.format)) { 789 aspect_mask(ImageAspectMask(info.format)) {
790 if (image) { 790 if (image) {
791 commit = runtime.memory_allocator.Commit(image, false); 791 commit = runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal);
792 } else { 792 } else {
793 commit = runtime.memory_allocator.Commit(buffer, false); 793 commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
794 } 794 }
795 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { 795 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
796 flags |= VideoCommon::ImageFlagBits::Converted; 796 flags |= VideoCommon::ImageFlagBits::Converted;
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index c1cf292af..8bb15794d 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -156,11 +156,13 @@ MemoryAllocator::MemoryAllocator(const Device& device_)
156 156
157MemoryAllocator::~MemoryAllocator() = default; 157MemoryAllocator::~MemoryAllocator() = default;
158 158
159MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, bool host_visible) { 159MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) {
160 const u64 chunk_size = GetAllocationChunkSize(requirements.size); 160 const u64 chunk_size = GetAllocationChunkSize(requirements.size);
161 161
162 // When a host visible commit is asked, search for host visible and coherent, otherwise search 162 // When a host visible commit is asked, search for host visible and coherent, otherwise search
163 // for a fast device local type. 163 // for a fast device local type.
164 // TODO: Deduce memory types from usage in a better way
165 const bool host_visible = IsHostVisible(usage);
164 const VkMemoryPropertyFlags wanted_properties = 166 const VkMemoryPropertyFlags wanted_properties =
165 host_visible ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 167 host_visible ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
166 : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 168 : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
@@ -176,14 +178,14 @@ MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, b
176 return TryAllocCommit(requirements, wanted_properties).value(); 178 return TryAllocCommit(requirements, wanted_properties).value();
177} 179}
178 180
179MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, bool host_visible) { 181MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, MemoryUsage usage) {
180 auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), host_visible); 182 auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), usage);
181 buffer.BindMemory(commit.Memory(), commit.Offset()); 183 buffer.BindMemory(commit.Memory(), commit.Offset());
182 return commit; 184 return commit;
183} 185}
184 186
185MemoryCommit MemoryAllocator::Commit(const vk::Image& image, bool host_visible) { 187MemoryCommit MemoryAllocator::Commit(const vk::Image& image, MemoryUsage usage) {
186 auto commit = Commit(device.GetLogical().GetImageMemoryRequirements(*image), host_visible); 188 auto commit = Commit(device.GetLogical().GetImageMemoryRequirements(*image), usage);
187 image.BindMemory(commit.Memory(), commit.Offset()); 189 image.BindMemory(commit.Memory(), commit.Offset());
188 return commit; 190 return commit;
189} 191}
@@ -224,4 +226,16 @@ std::optional<MemoryCommit> MemoryAllocator::TryAllocCommit(
224 return std::nullopt; 226 return std::nullopt;
225} 227}
226 228
229bool IsHostVisible(MemoryUsage usage) noexcept {
230 switch (usage) {
231 case MemoryUsage::DeviceLocal:
232 return false;
233 case MemoryUsage::Upload:
234 case MemoryUsage::Download:
235 return true;
236 }
237 UNREACHABLE_MSG("Invalid memory usage={}", usage);
238 return false;
239}
240
227} // namespace Vulkan 241} // 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 69a6341e1..efb32167a 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.h
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h
@@ -17,7 +17,16 @@ class Device;
17class MemoryMap; 17class MemoryMap;
18class MemoryAllocation; 18class MemoryAllocation;
19 19
20class MemoryCommit final { 20/// Hints and requirements for the backing memory type of a commit
21enum class MemoryUsage {
22 DeviceLocal, ///< Hints device local usages, fastest memory type to read and write from the GPU
23 Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads
24 Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks
25};
26
27/// Ownership handle of a memory commitment.
28/// Points to a subregion of a memory allocation.
29class MemoryCommit {
21public: 30public:
22 explicit MemoryCommit() noexcept = default; 31 explicit MemoryCommit() noexcept = default;
23 explicit MemoryCommit(const Device& device_, MemoryAllocation* allocation_, 32 explicit MemoryCommit(const Device& device_, MemoryAllocation* allocation_,
@@ -54,7 +63,9 @@ private:
54 std::span<u8> span; ///< Host visible memory span. Empty if not queried before. 63 std::span<u8> span; ///< Host visible memory span. Empty if not queried before.
55}; 64};
56 65
57class MemoryAllocator final { 66/// Memory allocator container.
67/// Allocates and releases memory allocations on demand.
68class MemoryAllocator {
58public: 69public:
59 explicit MemoryAllocator(const Device& device_); 70 explicit MemoryAllocator(const Device& device_);
60 ~MemoryAllocator(); 71 ~MemoryAllocator();
@@ -71,13 +82,13 @@ public:
71 * 82 *
72 * @returns A memory commit. 83 * @returns A memory commit.
73 */ 84 */
74 MemoryCommit Commit(const VkMemoryRequirements& requirements, bool host_visible); 85 MemoryCommit Commit(const VkMemoryRequirements& requirements, MemoryUsage usage);
75 86
76 /// Commits memory required by the buffer and binds it. 87 /// Commits memory required by the buffer and binds it.
77 MemoryCommit Commit(const vk::Buffer& buffer, bool host_visible); 88 MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage);
78 89
79 /// Commits memory required by the image and binds it. 90 /// Commits memory required by the image and binds it.
80 MemoryCommit Commit(const vk::Image& image, bool host_visible); 91 MemoryCommit Commit(const vk::Image& image, MemoryUsage usage);
81 92
82private: 93private:
83 /// Allocates a chunk of memory. 94 /// Allocates a chunk of memory.
@@ -92,4 +103,7 @@ private:
92 std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. 103 std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations.
93}; 104};
94 105
106/// Returns true when a memory usage is guaranteed to be host visible.
107bool IsHostVisible(MemoryUsage usage) noexcept;
108
95} // namespace Vulkan 109} // namespace Vulkan