diff options
Diffstat (limited to 'src')
23 files changed, 398 insertions, 366 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index bf6439530..e9e6f278d 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -291,7 +291,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) | |||
| 291 | 291 | ||
| 292 | add_dependencies(video_core host_shaders) | 292 | add_dependencies(video_core host_shaders) |
| 293 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | 293 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) |
| 294 | target_link_libraries(video_core PRIVATE sirit Vulkan::Headers) | 294 | target_link_libraries(video_core PRIVATE sirit Vulkan::Headers vma) |
| 295 | 295 | ||
| 296 | if (ENABLE_NSIGHT_AFTERMATH) | 296 | if (ENABLE_NSIGHT_AFTERMATH) |
| 297 | if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) | 297 | if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 77128c6e2..ddf28ca28 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -89,8 +89,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 89 | Settings::values.renderer_debug.GetValue())), | 89 | Settings::values.renderer_debug.GetValue())), |
| 90 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | 90 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), |
| 91 | surface(CreateSurface(instance, render_window.GetWindowInfo())), | 91 | surface(CreateSurface(instance, render_window.GetWindowInfo())), |
| 92 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device, false), | 92 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(), |
| 93 | state_tracker(), scheduler(device, state_tracker), | 93 | scheduler(device, state_tracker), |
| 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, |
| 95 | render_window.GetFramebufferLayout().height, false), | 95 | render_window.GetFramebufferLayout().height, false), |
| 96 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, | 96 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, |
| @@ -173,7 +173,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 173 | return; | 173 | return; |
| 174 | } | 174 | } |
| 175 | const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; | 175 | const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; |
| 176 | vk::Image staging_image = device.GetLogical().CreateImage(VkImageCreateInfo{ | 176 | vk::Image staging_image = memory_allocator.CreateImage(VkImageCreateInfo{ |
| 177 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 177 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 178 | .pNext = nullptr, | 178 | .pNext = nullptr, |
| 179 | .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, | 179 | .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| @@ -196,7 +196,6 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 196 | .pQueueFamilyIndices = nullptr, | 196 | .pQueueFamilyIndices = nullptr, |
| 197 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 197 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 198 | }); | 198 | }); |
| 199 | const auto image_commit = memory_allocator.Commit(staging_image, MemoryUsage::DeviceLocal); | ||
| 200 | 199 | ||
| 201 | const vk::ImageView dst_view = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | 200 | const vk::ImageView dst_view = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ |
| 202 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 201 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| @@ -234,8 +233,8 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 234 | .queueFamilyIndexCount = 0, | 233 | .queueFamilyIndexCount = 0, |
| 235 | .pQueueFamilyIndices = nullptr, | 234 | .pQueueFamilyIndices = nullptr, |
| 236 | }; | 235 | }; |
| 237 | const vk::Buffer dst_buffer = device.GetLogical().CreateBuffer(dst_buffer_info); | 236 | const vk::Buffer dst_buffer = |
| 238 | MemoryCommit dst_buffer_memory = memory_allocator.Commit(dst_buffer, MemoryUsage::Download); | 237 | memory_allocator.CreateBuffer(dst_buffer_info, MemoryUsage::Download); |
| 239 | 238 | ||
| 240 | scheduler.RequestOutsideRenderPassOperationContext(); | 239 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 241 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { | 240 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { |
| @@ -309,8 +308,9 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 309 | scheduler.Finish(); | 308 | scheduler.Finish(); |
| 310 | 309 | ||
| 311 | // Copy backing image data to the QImage screenshot buffer | 310 | // Copy backing image data to the QImage screenshot buffer |
| 312 | const auto dst_memory_map = dst_buffer_memory.Map(); | 311 | dst_buffer.Invalidate(); |
| 313 | 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()); | ||
| 314 | renderer_settings.screenshot_complete_callback(false); | 314 | renderer_settings.screenshot_complete_callback(false); |
| 315 | renderer_settings.screenshot_requested = false; | 315 | renderer_settings.screenshot_requested = false; |
| 316 | } | 316 | } |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index acb143fc7..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) { |
| @@ -1071,14 +1071,9 @@ void BlitScreen::ReleaseRawImages() { | |||
| 1071 | scheduler.Wait(tick); | 1071 | scheduler.Wait(tick); |
| 1072 | } | 1072 | } |
| 1073 | raw_images.clear(); | 1073 | raw_images.clear(); |
| 1074 | raw_buffer_commits.clear(); | ||
| 1075 | |||
| 1076 | aa_image_view.reset(); | 1074 | aa_image_view.reset(); |
| 1077 | aa_image.reset(); | 1075 | aa_image.reset(); |
| 1078 | aa_commit = MemoryCommit{}; | ||
| 1079 | |||
| 1080 | buffer.reset(); | 1076 | buffer.reset(); |
| 1081 | buffer_commit = MemoryCommit{}; | ||
| 1082 | } | 1077 | } |
| 1083 | 1078 | ||
| 1084 | void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { | 1079 | void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { |
| @@ -1094,20 +1089,18 @@ void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer | |||
| 1094 | .pQueueFamilyIndices = nullptr, | 1089 | .pQueueFamilyIndices = nullptr, |
| 1095 | }; | 1090 | }; |
| 1096 | 1091 | ||
| 1097 | buffer = device.GetLogical().CreateBuffer(ci); | 1092 | buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload); |
| 1098 | buffer_commit = memory_allocator.Commit(buffer, MemoryUsage::Upload); | ||
| 1099 | } | 1093 | } |
| 1100 | 1094 | ||
| 1101 | void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { | 1095 | void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { |
| 1102 | raw_images.resize(image_count); | 1096 | raw_images.resize(image_count); |
| 1103 | raw_image_views.resize(image_count); | 1097 | raw_image_views.resize(image_count); |
| 1104 | raw_buffer_commits.resize(image_count); | ||
| 1105 | 1098 | ||
| 1106 | const auto create_image = [&](bool used_on_framebuffer = false, u32 up_scale = 1, | 1099 | const auto create_image = [&](bool used_on_framebuffer = false, u32 up_scale = 1, |
| 1107 | u32 down_shift = 0) { | 1100 | u32 down_shift = 0) { |
| 1108 | u32 extra_usages = used_on_framebuffer ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 1101 | u32 extra_usages = used_on_framebuffer ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
| 1109 | : VK_IMAGE_USAGE_TRANSFER_DST_BIT; | 1102 | : VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| 1110 | return device.GetLogical().CreateImage(VkImageCreateInfo{ | 1103 | return memory_allocator.CreateImage(VkImageCreateInfo{ |
| 1111 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 1104 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 1112 | .pNext = nullptr, | 1105 | .pNext = nullptr, |
| 1113 | .flags = 0, | 1106 | .flags = 0, |
| @@ -1130,9 +1123,6 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { | |||
| 1130 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 1123 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 1131 | }); | 1124 | }); |
| 1132 | }; | 1125 | }; |
| 1133 | const auto create_commit = [&](vk::Image& image) { | ||
| 1134 | return memory_allocator.Commit(image, MemoryUsage::DeviceLocal); | ||
| 1135 | }; | ||
| 1136 | const auto create_image_view = [&](vk::Image& image, bool used_on_framebuffer = false) { | 1126 | const auto create_image_view = [&](vk::Image& image, bool used_on_framebuffer = false) { |
| 1137 | return device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | 1127 | return device.GetLogical().CreateImageView(VkImageViewCreateInfo{ |
| 1138 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 1128 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| @@ -1161,7 +1151,6 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { | |||
| 1161 | 1151 | ||
| 1162 | for (size_t i = 0; i < image_count; ++i) { | 1152 | for (size_t i = 0; i < image_count; ++i) { |
| 1163 | raw_images[i] = create_image(); | 1153 | raw_images[i] = create_image(); |
| 1164 | raw_buffer_commits[i] = create_commit(raw_images[i]); | ||
| 1165 | raw_image_views[i] = create_image_view(raw_images[i]); | 1154 | raw_image_views[i] = create_image_view(raw_images[i]); |
| 1166 | } | 1155 | } |
| 1167 | 1156 | ||
| @@ -1169,7 +1158,6 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { | |||
| 1169 | const u32 up_scale = Settings::values.resolution_info.up_scale; | 1158 | const u32 up_scale = Settings::values.resolution_info.up_scale; |
| 1170 | const u32 down_shift = Settings::values.resolution_info.down_shift; | 1159 | const u32 down_shift = Settings::values.resolution_info.down_shift; |
| 1171 | aa_image = create_image(true, up_scale, down_shift); | 1160 | aa_image = create_image(true, up_scale, down_shift); |
| 1172 | aa_commit = create_commit(aa_image); | ||
| 1173 | aa_image_view = create_image_view(aa_image, true); | 1161 | aa_image_view = create_image_view(aa_image, true); |
| 1174 | VkExtent2D size{ | 1162 | VkExtent2D size{ |
| 1175 | .width = (up_scale * framebuffer.width) >> down_shift, | 1163 | .width = (up_scale * framebuffer.width) >> down_shift, |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index 68ec20253..8365b5668 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h | |||
| @@ -142,13 +142,11 @@ 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 | ||
| 149 | std::vector<vk::Image> raw_images; | 148 | std::vector<vk::Image> raw_images; |
| 150 | std::vector<vk::ImageView> raw_image_views; | 149 | std::vector<vk::ImageView> raw_image_views; |
| 151 | std::vector<MemoryCommit> raw_buffer_commits; | ||
| 152 | 150 | ||
| 153 | vk::DescriptorPool aa_descriptor_pool; | 151 | vk::DescriptorPool aa_descriptor_pool; |
| 154 | vk::DescriptorSetLayout aa_descriptor_set_layout; | 152 | vk::DescriptorSetLayout aa_descriptor_set_layout; |
| @@ -159,7 +157,6 @@ private: | |||
| 159 | vk::DescriptorSets aa_descriptor_sets; | 157 | vk::DescriptorSets aa_descriptor_sets; |
| 160 | vk::Image aa_image; | 158 | vk::Image aa_image; |
| 161 | vk::ImageView aa_image_view; | 159 | vk::ImageView aa_image_view; |
| 162 | MemoryCommit aa_commit; | ||
| 163 | 160 | ||
| 164 | u32 raw_width = 0; | 161 | u32 raw_width = 0; |
| 165 | u32 raw_height = 0; | 162 | u32 raw_height = 0; |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index f47301ad5..660f7c9ff 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 | ||
| 53 | vk::Buffer CreateBuffer(const Device& device, u64 size) { | 53 | vk::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) | |||
| 79 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, | 80 | Buffer::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_fsr.cpp b/src/video_core/renderer_vulkan/vk_fsr.cpp index df972cd54..9bcdca2fb 100644 --- a/src/video_core/renderer_vulkan/vk_fsr.cpp +++ b/src/video_core/renderer_vulkan/vk_fsr.cpp | |||
| @@ -205,10 +205,9 @@ void FSR::CreateDescriptorSets() { | |||
| 205 | void FSR::CreateImages() { | 205 | void FSR::CreateImages() { |
| 206 | images.resize(image_count * 2); | 206 | images.resize(image_count * 2); |
| 207 | image_views.resize(image_count * 2); | 207 | image_views.resize(image_count * 2); |
| 208 | buffer_commits.resize(image_count * 2); | ||
| 209 | 208 | ||
| 210 | for (size_t i = 0; i < image_count * 2; ++i) { | 209 | for (size_t i = 0; i < image_count * 2; ++i) { |
| 211 | images[i] = device.GetLogical().CreateImage(VkImageCreateInfo{ | 210 | images[i] = memory_allocator.CreateImage(VkImageCreateInfo{ |
| 212 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 211 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 213 | .pNext = nullptr, | 212 | .pNext = nullptr, |
| 214 | .flags = 0, | 213 | .flags = 0, |
| @@ -231,7 +230,6 @@ void FSR::CreateImages() { | |||
| 231 | .pQueueFamilyIndices = nullptr, | 230 | .pQueueFamilyIndices = nullptr, |
| 232 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 231 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 233 | }); | 232 | }); |
| 234 | buffer_commits[i] = memory_allocator.Commit(images[i], MemoryUsage::DeviceLocal); | ||
| 235 | image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | 233 | image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ |
| 236 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 234 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 237 | .pNext = nullptr, | 235 | .pNext = nullptr, |
diff --git a/src/video_core/renderer_vulkan/vk_fsr.h b/src/video_core/renderer_vulkan/vk_fsr.h index 5d872861f..8bb9fc23a 100644 --- a/src/video_core/renderer_vulkan/vk_fsr.h +++ b/src/video_core/renderer_vulkan/vk_fsr.h | |||
| @@ -47,7 +47,6 @@ private: | |||
| 47 | vk::Sampler sampler; | 47 | vk::Sampler sampler; |
| 48 | std::vector<vk::Image> images; | 48 | std::vector<vk::Image> images; |
| 49 | std::vector<vk::ImageView> image_views; | 49 | std::vector<vk::ImageView> image_views; |
| 50 | std::vector<MemoryCommit> buffer_commits; | ||
| 51 | }; | 50 | }; |
| 52 | 51 | ||
| 53 | } // namespace Vulkan | 52 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 10ace0420..d681bd22a 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp | |||
| @@ -181,7 +181,7 @@ void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_ | |||
| 181 | frame->height = height; | 181 | frame->height = height; |
| 182 | frame->is_srgb = is_srgb; | 182 | frame->is_srgb = is_srgb; |
| 183 | 183 | ||
| 184 | frame->image = dld.CreateImage({ | 184 | frame->image = memory_allocator.CreateImage({ |
| 185 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 185 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 186 | .pNext = nullptr, | 186 | .pNext = nullptr, |
| 187 | .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, | 187 | .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| @@ -204,8 +204,6 @@ void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_ | |||
| 204 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 204 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 205 | }); | 205 | }); |
| 206 | 206 | ||
| 207 | frame->image_commit = memory_allocator.Commit(frame->image, MemoryUsage::DeviceLocal); | ||
| 208 | |||
| 209 | frame->image_view = dld.CreateImageView({ | 207 | frame->image_view = dld.CreateImageView({ |
| 210 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 208 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 211 | .pNext = nullptr, | 209 | .pNext = nullptr, |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 4ac2e2395..83e859416 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h | |||
| @@ -29,7 +29,6 @@ struct Frame { | |||
| 29 | vk::Image image; | 29 | vk::Image image; |
| 30 | vk::ImageView image_view; | 30 | vk::ImageView image_view; |
| 31 | vk::Framebuffer framebuffer; | 31 | vk::Framebuffer framebuffer; |
| 32 | MemoryCommit image_commit; | ||
| 33 | vk::CommandBuffer cmdbuf; | 32 | vk::CommandBuffer cmdbuf; |
| 34 | vk::Semaphore render_ready; | 33 | vk::Semaphore render_ready; |
| 35 | vk::Fence present_done; | 34 | vk::Fence present_done; |
diff --git a/src/video_core/renderer_vulkan/vk_smaa.cpp b/src/video_core/renderer_vulkan/vk_smaa.cpp index f8735189d..5efd7d66e 100644 --- a/src/video_core/renderer_vulkan/vk_smaa.cpp +++ b/src/video_core/renderer_vulkan/vk_smaa.cpp | |||
| @@ -25,9 +25,7 @@ namespace { | |||
| 25 | 25 | ||
| 26 | #define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0]))) | 26 | #define ARRAY_TO_SPAN(a) std::span(a, (sizeof(a) / sizeof(a[0]))) |
| 27 | 27 | ||
| 28 | std::pair<vk::Image, MemoryCommit> CreateWrappedImage(const Device& device, | 28 | vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format) { |
| 29 | MemoryAllocator& allocator, | ||
| 30 | VkExtent2D dimensions, VkFormat format) { | ||
| 31 | const VkImageCreateInfo image_ci{ | 29 | const VkImageCreateInfo image_ci{ |
| 32 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 30 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 33 | .pNext = nullptr, | 31 | .pNext = nullptr, |
| @@ -46,11 +44,7 @@ std::pair<vk::Image, MemoryCommit> CreateWrappedImage(const Device& device, | |||
| 46 | .pQueueFamilyIndices = nullptr, | 44 | .pQueueFamilyIndices = nullptr, |
| 47 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 45 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 48 | }; | 46 | }; |
| 49 | 47 | return allocator.CreateImage(image_ci); | |
| 50 | auto image = device.GetLogical().CreateImage(image_ci); | ||
| 51 | auto commit = allocator.Commit(image, Vulkan::MemoryUsage::DeviceLocal); | ||
| 52 | |||
| 53 | return std::make_pair(std::move(image), std::move(commit)); | ||
| 54 | } | 48 | } |
| 55 | 49 | ||
| 56 | void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, | 50 | void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, |
| @@ -82,7 +76,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo | |||
| 82 | void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, | 76 | void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, |
| 83 | vk::Image& image, VkExtent2D dimensions, VkFormat format, | 77 | vk::Image& image, VkExtent2D dimensions, VkFormat format, |
| 84 | std::span<const u8> initial_contents = {}) { | 78 | std::span<const u8> initial_contents = {}) { |
| 85 | auto upload_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ | 79 | const VkBufferCreateInfo upload_ci = { |
| 86 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 80 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 87 | .pNext = nullptr, | 81 | .pNext = nullptr, |
| 88 | .flags = 0, | 82 | .flags = 0, |
| @@ -91,9 +85,10 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc | |||
| 91 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 85 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 92 | .queueFamilyIndexCount = 0, | 86 | .queueFamilyIndexCount = 0, |
| 93 | .pQueueFamilyIndices = nullptr, | 87 | .pQueueFamilyIndices = nullptr, |
| 94 | }); | 88 | }; |
| 95 | auto upload_commit = allocator.Commit(upload_buffer, MemoryUsage::Upload); | 89 | auto upload_buffer = allocator.CreateBuffer(upload_ci, MemoryUsage::Upload); |
| 96 | std::ranges::copy(initial_contents, upload_commit.Map().begin()); | 90 | std::ranges::copy(initial_contents, upload_buffer.Mapped().begin()); |
| 91 | upload_buffer.Flush(); | ||
| 97 | 92 | ||
| 98 | const std::array<VkBufferImageCopy, 1> regions{{{ | 93 | const std::array<VkBufferImageCopy, 1> regions{{{ |
| 99 | .bufferOffset = 0, | 94 | .bufferOffset = 0, |
| @@ -117,9 +112,6 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc | |||
| 117 | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); | 112 | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| 118 | }); | 113 | }); |
| 119 | scheduler.Finish(); | 114 | scheduler.Finish(); |
| 120 | |||
| 121 | // This should go out of scope before the commit | ||
| 122 | auto upload_buffer2 = std::move(upload_buffer); | ||
| 123 | } | 115 | } |
| 124 | 116 | ||
| 125 | vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) { | 117 | vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) { |
| @@ -531,10 +523,8 @@ void SMAA::CreateImages() { | |||
| 531 | static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; | 523 | static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; |
| 532 | static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; | 524 | static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; |
| 533 | 525 | ||
| 534 | std::tie(m_static_images[Area], m_static_buffer_commits[Area]) = | 526 | m_static_images[Area] = CreateWrappedImage(m_allocator, area_extent, VK_FORMAT_R8G8_UNORM); |
| 535 | CreateWrappedImage(m_device, m_allocator, area_extent, VK_FORMAT_R8G8_UNORM); | 527 | m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM); |
| 536 | std::tie(m_static_images[Search], m_static_buffer_commits[Search]) = | ||
| 537 | CreateWrappedImage(m_device, m_allocator, search_extent, VK_FORMAT_R8_UNORM); | ||
| 538 | 528 | ||
| 539 | m_static_image_views[Area] = | 529 | m_static_image_views[Area] = |
| 540 | CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); | 530 | CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); |
| @@ -544,12 +534,11 @@ void SMAA::CreateImages() { | |||
| 544 | for (u32 i = 0; i < m_image_count; i++) { | 534 | for (u32 i = 0; i < m_image_count; i++) { |
| 545 | Images& images = m_dynamic_images.emplace_back(); | 535 | Images& images = m_dynamic_images.emplace_back(); |
| 546 | 536 | ||
| 547 | std::tie(images.images[Blend], images.buffer_commits[Blend]) = | 537 | images.images[Blend] = |
| 548 | CreateWrappedImage(m_device, m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | 538 | CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); |
| 549 | std::tie(images.images[Edges], images.buffer_commits[Edges]) = | 539 | images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT); |
| 550 | CreateWrappedImage(m_device, m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT); | 540 | images.images[Output] = |
| 551 | std::tie(images.images[Output], images.buffer_commits[Output]) = | 541 | CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); |
| 552 | CreateWrappedImage(m_device, m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); | ||
| 553 | 542 | ||
| 554 | images.image_views[Blend] = | 543 | images.image_views[Blend] = |
| 555 | CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); | 544 | CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); |
diff --git a/src/video_core/renderer_vulkan/vk_smaa.h b/src/video_core/renderer_vulkan/vk_smaa.h index 99a369148..0e214258a 100644 --- a/src/video_core/renderer_vulkan/vk_smaa.h +++ b/src/video_core/renderer_vulkan/vk_smaa.h | |||
| @@ -66,13 +66,11 @@ private: | |||
| 66 | std::array<vk::Pipeline, MaxSMAAStage> m_pipelines{}; | 66 | std::array<vk::Pipeline, MaxSMAAStage> m_pipelines{}; |
| 67 | std::array<vk::RenderPass, MaxSMAAStage> m_renderpasses{}; | 67 | std::array<vk::RenderPass, MaxSMAAStage> m_renderpasses{}; |
| 68 | 68 | ||
| 69 | std::array<MemoryCommit, MaxStaticImage> m_static_buffer_commits; | ||
| 70 | std::array<vk::Image, MaxStaticImage> m_static_images{}; | 69 | std::array<vk::Image, MaxStaticImage> m_static_images{}; |
| 71 | std::array<vk::ImageView, MaxStaticImage> m_static_image_views{}; | 70 | std::array<vk::ImageView, MaxStaticImage> m_static_image_views{}; |
| 72 | 71 | ||
| 73 | struct Images { | 72 | struct Images { |
| 74 | vk::DescriptorSets descriptor_sets{}; | 73 | vk::DescriptorSets descriptor_sets{}; |
| 75 | std::array<MemoryCommit, MaxDynamicImage> buffer_commits; | ||
| 76 | std::array<vk::Image, MaxDynamicImage> images{}; | 74 | std::array<vk::Image, MaxDynamicImage> images{}; |
| 77 | std::array<vk::ImageView, MaxDynamicImage> image_views{}; | 75 | std::array<vk::ImageView, MaxDynamicImage> image_views{}; |
| 78 | std::array<vk::Framebuffer, MaxSMAAStage> framebuffers{}; | 76 | std::array<vk::Framebuffer, MaxSMAAStage> framebuffers{}; |
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; | |||
| 30 | constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; | 30 | constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; |
| 31 | constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS; | 31 | constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS; |
| 32 | 32 | ||
| 33 | constexpr VkMemoryPropertyFlags HOST_FLAGS = | ||
| 34 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||
| 35 | constexpr VkMemoryPropertyFlags STREAM_FLAGS = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | HOST_FLAGS; | ||
| 36 | |||
| 37 | bool IsStreamHeap(VkMemoryHeap heap) noexcept { | ||
| 38 | return STREAM_BUFFER_SIZE < (heap.size * 2) / 3; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::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 | |||
| 63 | u32 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 | |||
| 82 | size_t Region(size_t iterator) noexcept { | 33 | size_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 { | |||
| 87 | StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, | 38 | StagingBufferPool::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 | ||
| 144 | StagingBufferPool::~StagingBufferPool() = default; | 61 | StagingBufferPool::~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 | |||
| 247 | StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, | 164 | StagingBufferRef 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 f3cef09dd..ce6acc30c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include "video_core/renderer_vulkan/blit_image.h" | 15 | #include "video_core/renderer_vulkan/blit_image.h" |
| 16 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 16 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 17 | #include "video_core/renderer_vulkan/vk_compute_pass.h" | 17 | #include "video_core/renderer_vulkan/vk_compute_pass.h" |
| 18 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||
| 19 | #include "video_core/renderer_vulkan/vk_render_pass_cache.h" | 18 | #include "video_core/renderer_vulkan/vk_render_pass_cache.h" |
| 20 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 19 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 21 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 20 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| @@ -163,11 +162,12 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 163 | }; | 162 | }; |
| 164 | } | 163 | } |
| 165 | 164 | ||
| 166 | [[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info) { | 165 | [[nodiscard]] vk::Image MakeImage(const Device& device, const MemoryAllocator& allocator, |
| 166 | const ImageInfo& info) { | ||
| 167 | if (info.type == ImageType::Buffer) { | 167 | if (info.type == ImageType::Buffer) { |
| 168 | return vk::Image{}; | 168 | return vk::Image{}; |
| 169 | } | 169 | } |
| 170 | return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info)); | 170 | return allocator.CreateImage(MakeImageCreateInfo(device, info)); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { | 173 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { |
| @@ -839,14 +839,14 @@ bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) { | |||
| 839 | 839 | ||
| 840 | VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) { | 840 | VkBuffer 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 | ||
| @@ -1266,8 +1265,8 @@ void TextureCacheRuntime::TickFrame() {} | |||
| 1266 | Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_, | 1265 | Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_, |
| 1267 | VAddr cpu_addr_) | 1266 | VAddr cpu_addr_) |
| 1268 | : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler}, | 1267 | : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler}, |
| 1269 | runtime{&runtime_}, original_image(MakeImage(runtime_.device, info)), | 1268 | runtime{&runtime_}, |
| 1270 | commit(runtime_.memory_allocator.Commit(original_image, MemoryUsage::DeviceLocal)), | 1269 | original_image(MakeImage(runtime_.device, runtime_.memory_allocator, info)), |
| 1271 | aspect_mask(ImageAspectMask(info.format)) { | 1270 | aspect_mask(ImageAspectMask(info.format)) { |
| 1272 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) { | 1271 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) { |
| 1273 | if (Settings::values.async_astc.GetValue()) { | 1272 | if (Settings::values.async_astc.GetValue()) { |
| @@ -1468,9 +1467,7 @@ bool Image::ScaleUp(bool ignore) { | |||
| 1468 | auto scaled_info = info; | 1467 | auto scaled_info = info; |
| 1469 | scaled_info.size.width = scaled_width; | 1468 | scaled_info.size.width = scaled_width; |
| 1470 | scaled_info.size.height = scaled_height; | 1469 | scaled_info.size.height = scaled_height; |
| 1471 | scaled_image = MakeImage(runtime->device, scaled_info); | 1470 | scaled_image = MakeImage(runtime->device, runtime->memory_allocator, scaled_info); |
| 1472 | auto& allocator = runtime->memory_allocator; | ||
| 1473 | scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal)); | ||
| 1474 | ignore = false; | 1471 | ignore = false; |
| 1475 | } | 1472 | } |
| 1476 | current_image = *scaled_image; | 1473 | current_image = *scaled_image; |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index f14525dcb..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 | ||
| 122 | class Image : public VideoCommon::ImageBase { | 121 | class Image : public VideoCommon::ImageBase { |
| @@ -180,12 +179,10 @@ private: | |||
| 180 | TextureCacheRuntime* runtime{}; | 179 | TextureCacheRuntime* runtime{}; |
| 181 | 180 | ||
| 182 | vk::Image original_image; | 181 | vk::Image original_image; |
| 183 | MemoryCommit commit; | ||
| 184 | std::vector<vk::ImageView> storage_image_views; | 182 | std::vector<vk::ImageView> storage_image_views; |
| 185 | VkImageAspectFlags aspect_mask = 0; | 183 | VkImageAspectFlags aspect_mask = 0; |
| 186 | bool initialized = false; | 184 | bool initialized = false; |
| 187 | vk::Image scaled_image{}; | 185 | vk::Image scaled_image{}; |
| 188 | MemoryCommit scaled_commit{}; | ||
| 189 | VkImage current_image{}; | 186 | VkImage current_image{}; |
| 190 | 187 | ||
| 191 | std::unique_ptr<Framebuffer> scale_framebuffer; | 188 | std::unique_ptr<Framebuffer> scale_framebuffer; |
diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index a802d3c49..460d8d59d 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp | |||
| @@ -18,7 +18,7 @@ using namespace Common::Literals; | |||
| 18 | 18 | ||
| 19 | TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld) | 19 | TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld) |
| 20 | #ifndef ANDROID | 20 | #ifndef ANDROID |
| 21 | : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} | 21 | : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device} |
| 22 | #endif | 22 | #endif |
| 23 | { | 23 | { |
| 24 | { | 24 | { |
| @@ -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{ |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index b11abe311..e4ca65b58 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #include <adrenotools/bcenabler.h> | 22 | #include <adrenotools/bcenabler.h> |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | #include <vk_mem_alloc.h> | ||
| 26 | |||
| 25 | namespace Vulkan { | 27 | namespace Vulkan { |
| 26 | using namespace Common::Literals; | 28 | using namespace Common::Literals; |
| 27 | namespace { | 29 | namespace { |
| @@ -596,9 +598,31 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 596 | 598 | ||
| 597 | graphics_queue = logical.GetQueue(graphics_family); | 599 | graphics_queue = logical.GetQueue(graphics_family); |
| 598 | present_queue = logical.GetQueue(present_family); | 600 | present_queue = logical.GetQueue(present_family); |
| 601 | |||
| 602 | VmaVulkanFunctions functions{}; | ||
| 603 | functions.vkGetInstanceProcAddr = dld.vkGetInstanceProcAddr; | ||
| 604 | functions.vkGetDeviceProcAddr = dld.vkGetDeviceProcAddr; | ||
| 605 | |||
| 606 | const VmaAllocatorCreateInfo allocator_info = { | ||
| 607 | .flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, | ||
| 608 | .physicalDevice = physical, | ||
| 609 | .device = *logical, | ||
| 610 | .preferredLargeHeapBlockSize = 0, | ||
| 611 | .pAllocationCallbacks = nullptr, | ||
| 612 | .pDeviceMemoryCallbacks = nullptr, | ||
| 613 | .pHeapSizeLimit = nullptr, | ||
| 614 | .pVulkanFunctions = &functions, | ||
| 615 | .instance = instance, | ||
| 616 | .vulkanApiVersion = VK_API_VERSION_1_1, | ||
| 617 | .pTypeExternalMemoryHandleTypes = nullptr, | ||
| 618 | }; | ||
| 619 | |||
| 620 | vk::Check(vmaCreateAllocator(&allocator_info, &allocator)); | ||
| 599 | } | 621 | } |
| 600 | 622 | ||
| 601 | Device::~Device() = default; | 623 | Device::~Device() { |
| 624 | vmaDestroyAllocator(allocator); | ||
| 625 | } | ||
| 602 | 626 | ||
| 603 | VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags wanted_usage, | 627 | VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags wanted_usage, |
| 604 | FormatType format_type) const { | 628 | FormatType format_type) const { |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 0b634a876..b84af3dfb 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 15 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 15 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 16 | 16 | ||
| 17 | VK_DEFINE_HANDLE(VmaAllocator) | ||
| 18 | |||
| 17 | // Define all features which may be used by the implementation here. | 19 | // Define all features which may be used by the implementation here. |
| 18 | // Vulkan version in the macro describes the minimum version required for feature availability. | 20 | // Vulkan version in the macro describes the minimum version required for feature availability. |
| 19 | // If the Vulkan version is lower than the required version, the named extension is required. | 21 | // If the Vulkan version is lower than the required version, the named extension is required. |
| @@ -199,6 +201,11 @@ public: | |||
| 199 | return dld; | 201 | return dld; |
| 200 | } | 202 | } |
| 201 | 203 | ||
| 204 | /// Returns the VMA allocator. | ||
| 205 | VmaAllocator GetAllocator() const { | ||
| 206 | return allocator; | ||
| 207 | } | ||
| 208 | |||
| 202 | /// Returns the logical device. | 209 | /// Returns the logical device. |
| 203 | const vk::Device& GetLogical() const { | 210 | const vk::Device& GetLogical() const { |
| 204 | return logical; | 211 | return logical; |
| @@ -630,6 +637,7 @@ private: | |||
| 630 | 637 | ||
| 631 | private: | 638 | private: |
| 632 | VkInstance instance; ///< Vulkan instance. | 639 | VkInstance instance; ///< Vulkan instance. |
| 640 | VmaAllocator allocator; ///< VMA allocator. | ||
| 633 | vk::DeviceDispatch dld; ///< Device function pointers. | 641 | vk::DeviceDispatch dld; ///< Device function pointers. |
| 634 | vk::PhysicalDevice physical; ///< Physical device. | 642 | vk::PhysicalDevice physical; ///< Physical device. |
| 635 | vk::Device logical; ///< Logical device. | 643 | vk::Device logical; ///< Logical device. |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index e28a556f8..a2ef0efa4 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp | |||
| @@ -6,8 +6,6 @@ | |||
| 6 | #include <optional> | 6 | #include <optional> |
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include <glad/glad.h> | ||
| 10 | |||
| 11 | #include "common/alignment.h" | 9 | #include "common/alignment.h" |
| 12 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 13 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| @@ -17,6 +15,8 @@ | |||
| 17 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 15 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 18 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 16 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 19 | 17 | ||
| 18 | #include <vk_mem_alloc.h> | ||
| 19 | |||
| 20 | namespace Vulkan { | 20 | namespace Vulkan { |
| 21 | namespace { | 21 | namespace { |
| 22 | struct Range { | 22 | struct Range { |
| @@ -49,22 +49,45 @@ struct Range { | |||
| 49 | case MemoryUsage::Download: | 49 | case MemoryUsage::Download: |
| 50 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | | 50 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | |
| 51 | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; | 51 | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; |
| 52 | case MemoryUsage::Stream: | ||
| 53 | return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | | ||
| 54 | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||
| 52 | } | 55 | } |
| 53 | ASSERT_MSG(false, "Invalid memory usage={}", usage); | 56 | ASSERT_MSG(false, "Invalid memory usage={}", usage); |
| 54 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | 57 | return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| 57 | constexpr VkExportMemoryAllocateInfo EXPORT_ALLOCATE_INFO{ | 60 | [[nodiscard]] VkMemoryPropertyFlags MemoryUsagePreferedVmaFlags(MemoryUsage usage) { |
| 58 | .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, | 61 | return usage != MemoryUsage::DeviceLocal ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
| 59 | .pNext = nullptr, | 62 | : VkMemoryPropertyFlagBits{}; |
| 60 | #ifdef _WIN32 | 63 | } |
| 61 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, | 64 | |
| 62 | #elif __unix__ | 65 | [[nodiscard]] VmaAllocationCreateFlags MemoryUsageVmaFlags(MemoryUsage usage) { |
| 63 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, | 66 | switch (usage) { |
| 64 | #else | 67 | case MemoryUsage::Upload: |
| 65 | .handleTypes = 0, | 68 | case MemoryUsage::Stream: |
| 66 | #endif | 69 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; |
| 67 | }; | 70 | case MemoryUsage::Download: |
| 71 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; | ||
| 72 | case MemoryUsage::DeviceLocal: | ||
| 73 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | | ||
| 74 | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT; | ||
| 75 | } | ||
| 76 | return {}; | ||
| 77 | } | ||
| 78 | |||
| 79 | [[nodiscard]] VmaMemoryUsage MemoryUsageVma(MemoryUsage usage) { | ||
| 80 | switch (usage) { | ||
| 81 | case MemoryUsage::DeviceLocal: | ||
| 82 | case MemoryUsage::Stream: | ||
| 83 | return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; | ||
| 84 | case MemoryUsage::Upload: | ||
| 85 | case MemoryUsage::Download: | ||
| 86 | return VMA_MEMORY_USAGE_AUTO_PREFER_HOST; | ||
| 87 | } | ||
| 88 | return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; | ||
| 89 | } | ||
| 90 | |||
| 68 | } // Anonymous namespace | 91 | } // Anonymous namespace |
| 69 | 92 | ||
| 70 | class MemoryAllocation { | 93 | class MemoryAllocation { |
| @@ -74,14 +97,6 @@ public: | |||
| 74 | : allocator{allocator_}, memory{std::move(memory_)}, allocation_size{allocation_size_}, | 97 | : allocator{allocator_}, memory{std::move(memory_)}, allocation_size{allocation_size_}, |
| 75 | property_flags{properties}, shifted_memory_type{1U << type} {} | 98 | property_flags{properties}, shifted_memory_type{1U << type} {} |
| 76 | 99 | ||
| 77 | #if defined(_WIN32) || defined(__unix__) | ||
| 78 | ~MemoryAllocation() { | ||
| 79 | if (owning_opengl_handle != 0) { | ||
| 80 | glDeleteMemoryObjectsEXT(1, &owning_opengl_handle); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | #endif | ||
| 84 | |||
| 85 | MemoryAllocation& operator=(const MemoryAllocation&) = delete; | 100 | MemoryAllocation& operator=(const MemoryAllocation&) = delete; |
| 86 | MemoryAllocation(const MemoryAllocation&) = delete; | 101 | MemoryAllocation(const MemoryAllocation&) = delete; |
| 87 | 102 | ||
| @@ -120,31 +135,6 @@ public: | |||
| 120 | return memory_mapped_span; | 135 | return memory_mapped_span; |
| 121 | } | 136 | } |
| 122 | 137 | ||
| 123 | #ifdef _WIN32 | ||
| 124 | [[nodiscard]] u32 ExportOpenGLHandle() { | ||
| 125 | if (!owning_opengl_handle) { | ||
| 126 | glCreateMemoryObjectsEXT(1, &owning_opengl_handle); | ||
| 127 | glImportMemoryWin32HandleEXT(owning_opengl_handle, allocation_size, | ||
| 128 | GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, | ||
| 129 | memory.GetMemoryWin32HandleKHR()); | ||
| 130 | } | ||
| 131 | return owning_opengl_handle; | ||
| 132 | } | ||
| 133 | #elif __unix__ | ||
| 134 | [[nodiscard]] u32 ExportOpenGLHandle() { | ||
| 135 | if (!owning_opengl_handle) { | ||
| 136 | glCreateMemoryObjectsEXT(1, &owning_opengl_handle); | ||
| 137 | glImportMemoryFdEXT(owning_opengl_handle, allocation_size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, | ||
| 138 | memory.GetMemoryFdKHR()); | ||
| 139 | } | ||
| 140 | return owning_opengl_handle; | ||
| 141 | } | ||
| 142 | #else | ||
| 143 | [[nodiscard]] u32 ExportOpenGLHandle() { | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | #endif | ||
| 147 | |||
| 148 | /// Returns whether this allocation is compatible with the arguments. | 138 | /// Returns whether this allocation is compatible with the arguments. |
| 149 | [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const { | 139 | [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const { |
| 150 | return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0; | 140 | return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0; |
| @@ -182,9 +172,6 @@ private: | |||
| 182 | const u32 shifted_memory_type; ///< Shifted Vulkan memory type. | 172 | const u32 shifted_memory_type; ///< Shifted Vulkan memory type. |
| 183 | std::vector<Range> commits; ///< All commit ranges done from this allocation. | 173 | std::vector<Range> commits; ///< All commit ranges done from this allocation. |
| 184 | std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before. | 174 | std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before. |
| 185 | #if defined(_WIN32) || defined(__unix__) | ||
| 186 | u32 owning_opengl_handle{}; ///< Owning OpenGL memory object handle. | ||
| 187 | #endif | ||
| 188 | }; | 175 | }; |
| 189 | 176 | ||
| 190 | MemoryCommit::MemoryCommit(MemoryAllocation* allocation_, VkDeviceMemory memory_, u64 begin_, | 177 | MemoryCommit::MemoryCommit(MemoryAllocation* allocation_, VkDeviceMemory memory_, u64 begin_, |
| @@ -216,24 +203,70 @@ std::span<u8> MemoryCommit::Map() { | |||
| 216 | return span; | 203 | return span; |
| 217 | } | 204 | } |
| 218 | 205 | ||
| 219 | u32 MemoryCommit::ExportOpenGLHandle() const { | ||
| 220 | return allocation->ExportOpenGLHandle(); | ||
| 221 | } | ||
| 222 | |||
| 223 | void MemoryCommit::Release() { | 206 | void MemoryCommit::Release() { |
| 224 | if (allocation) { | 207 | if (allocation) { |
| 225 | allocation->Free(begin); | 208 | allocation->Free(begin); |
| 226 | } | 209 | } |
| 227 | } | 210 | } |
| 228 | 211 | ||
| 229 | MemoryAllocator::MemoryAllocator(const Device& device_, bool export_allocations_) | 212 | MemoryAllocator::MemoryAllocator(const Device& device_) |
| 230 | : device{device_}, properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, | 213 | : device{device_}, allocator{device.GetAllocator()}, |
| 231 | export_allocations{export_allocations_}, | 214 | properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, |
| 232 | buffer_image_granularity{ | 215 | buffer_image_granularity{ |
| 233 | device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} | 216 | device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} |
| 234 | 217 | ||
| 235 | MemoryAllocator::~MemoryAllocator() = default; | 218 | MemoryAllocator::~MemoryAllocator() = default; |
| 236 | 219 | ||
| 220 | vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const { | ||
| 221 | const VmaAllocationCreateInfo alloc_ci = { | ||
| 222 | .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT, | ||
| 223 | .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, | ||
| 224 | .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, | ||
| 225 | .preferredFlags = 0, | ||
| 226 | .memoryTypeBits = 0, | ||
| 227 | .pool = VK_NULL_HANDLE, | ||
| 228 | .pUserData = nullptr, | ||
| 229 | .priority = 0.f, | ||
| 230 | }; | ||
| 231 | |||
| 232 | VkImage handle{}; | ||
| 233 | VmaAllocation allocation{}; | ||
| 234 | |||
| 235 | vk::Check(vmaCreateImage(allocator, &ci, &alloc_ci, &handle, &allocation, nullptr)); | ||
| 236 | |||
| 237 | return vk::Image(handle, *device.GetLogical(), allocator, allocation, | ||
| 238 | device.GetDispatchLoader()); | ||
| 239 | } | ||
| 240 | |||
| 241 | vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const { | ||
| 242 | const VmaAllocationCreateInfo alloc_ci = { | ||
| 243 | .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT | | ||
| 244 | MemoryUsageVmaFlags(usage), | ||
| 245 | .usage = MemoryUsageVma(usage), | ||
| 246 | .requiredFlags = 0, | ||
| 247 | .preferredFlags = MemoryUsagePreferedVmaFlags(usage), | ||
| 248 | .memoryTypeBits = 0, | ||
| 249 | .pool = VK_NULL_HANDLE, | ||
| 250 | .pUserData = nullptr, | ||
| 251 | .priority = 0.f, | ||
| 252 | }; | ||
| 253 | |||
| 254 | VkBuffer handle{}; | ||
| 255 | VmaAllocationInfo alloc_info{}; | ||
| 256 | VmaAllocation allocation{}; | ||
| 257 | VkMemoryPropertyFlags property_flags{}; | ||
| 258 | |||
| 259 | vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info)); | ||
| 260 | vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags); | ||
| 261 | |||
| 262 | u8* data = reinterpret_cast<u8*>(alloc_info.pMappedData); | ||
| 263 | const std::span<u8> mapped_data = data ? std::span<u8>{data, ci.size} : std::span<u8>{}; | ||
| 264 | const bool is_coherent = property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||
| 265 | |||
| 266 | return vk::Buffer(handle, *device.GetLogical(), allocator, allocation, mapped_data, is_coherent, | ||
| 267 | device.GetDispatchLoader()); | ||
| 268 | } | ||
| 269 | |||
| 237 | MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { | 270 | MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { |
| 238 | // Find the fastest memory flags we can afford with the current requirements | 271 | // Find the fastest memory flags we can afford with the current requirements |
| 239 | const u32 type_mask = requirements.memoryTypeBits; | 272 | const u32 type_mask = requirements.memoryTypeBits; |
| @@ -253,25 +286,11 @@ MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, M | |||
| 253 | return TryCommit(requirements, flags).value(); | 286 | return TryCommit(requirements, flags).value(); |
| 254 | } | 287 | } |
| 255 | 288 | ||
| 256 | MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, MemoryUsage usage) { | ||
| 257 | auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), usage); | ||
| 258 | buffer.BindMemory(commit.Memory(), commit.Offset()); | ||
| 259 | return commit; | ||
| 260 | } | ||
| 261 | |||
| 262 | MemoryCommit MemoryAllocator::Commit(const vk::Image& image, MemoryUsage usage) { | ||
| 263 | VkMemoryRequirements requirements = device.GetLogical().GetImageMemoryRequirements(*image); | ||
| 264 | requirements.size = Common::AlignUp(requirements.size, buffer_image_granularity); | ||
| 265 | auto commit = Commit(requirements, usage); | ||
| 266 | image.BindMemory(commit.Memory(), commit.Offset()); | ||
| 267 | return commit; | ||
| 268 | } | ||
| 269 | |||
| 270 | bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { | 289 | bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { |
| 271 | const u32 type = FindType(flags, type_mask).value(); | 290 | const u32 type = FindType(flags, type_mask).value(); |
| 272 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ | 291 | vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ |
| 273 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | 292 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
| 274 | .pNext = export_allocations ? &EXPORT_ALLOCATE_INFO : nullptr, | 293 | .pNext = nullptr, |
| 275 | .allocationSize = size, | 294 | .allocationSize = size, |
| 276 | .memoryTypeIndex = type, | 295 | .memoryTypeIndex = type, |
| 277 | }); | 296 | }); |
| @@ -342,16 +361,4 @@ std::optional<u32> MemoryAllocator::FindType(VkMemoryPropertyFlags flags, u32 ty | |||
| 342 | return std::nullopt; | 361 | return std::nullopt; |
| 343 | } | 362 | } |
| 344 | 363 | ||
| 345 | bool IsHostVisible(MemoryUsage usage) noexcept { | ||
| 346 | switch (usage) { | ||
| 347 | case MemoryUsage::DeviceLocal: | ||
| 348 | return false; | ||
| 349 | case MemoryUsage::Upload: | ||
| 350 | case MemoryUsage::Download: | ||
| 351 | return true; | ||
| 352 | } | ||
| 353 | ASSERT_MSG(false, "Invalid memory usage={}", usage); | ||
| 354 | return false; | ||
| 355 | } | ||
| 356 | |||
| 357 | } // namespace Vulkan | 364 | } // 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 a5bff03fe..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. |
| @@ -41,9 +45,6 @@ public: | |||
| 41 | /// It will map the backing allocation if it hasn't been mapped before. | 45 | /// It will map the backing allocation if it hasn't been mapped before. |
| 42 | std::span<u8> Map(); | 46 | std::span<u8> Map(); |
| 43 | 47 | ||
| 44 | /// Returns an non-owning OpenGL handle, creating one if it doesn't exist. | ||
| 45 | u32 ExportOpenGLHandle() const; | ||
| 46 | |||
| 47 | /// Returns the Vulkan memory handler. | 48 | /// Returns the Vulkan memory handler. |
| 48 | VkDeviceMemory Memory() const { | 49 | VkDeviceMemory Memory() const { |
| 49 | return memory; | 50 | return memory; |
| @@ -74,16 +75,19 @@ public: | |||
| 74 | * Construct memory allocator | 75 | * Construct memory allocator |
| 75 | * | 76 | * |
| 76 | * @param device_ Device to allocate from | 77 | * @param device_ Device to allocate from |
| 77 | * @param export_allocations_ True when allocations have to be exported | ||
| 78 | * | 78 | * |
| 79 | * @throw vk::Exception on failure | 79 | * @throw vk::Exception on failure |
| 80 | */ | 80 | */ |
| 81 | explicit MemoryAllocator(const Device& device_, bool export_allocations_); | 81 | explicit MemoryAllocator(const Device& device_); |
| 82 | ~MemoryAllocator(); | 82 | ~MemoryAllocator(); |
| 83 | 83 | ||
| 84 | MemoryAllocator& operator=(const MemoryAllocator&) = delete; | 84 | MemoryAllocator& operator=(const MemoryAllocator&) = delete; |
| 85 | MemoryAllocator(const MemoryAllocator&) = delete; | 85 | MemoryAllocator(const MemoryAllocator&) = delete; |
| 86 | 86 | ||
| 87 | vk::Image CreateImage(const VkImageCreateInfo& ci) const; | ||
| 88 | |||
| 89 | vk::Buffer CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const; | ||
| 90 | |||
| 87 | /** | 91 | /** |
| 88 | * Commits a memory with the specified requirements. | 92 | * Commits a memory with the specified requirements. |
| 89 | * | 93 | * |
| @@ -97,9 +101,6 @@ public: | |||
| 97 | /// Commits memory required by the buffer and binds it. | 101 | /// Commits memory required by the buffer and binds it. |
| 98 | MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage); | 102 | MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage); |
| 99 | 103 | ||
| 100 | /// Commits memory required by the image and binds it. | ||
| 101 | MemoryCommit Commit(const vk::Image& image, MemoryUsage usage); | ||
| 102 | |||
| 103 | private: | 104 | private: |
| 104 | /// Tries to allocate a chunk of memory. | 105 | /// Tries to allocate a chunk of memory. |
| 105 | bool TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size); | 106 | bool TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size); |
| @@ -117,15 +118,12 @@ private: | |||
| 117 | /// Returns index to the fastest memory type compatible with the passed requirements. | 118 | /// Returns index to the fastest memory type compatible with the passed requirements. |
| 118 | std::optional<u32> FindType(VkMemoryPropertyFlags flags, u32 type_mask) const; | 119 | std::optional<u32> FindType(VkMemoryPropertyFlags flags, u32 type_mask) const; |
| 119 | 120 | ||
| 120 | const Device& device; ///< Device handle. | 121 | const Device& device; ///< Device handle. |
| 121 | const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties. | 122 | VmaAllocator allocator; ///< Vma allocator. |
| 122 | const bool export_allocations; ///< True when memory allocations have to be exported. | 123 | const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties. |
| 123 | std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. | 124 | std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. |
| 124 | VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers | 125 | VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers |
| 125 | // and optimal images | 126 | // and optimal images |
| 126 | }; | 127 | }; |
| 127 | 128 | ||
| 128 | /// Returns true when a memory usage is guaranteed to be host visible. | ||
| 129 | bool IsHostVisible(MemoryUsage usage) noexcept; | ||
| 130 | |||
| 131 | } // 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 336f53700..28fcb21a0 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 14 | 14 | ||
| 15 | #include <vk_mem_alloc.h> | ||
| 16 | |||
| 15 | namespace Vulkan::vk { | 17 | namespace Vulkan::vk { |
| 16 | 18 | ||
| 17 | namespace { | 19 | namespace { |
| @@ -547,24 +549,40 @@ DebugUtilsMessenger Instance::CreateDebugUtilsMessenger( | |||
| 547 | return DebugUtilsMessenger(object, handle, *dld); | 549 | return DebugUtilsMessenger(object, handle, *dld); |
| 548 | } | 550 | } |
| 549 | 551 | ||
| 550 | void Buffer::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const { | 552 | void Image::SetObjectNameEXT(const char* name) const { |
| 551 | Check(dld->vkBindBufferMemory(owner, handle, memory, offset)); | 553 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name); |
| 552 | } | 554 | } |
| 553 | 555 | ||
| 554 | void Buffer::SetObjectNameEXT(const char* name) const { | 556 | void Image::Release() const noexcept { |
| 555 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER, name); | 557 | if (handle) { |
| 558 | vmaDestroyImage(allocator, handle, allocation); | ||
| 559 | } | ||
| 556 | } | 560 | } |
| 557 | 561 | ||
| 558 | void BufferView::SetObjectNameEXT(const char* name) const { | 562 | void Buffer::Flush() const { |
| 559 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER_VIEW, name); | 563 | if (!is_coherent) { |
| 564 | vmaFlushAllocation(allocator, allocation, 0, VK_WHOLE_SIZE); | ||
| 565 | } | ||
| 560 | } | 566 | } |
| 561 | 567 | ||
| 562 | void Image::BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const { | 568 | void Buffer::Invalidate() const { |
| 563 | Check(dld->vkBindImageMemory(owner, handle, memory, offset)); | 569 | if (!is_coherent) { |
| 570 | vmaInvalidateAllocation(allocator, allocation, 0, VK_WHOLE_SIZE); | ||
| 571 | } | ||
| 564 | } | 572 | } |
| 565 | 573 | ||
| 566 | void Image::SetObjectNameEXT(const char* name) const { | 574 | void Buffer::SetObjectNameEXT(const char* name) const { |
| 567 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name); | 575 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER, name); |
| 576 | } | ||
| 577 | |||
| 578 | void Buffer::Release() const noexcept { | ||
| 579 | if (handle) { | ||
| 580 | vmaDestroyBuffer(allocator, handle, allocation); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 584 | void BufferView::SetObjectNameEXT(const char* name) const { | ||
| 585 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_BUFFER_VIEW, name); | ||
| 568 | } | 586 | } |
| 569 | 587 | ||
| 570 | void ImageView::SetObjectNameEXT(const char* name) const { | 588 | void ImageView::SetObjectNameEXT(const char* name) const { |
| @@ -701,24 +719,12 @@ Queue Device::GetQueue(u32 family_index) const noexcept { | |||
| 701 | return Queue(queue, *dld); | 719 | return Queue(queue, *dld); |
| 702 | } | 720 | } |
| 703 | 721 | ||
| 704 | Buffer Device::CreateBuffer(const VkBufferCreateInfo& ci) const { | ||
| 705 | VkBuffer object; | ||
| 706 | Check(dld->vkCreateBuffer(handle, &ci, nullptr, &object)); | ||
| 707 | return Buffer(object, handle, *dld); | ||
| 708 | } | ||
| 709 | |||
| 710 | BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const { | 722 | BufferView Device::CreateBufferView(const VkBufferViewCreateInfo& ci) const { |
| 711 | VkBufferView object; | 723 | VkBufferView object; |
| 712 | Check(dld->vkCreateBufferView(handle, &ci, nullptr, &object)); | 724 | Check(dld->vkCreateBufferView(handle, &ci, nullptr, &object)); |
| 713 | return BufferView(object, handle, *dld); | 725 | return BufferView(object, handle, *dld); |
| 714 | } | 726 | } |
| 715 | 727 | ||
| 716 | Image Device::CreateImage(const VkImageCreateInfo& ci) const { | ||
| 717 | VkImage object; | ||
| 718 | Check(dld->vkCreateImage(handle, &ci, nullptr, &object)); | ||
| 719 | return Image(object, handle, *dld); | ||
| 720 | } | ||
| 721 | |||
| 722 | ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const { | 728 | ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const { |
| 723 | VkImageView object; | 729 | VkImageView object; |
| 724 | Check(dld->vkCreateImageView(handle, &ci, nullptr, &object)); | 730 | Check(dld->vkCreateImageView(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 4ff328a21..44fce47a5 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -32,6 +32,9 @@ | |||
| 32 | #pragma warning(disable : 26812) // Disable prefer enum class over enum | 32 | #pragma warning(disable : 26812) // Disable prefer enum class over enum |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | VK_DEFINE_HANDLE(VmaAllocator) | ||
| 36 | VK_DEFINE_HANDLE(VmaAllocation) | ||
| 37 | |||
| 35 | namespace Vulkan::vk { | 38 | namespace Vulkan::vk { |
| 36 | 39 | ||
| 37 | /** | 40 | /** |
| @@ -616,6 +619,138 @@ public: | |||
| 616 | } | 619 | } |
| 617 | }; | 620 | }; |
| 618 | 621 | ||
| 622 | class Image { | ||
| 623 | public: | ||
| 624 | explicit Image(VkImage handle_, VkDevice owner_, VmaAllocator allocator_, | ||
| 625 | VmaAllocation allocation_, const DeviceDispatch& dld_) noexcept | ||
| 626 | : handle{handle_}, owner{owner_}, allocator{allocator_}, | ||
| 627 | allocation{allocation_}, dld{&dld_} {} | ||
| 628 | Image() = default; | ||
| 629 | |||
| 630 | Image(const Image&) = delete; | ||
| 631 | Image& operator=(const Image&) = delete; | ||
| 632 | |||
| 633 | Image(Image&& rhs) noexcept | ||
| 634 | : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, allocator{rhs.allocator}, | ||
| 635 | allocation{rhs.allocation}, dld{rhs.dld} {} | ||
| 636 | |||
| 637 | Image& operator=(Image&& rhs) noexcept { | ||
| 638 | Release(); | ||
| 639 | handle = std::exchange(rhs.handle, nullptr); | ||
| 640 | owner = rhs.owner; | ||
| 641 | allocator = rhs.allocator; | ||
| 642 | allocation = rhs.allocation; | ||
| 643 | dld = rhs.dld; | ||
| 644 | return *this; | ||
| 645 | } | ||
| 646 | |||
| 647 | ~Image() noexcept { | ||
| 648 | Release(); | ||
| 649 | } | ||
| 650 | |||
| 651 | VkImage operator*() const noexcept { | ||
| 652 | return handle; | ||
| 653 | } | ||
| 654 | |||
| 655 | void reset() noexcept { | ||
| 656 | Release(); | ||
| 657 | handle = nullptr; | ||
| 658 | } | ||
| 659 | |||
| 660 | explicit operator bool() const noexcept { | ||
| 661 | return handle != nullptr; | ||
| 662 | } | ||
| 663 | |||
| 664 | void SetObjectNameEXT(const char* name) const; | ||
| 665 | |||
| 666 | private: | ||
| 667 | void Release() const noexcept; | ||
| 668 | |||
| 669 | VkImage handle = nullptr; | ||
| 670 | VkDevice owner = nullptr; | ||
| 671 | VmaAllocator allocator = nullptr; | ||
| 672 | VmaAllocation allocation = nullptr; | ||
| 673 | const DeviceDispatch* dld = nullptr; | ||
| 674 | }; | ||
| 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 | |||
| 619 | class Queue { | 754 | class Queue { |
| 620 | public: | 755 | public: |
| 621 | /// Construct an empty queue handle. | 756 | /// Construct an empty queue handle. |
| @@ -639,17 +774,6 @@ private: | |||
| 639 | const DeviceDispatch* dld = nullptr; | 774 | const DeviceDispatch* dld = nullptr; |
| 640 | }; | 775 | }; |
| 641 | 776 | ||
| 642 | class Buffer : public Handle<VkBuffer, VkDevice, DeviceDispatch> { | ||
| 643 | using Handle<VkBuffer, VkDevice, DeviceDispatch>::Handle; | ||
| 644 | |||
| 645 | public: | ||
| 646 | /// Attaches a memory allocation. | ||
| 647 | void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const; | ||
| 648 | |||
| 649 | /// Set object name. | ||
| 650 | void SetObjectNameEXT(const char* name) const; | ||
| 651 | }; | ||
| 652 | |||
| 653 | class BufferView : public Handle<VkBufferView, VkDevice, DeviceDispatch> { | 777 | class BufferView : public Handle<VkBufferView, VkDevice, DeviceDispatch> { |
| 654 | using Handle<VkBufferView, VkDevice, DeviceDispatch>::Handle; | 778 | using Handle<VkBufferView, VkDevice, DeviceDispatch>::Handle; |
| 655 | 779 | ||
| @@ -658,17 +782,6 @@ public: | |||
| 658 | void SetObjectNameEXT(const char* name) const; | 782 | void SetObjectNameEXT(const char* name) const; |
| 659 | }; | 783 | }; |
| 660 | 784 | ||
| 661 | class Image : public Handle<VkImage, VkDevice, DeviceDispatch> { | ||
| 662 | using Handle<VkImage, VkDevice, DeviceDispatch>::Handle; | ||
| 663 | |||
| 664 | public: | ||
| 665 | /// Attaches a memory allocation. | ||
| 666 | void BindMemory(VkDeviceMemory memory, VkDeviceSize offset) const; | ||
| 667 | |||
| 668 | /// Set object name. | ||
| 669 | void SetObjectNameEXT(const char* name) const; | ||
| 670 | }; | ||
| 671 | |||
| 672 | class ImageView : public Handle<VkImageView, VkDevice, DeviceDispatch> { | 785 | class ImageView : public Handle<VkImageView, VkDevice, DeviceDispatch> { |
| 673 | using Handle<VkImageView, VkDevice, DeviceDispatch>::Handle; | 786 | using Handle<VkImageView, VkDevice, DeviceDispatch>::Handle; |
| 674 | 787 | ||
| @@ -840,12 +953,8 @@ public: | |||
| 840 | 953 | ||
| 841 | Queue GetQueue(u32 family_index) const noexcept; | 954 | Queue GetQueue(u32 family_index) const noexcept; |
| 842 | 955 | ||
| 843 | Buffer CreateBuffer(const VkBufferCreateInfo& ci) const; | ||
| 844 | |||
| 845 | BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const; | 956 | BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const; |
| 846 | 957 | ||
| 847 | Image CreateImage(const VkImageCreateInfo& ci) const; | ||
| 848 | |||
| 849 | ImageView CreateImageView(const VkImageViewCreateInfo& ci) const; | 958 | ImageView CreateImageView(const VkImageViewCreateInfo& ci) const; |
| 850 | 959 | ||
| 851 | Semaphore CreateSemaphore() const; | 960 | Semaphore CreateSemaphore() const; |