summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar GPUCode2023-05-27 17:09:17 +0300
committerGravatar GPUCode2023-06-18 12:45:18 +0300
commit7b2f680468bbac206f96b26a1300939be90f5f1b (patch)
treec8f506462c6d2b577ab0273e50c530fd7c71abbc /src/video_core/renderer_vulkan
parentrenderer_vulkan: Use VMA for images (diff)
downloadyuzu-7b2f680468bbac206f96b26a1300939be90f5f1b.tar.gz
yuzu-7b2f680468bbac206f96b26a1300939be90f5f1b.tar.xz
yuzu-7b2f680468bbac206f96b26a1300939be90f5f1b.zip
renderer_vulkan: Use VMA for buffers
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp81
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_smaa.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp105
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_turbo_mode.cpp8
11 files changed, 76 insertions, 162 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index e569523b6..ddf28ca28 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -233,8 +233,8 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
233 .queueFamilyIndexCount = 0, 233 .queueFamilyIndexCount = 0,
234 .pQueueFamilyIndices = nullptr, 234 .pQueueFamilyIndices = nullptr,
235 }; 235 };
236 const vk::Buffer dst_buffer = device.GetLogical().CreateBuffer(dst_buffer_info); 236 const vk::Buffer dst_buffer =
237 MemoryCommit dst_buffer_memory = memory_allocator.Commit(dst_buffer, MemoryUsage::Download); 237 memory_allocator.CreateBuffer(dst_buffer_info, MemoryUsage::Download);
238 238
239 scheduler.RequestOutsideRenderPassOperationContext(); 239 scheduler.RequestOutsideRenderPassOperationContext();
240 scheduler.Record([&](vk::CommandBuffer cmdbuf) { 240 scheduler.Record([&](vk::CommandBuffer cmdbuf) {
@@ -308,8 +308,9 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
308 scheduler.Finish(); 308 scheduler.Finish();
309 309
310 // Copy backing image data to the QImage screenshot buffer 310 // Copy backing image data to the QImage screenshot buffer
311 const auto dst_memory_map = dst_buffer_memory.Map(); 311 dst_buffer.Invalidate();
312 std::memcpy(renderer_settings.screenshot_bits, dst_memory_map.data(), dst_memory_map.size()); 312 std::memcpy(renderer_settings.screenshot_bits, dst_buffer.Mapped().data(),
313 dst_buffer.Mapped().size());
313 renderer_settings.screenshot_complete_callback(false); 314 renderer_settings.screenshot_complete_callback(false);
314 renderer_settings.screenshot_requested = false; 315 renderer_settings.screenshot_requested = false;
315} 316}
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 82ca81c7e..ad3b29f0e 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -162,7 +162,7 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
162 SetUniformData(data, layout); 162 SetUniformData(data, layout);
163 SetVertexData(data, framebuffer, layout); 163 SetVertexData(data, framebuffer, layout);
164 164
165 const std::span<u8> mapped_span = buffer_commit.Map(); 165 const std::span<u8> mapped_span = buffer.Mapped();
166 std::memcpy(mapped_span.data(), &data, sizeof(data)); 166 std::memcpy(mapped_span.data(), &data, sizeof(data));
167 167
168 if (!use_accelerated) { 168 if (!use_accelerated) {
@@ -1074,7 +1074,6 @@ void BlitScreen::ReleaseRawImages() {
1074 aa_image_view.reset(); 1074 aa_image_view.reset();
1075 aa_image.reset(); 1075 aa_image.reset();
1076 buffer.reset(); 1076 buffer.reset();
1077 buffer_commit = MemoryCommit{};
1078} 1077}
1079 1078
1080void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { 1079void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
@@ -1090,8 +1089,7 @@ void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer
1090 .pQueueFamilyIndices = nullptr, 1089 .pQueueFamilyIndices = nullptr,
1091 }; 1090 };
1092 1091
1093 buffer = device.GetLogical().CreateBuffer(ci); 1092 buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload);
1094 buffer_commit = memory_allocator.Commit(buffer, MemoryUsage::Upload);
1095} 1093}
1096 1094
1097void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { 1095void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index 7fcfa9976..8365b5668 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -142,7 +142,6 @@ private:
142 vk::Sampler sampler; 142 vk::Sampler sampler;
143 143
144 vk::Buffer buffer; 144 vk::Buffer buffer;
145 MemoryCommit buffer_commit;
146 145
147 std::vector<u64> resource_ticks; 146 std::vector<u64> resource_ticks;
148 147
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 8c33722d3..67356c679 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -50,7 +50,7 @@ size_t BytesPerIndex(VkIndexType index_type) {
50 } 50 }
51} 51}
52 52
53vk::Buffer CreateBuffer(const Device& device, u64 size) { 53vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allocator, u64 size) {
54 VkBufferUsageFlags flags = 54 VkBufferUsageFlags flags =
55 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | 55 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
56 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | 56 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
@@ -60,7 +60,7 @@ vk::Buffer CreateBuffer(const Device& device, u64 size) {
60 if (device.IsExtTransformFeedbackSupported()) { 60 if (device.IsExtTransformFeedbackSupported()) {
61 flags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; 61 flags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
62 } 62 }
63 return device.GetLogical().CreateBuffer({ 63 const VkBufferCreateInfo buffer_ci = {
64 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 64 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
65 .pNext = nullptr, 65 .pNext = nullptr,
66 .flags = 0, 66 .flags = 0,
@@ -69,7 +69,8 @@ vk::Buffer CreateBuffer(const Device& device, u64 size) {
69 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 69 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
70 .queueFamilyIndexCount = 0, 70 .queueFamilyIndexCount = 0,
71 .pQueueFamilyIndices = nullptr, 71 .pQueueFamilyIndices = nullptr,
72 }); 72 };
73 return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal);
73} 74}
74} // Anonymous namespace 75} // Anonymous namespace
75 76
@@ -79,8 +80,8 @@ Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
79Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, 80Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
80 VAddr cpu_addr_, u64 size_bytes_) 81 VAddr cpu_addr_, u64 size_bytes_)
81 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_), 82 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_),
82 device{&runtime.device}, buffer{CreateBuffer(*device, SizeBytes())}, 83 device{&runtime.device}, buffer{
83 commit{runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal)} { 84 CreateBuffer(*device, runtime.memory_allocator, SizeBytes())} {
84 if (runtime.device.HasDebuggingToolAttached()) { 85 if (runtime.device.HasDebuggingToolAttached()) {
85 buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); 86 buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str());
86 } 87 }
@@ -138,7 +139,7 @@ public:
138 const u32 num_first_offset_copies = 4; 139 const u32 num_first_offset_copies = 4;
139 const size_t bytes_per_index = BytesPerIndex(index_type); 140 const size_t bytes_per_index = BytesPerIndex(index_type);
140 const size_t size_bytes = num_triangle_indices * bytes_per_index * num_first_offset_copies; 141 const size_t size_bytes = num_triangle_indices * bytes_per_index * num_first_offset_copies;
141 buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ 142 const VkBufferCreateInfo buffer_ci = {
142 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 143 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
143 .pNext = nullptr, 144 .pNext = nullptr,
144 .flags = 0, 145 .flags = 0,
@@ -147,14 +148,21 @@ public:
147 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 148 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
148 .queueFamilyIndexCount = 0, 149 .queueFamilyIndexCount = 0,
149 .pQueueFamilyIndices = nullptr, 150 .pQueueFamilyIndices = nullptr,
150 }); 151 };
152 buffer = memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal);
151 if (device.HasDebuggingToolAttached()) { 153 if (device.HasDebuggingToolAttached()) {
152 buffer.SetObjectNameEXT("Quad LUT"); 154 buffer.SetObjectNameEXT("Quad LUT");
153 } 155 }
154 memory_commit = memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
155 156
156 const StagingBufferRef staging = staging_pool.Request(size_bytes, MemoryUsage::Upload); 157 const bool host_visible = buffer.IsHostVisible();
157 u8* staging_data = staging.mapped_span.data(); 158 const StagingBufferRef staging = [&] {
159 if (host_visible) {
160 return StagingBufferRef{};
161 }
162 return staging_pool.Request(size_bytes, MemoryUsage::Upload);
163 }();
164
165 u8* staging_data = host_visible ? buffer.Mapped().data() : staging.mapped_span.data();
158 const size_t quad_size = bytes_per_index * 6; 166 const size_t quad_size = bytes_per_index * 6;
159 167
160 for (u32 first = 0; first < num_first_offset_copies; ++first) { 168 for (u32 first = 0; first < num_first_offset_copies; ++first) {
@@ -164,29 +172,33 @@ public:
164 } 172 }
165 } 173 }
166 174
167 scheduler.RequestOutsideRenderPassOperationContext(); 175 if (!host_visible) {
168 scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset, 176 scheduler.RequestOutsideRenderPassOperationContext();
169 dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) { 177 scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset,
170 const VkBufferCopy copy{ 178 dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) {
171 .srcOffset = src_offset, 179 const VkBufferCopy copy{
172 .dstOffset = 0, 180 .srcOffset = src_offset,
173 .size = size_bytes, 181 .dstOffset = 0,
174 }; 182 .size = size_bytes,
175 const VkBufferMemoryBarrier write_barrier{ 183 };
176 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 184 const VkBufferMemoryBarrier write_barrier{
177 .pNext = nullptr, 185 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
178 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, 186 .pNext = nullptr,
179 .dstAccessMask = VK_ACCESS_INDEX_READ_BIT, 187 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
180 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 188 .dstAccessMask = VK_ACCESS_INDEX_READ_BIT,
181 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 189 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
182 .buffer = dst_buffer, 190 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
183 .offset = 0, 191 .buffer = dst_buffer,
184 .size = size_bytes, 192 .offset = 0,
185 }; 193 .size = size_bytes,
186 cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy); 194 };
187 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, 195 cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy);
188 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, write_barrier); 196 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
189 }); 197 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, write_barrier);
198 });
199 } else {
200 buffer.Flush();
201 }
190 } 202 }
191 203
192 void BindBuffer(u32 first) { 204 void BindBuffer(u32 first) {
@@ -587,11 +599,10 @@ void BufferCacheRuntime::ReserveNullBuffer() {
587 create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; 599 create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
588 } 600 }
589 create_info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; 601 create_info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
590 null_buffer = device.GetLogical().CreateBuffer(create_info); 602 null_buffer = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal);
591 if (device.HasDebuggingToolAttached()) { 603 if (device.HasDebuggingToolAttached()) {
592 null_buffer.SetObjectNameEXT("Null buffer"); 604 null_buffer.SetObjectNameEXT("Null buffer");
593 } 605 }
594 null_buffer_commit = memory_allocator.Commit(null_buffer, MemoryUsage::DeviceLocal);
595 606
596 scheduler.RequestOutsideRenderPassOperationContext(); 607 scheduler.RequestOutsideRenderPassOperationContext();
597 scheduler.Record([buffer = *null_buffer](vk::CommandBuffer cmdbuf) { 608 scheduler.Record([buffer = *null_buffer](vk::CommandBuffer cmdbuf) {
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index cdeef8846..95446c732 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -48,7 +48,6 @@ private:
48 48
49 const Device* device{}; 49 const Device* device{};
50 vk::Buffer buffer; 50 vk::Buffer buffer;
51 MemoryCommit commit;
52 std::vector<BufferView> views; 51 std::vector<BufferView> views;
53}; 52};
54 53
@@ -142,7 +141,6 @@ private:
142 std::shared_ptr<QuadStripIndexBuffer> quad_strip_index_buffer; 141 std::shared_ptr<QuadStripIndexBuffer> quad_strip_index_buffer;
143 142
144 vk::Buffer null_buffer; 143 vk::Buffer null_buffer;
145 MemoryCommit null_buffer_commit;
146 144
147 std::unique_ptr<Uint8Pass> uint8_pass; 145 std::unique_ptr<Uint8Pass> uint8_pass;
148 QuadIndexedPass quad_index_pass; 146 QuadIndexedPass quad_index_pass;
diff --git a/src/video_core/renderer_vulkan/vk_smaa.cpp b/src/video_core/renderer_vulkan/vk_smaa.cpp
index ff7c3a419..5efd7d66e 100644
--- a/src/video_core/renderer_vulkan/vk_smaa.cpp
+++ b/src/video_core/renderer_vulkan/vk_smaa.cpp
@@ -76,7 +76,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
76void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, 76void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
77 vk::Image& image, VkExtent2D dimensions, VkFormat format, 77 vk::Image& image, VkExtent2D dimensions, VkFormat format,
78 std::span<const u8> initial_contents = {}) { 78 std::span<const u8> initial_contents = {}) {
79 auto upload_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ 79 const VkBufferCreateInfo upload_ci = {
80 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 80 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
81 .pNext = nullptr, 81 .pNext = nullptr,
82 .flags = 0, 82 .flags = 0,
@@ -85,9 +85,10 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc
85 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 85 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
86 .queueFamilyIndexCount = 0, 86 .queueFamilyIndexCount = 0,
87 .pQueueFamilyIndices = nullptr, 87 .pQueueFamilyIndices = nullptr,
88 }); 88 };
89 auto upload_commit = allocator.Commit(upload_buffer, MemoryUsage::Upload); 89 auto upload_buffer = allocator.CreateBuffer(upload_ci, MemoryUsage::Upload);
90 std::ranges::copy(initial_contents, upload_commit.Map().begin()); 90 std::ranges::copy(initial_contents, upload_buffer.Mapped().begin());
91 upload_buffer.Flush();
91 92
92 const std::array<VkBufferImageCopy, 1> regions{{{ 93 const std::array<VkBufferImageCopy, 1> regions{{{
93 .bufferOffset = 0, 94 .bufferOffset = 0,
@@ -111,9 +112,6 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc
111 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 112 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
112 }); 113 });
113 scheduler.Finish(); 114 scheduler.Finish();
114
115 // This should go out of scope before the commit
116 auto upload_buffer2 = std::move(upload_buffer);
117} 115}
118 116
119vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) { 117vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) {
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 74ca77216..62b251a9b 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -30,55 +30,6 @@ constexpr VkDeviceSize MAX_STREAM_BUFFER_REQUEST_SIZE = 8_MiB;
30constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; 30constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB;
31constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS; 31constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS;
32 32
33constexpr VkMemoryPropertyFlags HOST_FLAGS =
34 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
35constexpr VkMemoryPropertyFlags STREAM_FLAGS = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | HOST_FLAGS;
36
37bool IsStreamHeap(VkMemoryHeap heap) noexcept {
38 return STREAM_BUFFER_SIZE < (heap.size * 2) / 3;
39}
40
41std::optional<u32> FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_mask,
42 VkMemoryPropertyFlags flags) noexcept {
43 for (u32 type_index = 0; type_index < props.memoryTypeCount; ++type_index) {
44 if (((type_mask >> type_index) & 1) == 0) {
45 // Memory type is incompatible
46 continue;
47 }
48 const VkMemoryType& memory_type = props.memoryTypes[type_index];
49 if ((memory_type.propertyFlags & flags) != flags) {
50 // Memory type doesn't have the flags we want
51 continue;
52 }
53 if (!IsStreamHeap(props.memoryHeaps[memory_type.heapIndex])) {
54 // Memory heap is not suitable for streaming
55 continue;
56 }
57 // Success!
58 return type_index;
59 }
60 return std::nullopt;
61}
62
63u32 FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_mask,
64 bool try_device_local) {
65 std::optional<u32> type;
66 if (try_device_local) {
67 // Try to find a DEVICE_LOCAL_BIT type, Nvidia and AMD have a dedicated heap for this
68 type = FindMemoryTypeIndex(props, type_mask, STREAM_FLAGS);
69 if (type) {
70 return *type;
71 }
72 }
73 // Otherwise try without the DEVICE_LOCAL_BIT
74 type = FindMemoryTypeIndex(props, type_mask, HOST_FLAGS);
75 if (type) {
76 return *type;
77 }
78 // This should never happen, and in case it does, signal it as an out of memory situation
79 throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY);
80}
81
82size_t Region(size_t iterator) noexcept { 33size_t Region(size_t iterator) noexcept {
83 return iterator / REGION_SIZE; 34 return iterator / REGION_SIZE;
84} 35}
@@ -87,8 +38,7 @@ size_t Region(size_t iterator) noexcept {
87StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, 38StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
88 Scheduler& scheduler_) 39 Scheduler& scheduler_)
89 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} { 40 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} {
90 const vk::Device& dev = device.GetLogical(); 41 const VkBufferCreateInfo stream_ci = {
91 stream_buffer = dev.CreateBuffer(VkBufferCreateInfo{
92 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 42 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
93 .pNext = nullptr, 43 .pNext = nullptr,
94 .flags = 0, 44 .flags = 0,
@@ -99,46 +49,13 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
99 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 49 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
100 .queueFamilyIndexCount = 0, 50 .queueFamilyIndexCount = 0,
101 .pQueueFamilyIndices = nullptr, 51 .pQueueFamilyIndices = nullptr,
102 });
103 if (device.HasDebuggingToolAttached()) {
104 stream_buffer.SetObjectNameEXT("Stream Buffer");
105 }
106 VkMemoryDedicatedRequirements dedicated_reqs{
107 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
108 .pNext = nullptr,
109 .prefersDedicatedAllocation = VK_FALSE,
110 .requiresDedicatedAllocation = VK_FALSE,
111 };
112 const auto requirements = dev.GetBufferMemoryRequirements(*stream_buffer, &dedicated_reqs);
113 const bool make_dedicated = dedicated_reqs.prefersDedicatedAllocation == VK_TRUE ||
114 dedicated_reqs.requiresDedicatedAllocation == VK_TRUE;
115 const VkMemoryDedicatedAllocateInfo dedicated_info{
116 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
117 .pNext = nullptr,
118 .image = nullptr,
119 .buffer = *stream_buffer,
120 }; 52 };
121 const auto memory_properties = device.GetPhysical().GetMemoryProperties().memoryProperties; 53 stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
122 VkMemoryAllocateInfo stream_memory_info{
123 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
124 .pNext = make_dedicated ? &dedicated_info : nullptr,
125 .allocationSize = requirements.size,
126 .memoryTypeIndex =
127 FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, true),
128 };
129 stream_memory = dev.TryAllocateMemory(stream_memory_info);
130 if (!stream_memory) {
131 LOG_INFO(Render_Vulkan, "Dynamic memory allocation failed, trying with system memory");
132 stream_memory_info.memoryTypeIndex =
133 FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, false);
134 stream_memory = dev.AllocateMemory(stream_memory_info);
135 }
136
137 if (device.HasDebuggingToolAttached()) { 54 if (device.HasDebuggingToolAttached()) {
138 stream_memory.SetObjectNameEXT("Stream Buffer Memory"); 55 stream_buffer.SetObjectNameEXT("Stream Buffer");
139 } 56 }
140 stream_buffer.BindMemory(*stream_memory, 0); 57 stream_pointer = stream_buffer.Mapped();
141 stream_pointer = stream_memory.Map(0, STREAM_BUFFER_SIZE); 58 ASSERT_MSG(!stream_pointer.empty(), "Stream buffer must be host visible!");
142} 59}
143 60
144StagingBufferPool::~StagingBufferPool() = default; 61StagingBufferPool::~StagingBufferPool() = default;
@@ -199,7 +116,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
199 return StagingBufferRef{ 116 return StagingBufferRef{
200 .buffer = *stream_buffer, 117 .buffer = *stream_buffer,
201 .offset = static_cast<VkDeviceSize>(offset), 118 .offset = static_cast<VkDeviceSize>(offset),
202 .mapped_span = std::span<u8>(stream_pointer + offset, size), 119 .mapped_span = stream_pointer.subspan(offset, size),
203 .usage{}, 120 .usage{},
204 .log2_level{}, 121 .log2_level{},
205 .index{}, 122 .index{},
@@ -247,7 +164,7 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s
247StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, 164StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage,
248 bool deferred) { 165 bool deferred) {
249 const u32 log2 = Common::Log2Ceil64(size); 166 const u32 log2 = Common::Log2Ceil64(size);
250 vk::Buffer buffer = device.GetLogical().CreateBuffer({ 167 const VkBufferCreateInfo buffer_ci = {
251 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 168 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
252 .pNext = nullptr, 169 .pNext = nullptr,
253 .flags = 0, 170 .flags = 0,
@@ -259,17 +176,15 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage
259 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 176 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
260 .queueFamilyIndexCount = 0, 177 .queueFamilyIndexCount = 0,
261 .pQueueFamilyIndices = nullptr, 178 .pQueueFamilyIndices = nullptr,
262 }); 179 };
180 vk::Buffer buffer = memory_allocator.CreateBuffer(buffer_ci, usage);
263 if (device.HasDebuggingToolAttached()) { 181 if (device.HasDebuggingToolAttached()) {
264 ++buffer_index; 182 ++buffer_index;
265 buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str()); 183 buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str());
266 } 184 }
267 MemoryCommit commit = memory_allocator.Commit(buffer, usage); 185 const std::span<u8> mapped_span = buffer.Mapped();
268 const std::span<u8> mapped_span = IsHostVisible(usage) ? commit.Map() : std::span<u8>{};
269
270 StagingBuffer& entry = GetCache(usage)[log2].entries.emplace_back(StagingBuffer{ 186 StagingBuffer& entry = GetCache(usage)[log2].entries.emplace_back(StagingBuffer{
271 .buffer = std::move(buffer), 187 .buffer = std::move(buffer),
272 .commit = std::move(commit),
273 .mapped_span = mapped_span, 188 .mapped_span = mapped_span,
274 .usage = usage, 189 .usage = usage,
275 .log2_level = log2, 190 .log2_level = 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 4fd15f11a..5f69f08b1 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -46,7 +46,6 @@ private:
46 46
47 struct StagingBuffer { 47 struct StagingBuffer {
48 vk::Buffer buffer; 48 vk::Buffer buffer;
49 MemoryCommit commit;
50 std::span<u8> mapped_span; 49 std::span<u8> mapped_span;
51 MemoryUsage usage; 50 MemoryUsage usage;
52 u32 log2_level; 51 u32 log2_level;
@@ -97,8 +96,7 @@ private:
97 Scheduler& scheduler; 96 Scheduler& scheduler;
98 97
99 vk::Buffer stream_buffer; 98 vk::Buffer stream_buffer;
100 vk::DeviceMemory stream_memory; 99 std::span<u8> stream_pointer;
101 u8* stream_pointer = nullptr;
102 100
103 size_t iterator = 0; 101 size_t iterator = 0;
104 size_t used_iterator = 0; 102 size_t used_iterator = 0;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 10defe6cb..28985b6fe 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -839,14 +839,14 @@ bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) {
839 839
840VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) { 840VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
841 const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL); 841 const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL);
842 if (buffer_commits[level]) { 842 if (buffers[level]) {
843 return *buffers[level]; 843 return *buffers[level];
844 } 844 }
845 const auto new_size = Common::NextPow2(needed_size); 845 const auto new_size = Common::NextPow2(needed_size);
846 static constexpr VkBufferUsageFlags flags = 846 static constexpr VkBufferUsageFlags flags =
847 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | 847 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
848 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; 848 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
849 buffers[level] = device.GetLogical().CreateBuffer({ 849 const VkBufferCreateInfo temp_ci = {
850 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 850 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
851 .pNext = nullptr, 851 .pNext = nullptr,
852 .flags = 0, 852 .flags = 0,
@@ -855,9 +855,8 @@ VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
855 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 855 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
856 .queueFamilyIndexCount = 0, 856 .queueFamilyIndexCount = 0,
857 .pQueueFamilyIndices = nullptr, 857 .pQueueFamilyIndices = nullptr,
858 }); 858 };
859 buffer_commits[level] = std::make_unique<MemoryCommit>( 859 buffers[level] = memory_allocator.CreateBuffer(temp_ci, MemoryUsage::DeviceLocal);
860 memory_allocator.Commit(buffers[level], MemoryUsage::DeviceLocal));
861 return *buffers[level]; 860 return *buffers[level];
862} 861}
863 862
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 9481f2531..220943116 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -116,7 +116,6 @@ public:
116 116
117 static constexpr size_t indexing_slots = 8 * sizeof(size_t); 117 static constexpr size_t indexing_slots = 8 * sizeof(size_t);
118 std::array<vk::Buffer, indexing_slots> buffers{}; 118 std::array<vk::Buffer, indexing_slots> buffers{};
119 std::array<std::unique_ptr<MemoryCommit>, indexing_slots> buffer_commits{};
120}; 119};
121 120
122class Image : public VideoCommon::ImageBase { 121class Image : public VideoCommon::ImageBase {
diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp
index 6417d7e31..460d8d59d 100644
--- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp
+++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp
@@ -41,7 +41,7 @@ void TurboMode::Run(std::stop_token stop_token) {
41 auto& dld = m_device.GetLogical(); 41 auto& dld = m_device.GetLogical();
42 42
43 // Allocate buffer. 2MiB should be sufficient. 43 // Allocate buffer. 2MiB should be sufficient.
44 auto buffer = dld.CreateBuffer(VkBufferCreateInfo{ 44 const VkBufferCreateInfo buffer_ci = {
45 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 45 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
46 .pNext = nullptr, 46 .pNext = nullptr,
47 .flags = 0, 47 .flags = 0,
@@ -50,10 +50,8 @@ void TurboMode::Run(std::stop_token stop_token) {
50 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 50 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
51 .queueFamilyIndexCount = 0, 51 .queueFamilyIndexCount = 0,
52 .pQueueFamilyIndices = nullptr, 52 .pQueueFamilyIndices = nullptr,
53 }); 53 };
54 54 vk::Buffer buffer = m_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal);
55 // Commit some device local memory for the buffer.
56 auto commit = m_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
57 55
58 // Create the descriptor pool to contain our descriptor. 56 // Create the descriptor pool to contain our descriptor.
59 static constexpr VkDescriptorPoolSize pool_size{ 57 static constexpr VkDescriptorPoolSize pool_size{