diff options
| author | 2023-07-01 15:01:11 -0700 | |
|---|---|---|
| committer | 2023-07-01 15:01:11 -0700 | |
| commit | 98685d48e3cb9f25f6919f004ec62cadf33afad2 (patch) | |
| tree | 9df2ce7f57370641589bfae7196c77b090bcbe0f /src/video_core/renderer_vulkan | |
| parent | PR feedback + constification (diff) | |
| parent | Update translations (2023-07-01) (#10972) (diff) | |
| download | yuzu-98685d48e3cb9f25f6919f004ec62cadf33afad2.tar.gz yuzu-98685d48e3cb9f25f6919f004ec62cadf33afad2.tar.xz yuzu-98685d48e3cb9f25f6919f004ec62cadf33afad2.zip | |
Merge remote-tracking branch 'origin/master' into ssl
Diffstat (limited to 'src/video_core/renderer_vulkan')
24 files changed, 215 insertions, 266 deletions
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index cf2964a3f..28d4b15a0 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -495,6 +495,9 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | |||
| 495 | const Region2D& dst_region, const Region2D& src_region, | 495 | const Region2D& dst_region, const Region2D& src_region, |
| 496 | Tegra::Engines::Fermi2D::Filter filter, | 496 | Tegra::Engines::Fermi2D::Filter filter, |
| 497 | Tegra::Engines::Fermi2D::Operation operation) { | 497 | Tegra::Engines::Fermi2D::Operation operation) { |
| 498 | if (!device.IsExtShaderStencilExportSupported()) { | ||
| 499 | return; | ||
| 500 | } | ||
| 498 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); | 501 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); |
| 499 | ASSERT(operation == Tegra::Engines::Fermi2D::Operation::SrcCopy); | 502 | ASSERT(operation == Tegra::Engines::Fermi2D::Operation::SrcCopy); |
| 500 | const BlitImagePipelineKey key{ | 503 | const BlitImagePipelineKey key{ |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 9a0b10568..a8540339d 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -259,6 +259,26 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with | |||
| 259 | break; | 259 | break; |
| 260 | } | 260 | } |
| 261 | } | 261 | } |
| 262 | // Transcode on hardware that doesn't support BCn natively | ||
| 263 | if (!device.IsOptimalBcnSupported() && VideoCore::Surface::IsPixelFormatBCn(pixel_format)) { | ||
| 264 | const bool is_srgb = with_srgb && VideoCore::Surface::IsPixelFormatSRGB(pixel_format); | ||
| 265 | if (pixel_format == PixelFormat::BC4_SNORM) { | ||
| 266 | tuple.format = VK_FORMAT_R8_SNORM; | ||
| 267 | } else if (pixel_format == PixelFormat::BC4_UNORM) { | ||
| 268 | tuple.format = VK_FORMAT_R8_UNORM; | ||
| 269 | } else if (pixel_format == PixelFormat::BC5_SNORM) { | ||
| 270 | tuple.format = VK_FORMAT_R8G8_SNORM; | ||
| 271 | } else if (pixel_format == PixelFormat::BC5_UNORM) { | ||
| 272 | tuple.format = VK_FORMAT_R8G8_UNORM; | ||
| 273 | } else if (pixel_format == PixelFormat::BC6H_SFLOAT || | ||
| 274 | pixel_format == PixelFormat::BC6H_UFLOAT) { | ||
| 275 | tuple.format = VK_FORMAT_R16G16B16A16_SFLOAT; | ||
| 276 | } else if (is_srgb) { | ||
| 277 | tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32; | ||
| 278 | } else { | ||
| 279 | tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32; | ||
| 280 | } | ||
| 281 | } | ||
| 262 | const bool attachable = (tuple.usage & Attachable) != 0; | 282 | const bool attachable = (tuple.usage & Attachable) != 0; |
| 263 | const bool storage = (tuple.usage & Storage) != 0; | 283 | const bool storage = (tuple.usage & Storage) != 0; |
| 264 | 284 | ||
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 77128c6e2..454bb66a4 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <fmt/format.h> | 12 | #include <fmt/format.h> |
| 13 | 13 | ||
| 14 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | #include "common/scope_exit.h" | 16 | #include "common/scope_exit.h" |
| 16 | #include "common/settings.h" | 17 | #include "common/settings.h" |
| 17 | #include "common/telemetry.h" | 18 | #include "common/telemetry.h" |
| @@ -65,6 +66,21 @@ std::string BuildCommaSeparatedExtensions( | |||
| 65 | return fmt::format("{}", fmt::join(available_extensions, ",")); | 66 | return fmt::format("{}", fmt::join(available_extensions, ",")); |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 69 | DebugCallback MakeDebugCallback(const vk::Instance& instance, const vk::InstanceDispatch& dld) { | ||
| 70 | if (!Settings::values.renderer_debug) { | ||
| 71 | return DebugCallback{}; | ||
| 72 | } | ||
| 73 | const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld); | ||
| 74 | const auto it = std::ranges::find_if(*properties, [](const auto& prop) { | ||
| 75 | return std::strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, prop.extensionName) == 0; | ||
| 76 | }); | ||
| 77 | if (it != properties->end()) { | ||
| 78 | return CreateDebugUtilsCallback(instance); | ||
| 79 | } else { | ||
| 80 | return CreateDebugReportCallback(instance); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 68 | } // Anonymous namespace | 84 | } // Anonymous namespace |
| 69 | 85 | ||
| 70 | Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, | 86 | Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, |
| @@ -87,10 +103,10 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 87 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), | 103 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), |
| 88 | instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | 104 | instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, |
| 89 | Settings::values.renderer_debug.GetValue())), | 105 | Settings::values.renderer_debug.GetValue())), |
| 90 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | 106 | debug_callback(MakeDebugCallback(instance, dld)), |
| 91 | surface(CreateSurface(instance, render_window.GetWindowInfo())), | 107 | surface(CreateSurface(instance, render_window.GetWindowInfo())), |
| 92 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device, false), | 108 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(), |
| 93 | state_tracker(), scheduler(device, state_tracker), | 109 | scheduler(device, state_tracker), |
| 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | 110 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, |
| 95 | render_window.GetFramebufferLayout().height, false), | 111 | render_window.GetFramebufferLayout().height, false), |
| 96 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, | 112 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, |
| @@ -173,7 +189,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 173 | return; | 189 | return; |
| 174 | } | 190 | } |
| 175 | const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; | 191 | const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; |
| 176 | vk::Image staging_image = device.GetLogical().CreateImage(VkImageCreateInfo{ | 192 | vk::Image staging_image = memory_allocator.CreateImage(VkImageCreateInfo{ |
| 177 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 193 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| 178 | .pNext = nullptr, | 194 | .pNext = nullptr, |
| 179 | .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, | 195 | .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| @@ -196,7 +212,6 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 196 | .pQueueFamilyIndices = nullptr, | 212 | .pQueueFamilyIndices = nullptr, |
| 197 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 213 | .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, |
| 198 | }); | 214 | }); |
| 199 | const auto image_commit = memory_allocator.Commit(staging_image, MemoryUsage::DeviceLocal); | ||
| 200 | 215 | ||
| 201 | const vk::ImageView dst_view = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | 216 | const vk::ImageView dst_view = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ |
| 202 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 217 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| @@ -234,8 +249,8 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 234 | .queueFamilyIndexCount = 0, | 249 | .queueFamilyIndexCount = 0, |
| 235 | .pQueueFamilyIndices = nullptr, | 250 | .pQueueFamilyIndices = nullptr, |
| 236 | }; | 251 | }; |
| 237 | const vk::Buffer dst_buffer = device.GetLogical().CreateBuffer(dst_buffer_info); | 252 | const vk::Buffer dst_buffer = |
| 238 | MemoryCommit dst_buffer_memory = memory_allocator.Commit(dst_buffer, MemoryUsage::Download); | 253 | memory_allocator.CreateBuffer(dst_buffer_info, MemoryUsage::Download); |
| 239 | 254 | ||
| 240 | scheduler.RequestOutsideRenderPassOperationContext(); | 255 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 241 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { | 256 | scheduler.Record([&](vk::CommandBuffer cmdbuf) { |
| @@ -309,8 +324,9 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr | |||
| 309 | scheduler.Finish(); | 324 | scheduler.Finish(); |
| 310 | 325 | ||
| 311 | // Copy backing image data to the QImage screenshot buffer | 326 | // Copy backing image data to the QImage screenshot buffer |
| 312 | const auto dst_memory_map = dst_buffer_memory.Map(); | 327 | dst_buffer.Invalidate(); |
| 313 | std::memcpy(renderer_settings.screenshot_bits, dst_memory_map.data(), dst_memory_map.size()); | 328 | std::memcpy(renderer_settings.screenshot_bits, dst_buffer.Mapped().data(), |
| 329 | dst_buffer.Mapped().size()); | ||
| 314 | renderer_settings.screenshot_complete_callback(false); | 330 | renderer_settings.screenshot_complete_callback(false); |
| 315 | renderer_settings.screenshot_requested = false; | 331 | renderer_settings.screenshot_requested = false; |
| 316 | } | 332 | } |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index b2e8cbd1b..ca22c0baa 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <variant> | ||
| 8 | 9 | ||
| 9 | #include "common/dynamic_library.h" | 10 | #include "common/dynamic_library.h" |
| 10 | #include "video_core/renderer_base.h" | 11 | #include "video_core/renderer_base.h" |
| @@ -33,6 +34,8 @@ class GPU; | |||
| 33 | 34 | ||
| 34 | namespace Vulkan { | 35 | namespace Vulkan { |
| 35 | 36 | ||
| 37 | using DebugCallback = std::variant<vk::DebugUtilsMessenger, vk::DebugReportCallback>; | ||
| 38 | |||
| 36 | Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, | 39 | Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, |
| 37 | VkSurfaceKHR surface); | 40 | VkSurfaceKHR surface); |
| 38 | 41 | ||
| @@ -71,7 +74,7 @@ private: | |||
| 71 | vk::InstanceDispatch dld; | 74 | vk::InstanceDispatch dld; |
| 72 | 75 | ||
| 73 | vk::Instance instance; | 76 | vk::Instance instance; |
| 74 | vk::DebugUtilsMessenger debug_callback; | 77 | DebugCallback debug_callback; |
| 75 | vk::SurfaceKHR surface; | 78 | vk::SurfaceKHR surface; |
| 76 | 79 | ||
| 77 | ScreenInfo screen_info; | 80 | ScreenInfo screen_info; |
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 e30fcb1ed..b72f95235 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) { |
| @@ -361,7 +373,7 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer, | |||
| 361 | .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, | 373 | .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, |
| 362 | }; | 374 | }; |
| 363 | // Measuring a popular game, this number never exceeds the specified size once data is warmed up | 375 | // Measuring a popular game, this number never exceeds the specified size once data is warmed up |
| 364 | boost::container::small_vector<VkBufferCopy, 3> vk_copies(copies.size()); | 376 | boost::container::small_vector<VkBufferCopy, 8> vk_copies(copies.size()); |
| 365 | std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy); | 377 | std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy); |
| 366 | scheduler.RequestOutsideRenderPassOperationContext(); | 378 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 367 | scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) { | 379 | scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) { |
| @@ -578,7 +590,8 @@ void BufferCacheRuntime::ReserveNullBuffer() { | |||
| 578 | .pNext = nullptr, | 590 | .pNext = nullptr, |
| 579 | .flags = 0, | 591 | .flags = 0, |
| 580 | .size = 4, | 592 | .size = 4, |
| 581 | .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, | 593 | .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | |
| 594 | VK_BUFFER_USAGE_TRANSFER_DST_BIT, | ||
| 582 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 595 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 583 | .queueFamilyIndexCount = 0, | 596 | .queueFamilyIndexCount = 0, |
| 584 | .pQueueFamilyIndices = nullptr, | 597 | .pQueueFamilyIndices = nullptr, |
| @@ -587,11 +600,10 @@ void BufferCacheRuntime::ReserveNullBuffer() { | |||
| 587 | create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; | 600 | create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; |
| 588 | } | 601 | } |
| 589 | create_info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; | 602 | create_info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; |
| 590 | null_buffer = device.GetLogical().CreateBuffer(create_info); | 603 | null_buffer = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal); |
| 591 | if (device.HasDebuggingToolAttached()) { | 604 | if (device.HasDebuggingToolAttached()) { |
| 592 | null_buffer.SetObjectNameEXT("Null buffer"); | 605 | null_buffer.SetObjectNameEXT("Null buffer"); |
| 593 | } | 606 | } |
| 594 | null_buffer_commit = memory_allocator.Commit(null_buffer, MemoryUsage::DeviceLocal); | ||
| 595 | 607 | ||
| 596 | scheduler.RequestOutsideRenderPassOperationContext(); | 608 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 597 | scheduler.Record([buffer = *null_buffer](vk::CommandBuffer cmdbuf) { | 609 | 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_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index c1595642e..ad35cacac 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -652,13 +652,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 652 | .pNext = nullptr, | 652 | .pNext = nullptr, |
| 653 | .negativeOneToOne = key.state.ndc_minus_one_to_one.Value() != 0 ? VK_TRUE : VK_FALSE, | 653 | .negativeOneToOne = key.state.ndc_minus_one_to_one.Value() != 0 ? VK_TRUE : VK_FALSE, |
| 654 | }; | 654 | }; |
| 655 | const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports); | ||
| 655 | VkPipelineViewportStateCreateInfo viewport_ci{ | 656 | VkPipelineViewportStateCreateInfo viewport_ci{ |
| 656 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, | 657 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, |
| 657 | .pNext = nullptr, | 658 | .pNext = nullptr, |
| 658 | .flags = 0, | 659 | .flags = 0, |
| 659 | .viewportCount = Maxwell::NumViewports, | 660 | .viewportCount = num_viewports, |
| 660 | .pViewports = nullptr, | 661 | .pViewports = nullptr, |
| 661 | .scissorCount = Maxwell::NumViewports, | 662 | .scissorCount = num_viewports, |
| 662 | .pScissors = nullptr, | 663 | .pScissors = nullptr, |
| 663 | }; | 664 | }; |
| 664 | if (device.IsNvViewportSwizzleSupported()) { | 665 | if (device.IsNvViewportSwizzleSupported()) { |
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index 5eeda08d2..6b288b994 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp | |||
| @@ -75,15 +75,9 @@ void MasterSemaphore::Refresh() { | |||
| 75 | 75 | ||
| 76 | void MasterSemaphore::Wait(u64 tick) { | 76 | void MasterSemaphore::Wait(u64 tick) { |
| 77 | if (!semaphore) { | 77 | if (!semaphore) { |
| 78 | // If we don't support timeline semaphores, use an atomic wait | 78 | // If we don't support timeline semaphores, wait for the value normally |
| 79 | while (true) { | 79 | std::unique_lock lk{free_mutex}; |
| 80 | u64 current_value = gpu_tick.load(std::memory_order_relaxed); | 80 | free_cv.wait(lk, [&] { return gpu_tick.load(std::memory_order_relaxed) >= tick; }); |
| 81 | if (current_value >= tick) { | ||
| 82 | return; | ||
| 83 | } | ||
| 84 | gpu_tick.wait(current_value); | ||
| 85 | } | ||
| 86 | |||
| 87 | return; | 81 | return; |
| 88 | } | 82 | } |
| 89 | 83 | ||
| @@ -198,11 +192,13 @@ void MasterSemaphore::WaitThread(std::stop_token token) { | |||
| 198 | 192 | ||
| 199 | fence.Wait(); | 193 | fence.Wait(); |
| 200 | fence.Reset(); | 194 | fence.Reset(); |
| 201 | gpu_tick.store(host_tick); | ||
| 202 | gpu_tick.notify_all(); | ||
| 203 | 195 | ||
| 204 | std::scoped_lock lock{free_mutex}; | 196 | { |
| 205 | free_queue.push_front(std::move(fence)); | 197 | std::scoped_lock lock{free_mutex}; |
| 198 | free_queue.push_front(std::move(fence)); | ||
| 199 | gpu_tick.store(host_tick); | ||
| 200 | } | ||
| 201 | free_cv.notify_one(); | ||
| 206 | } | 202 | } |
| 207 | } | 203 | } |
| 208 | 204 | ||
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h index 1e7c90215..3f599d7bd 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.h +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h | |||
| @@ -72,6 +72,7 @@ private: | |||
| 72 | std::atomic<u64> current_tick{1}; ///< Current logical tick. | 72 | std::atomic<u64> current_tick{1}; ///< Current logical tick. |
| 73 | std::mutex wait_mutex; | 73 | std::mutex wait_mutex; |
| 74 | std::mutex free_mutex; | 74 | std::mutex free_mutex; |
| 75 | std::condition_variable free_cv; | ||
| 75 | std::condition_variable_any wait_cv; | 76 | std::condition_variable_any wait_cv; |
| 76 | std::queue<Waitable> wait_queue; ///< Queue for the fences to be waited on by the wait thread. | 77 | std::queue<Waitable> wait_queue; ///< Queue for the fences to be waited on by the wait thread. |
| 77 | std::deque<vk::Fence> free_queue; ///< Holds available fences for submission. | 78 | std::deque<vk::Fence> free_queue; ///< Holds available fences for submission. |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 18e040a1b..d600c4e61 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -167,7 +167,10 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program | |||
| 167 | info.fixed_state_point_size = point_size; | 167 | info.fixed_state_point_size = point_size; |
| 168 | } | 168 | } |
| 169 | if (key.state.xfb_enabled) { | 169 | if (key.state.xfb_enabled) { |
| 170 | info.xfb_varyings = VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state); | 170 | auto [varyings, count] = |
| 171 | VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state); | ||
| 172 | info.xfb_varyings = varyings; | ||
| 173 | info.xfb_count = count; | ||
| 171 | } | 174 | } |
| 172 | info.convert_depth_mode = gl_ndc; | 175 | info.convert_depth_mode = gl_ndc; |
| 173 | } | 176 | } |
| @@ -214,7 +217,10 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program | |||
| 214 | info.fixed_state_point_size = point_size; | 217 | info.fixed_state_point_size = point_size; |
| 215 | } | 218 | } |
| 216 | if (key.state.xfb_enabled != 0) { | 219 | if (key.state.xfb_enabled != 0) { |
| 217 | info.xfb_varyings = VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state); | 220 | auto [varyings, count] = |
| 221 | VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state); | ||
| 222 | info.xfb_varyings = varyings; | ||
| 223 | info.xfb_count = count; | ||
| 218 | } | 224 | } |
| 219 | info.convert_depth_mode = gl_ndc; | 225 | info.convert_depth_mode = gl_ndc; |
| 220 | break; | 226 | break; |
| @@ -303,7 +309,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 303 | .support_int16 = device.IsShaderInt16Supported(), | 309 | .support_int16 = device.IsShaderInt16Supported(), |
| 304 | .support_int64 = device.IsShaderInt64Supported(), | 310 | .support_int64 = device.IsShaderInt64Supported(), |
| 305 | .support_vertex_instance_id = false, | 311 | .support_vertex_instance_id = false, |
| 306 | .support_float_controls = true, | 312 | .support_float_controls = device.IsKhrShaderFloatControlsSupported(), |
| 307 | .support_separate_denorm_behavior = | 313 | .support_separate_denorm_behavior = |
| 308 | float_control.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, | 314 | float_control.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, |
| 309 | .support_separate_rounding_mode = | 315 | .support_separate_rounding_mode = |
| @@ -319,12 +325,13 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 319 | .support_fp64_signed_zero_nan_preserve = | 325 | .support_fp64_signed_zero_nan_preserve = |
| 320 | float_control.shaderSignedZeroInfNanPreserveFloat64 != VK_FALSE, | 326 | float_control.shaderSignedZeroInfNanPreserveFloat64 != VK_FALSE, |
| 321 | .support_explicit_workgroup_layout = device.IsKhrWorkgroupMemoryExplicitLayoutSupported(), | 327 | .support_explicit_workgroup_layout = device.IsKhrWorkgroupMemoryExplicitLayoutSupported(), |
| 322 | .support_vote = true, | 328 | .support_vote = device.IsSubgroupFeatureSupported(VK_SUBGROUP_FEATURE_VOTE_BIT), |
| 323 | .support_viewport_index_layer_non_geometry = | 329 | .support_viewport_index_layer_non_geometry = |
| 324 | device.IsExtShaderViewportIndexLayerSupported(), | 330 | device.IsExtShaderViewportIndexLayerSupported(), |
| 325 | .support_viewport_mask = device.IsNvViewportArray2Supported(), | 331 | .support_viewport_mask = device.IsNvViewportArray2Supported(), |
| 326 | .support_typeless_image_loads = device.IsFormatlessImageLoadSupported(), | 332 | .support_typeless_image_loads = device.IsFormatlessImageLoadSupported(), |
| 327 | .support_demote_to_helper_invocation = true, | 333 | .support_demote_to_helper_invocation = |
| 334 | device.IsExtShaderDemoteToHelperInvocationSupported(), | ||
| 328 | .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), | 335 | .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), |
| 329 | .support_derivative_control = true, | 336 | .support_derivative_control = true, |
| 330 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), | 337 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), |
| @@ -705,10 +712,7 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 705 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | 712 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( |
| 706 | ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, | 713 | ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, |
| 707 | PipelineStatistics* statistics, bool build_in_parallel) try { | 714 | PipelineStatistics* statistics, bool build_in_parallel) try { |
| 708 | // TODO: Remove this when Intel fixes their shader compiler. | 715 | if (device.HasBrokenCompute()) { |
| 709 | // https://github.com/IGCIT/Intel-GPU-Community-Issue-Tracker-IGCIT/issues/159 | ||
| 710 | if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS && | ||
| 711 | !Settings::values.enable_compute_pipelines.GetValue()) { | ||
| 712 | LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash()); | 716 | LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash()); |
| 713 | return nullptr; | 717 | return nullptr; |
| 714 | } | 718 | } |
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_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 84e3a30cc..f7c0d939a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -315,7 +315,14 @@ void RasterizerVulkan::Clear(u32 layer_count) { | |||
| 315 | FlushWork(); | 315 | FlushWork(); |
| 316 | gpu_memory->FlushCaching(); | 316 | gpu_memory->FlushCaching(); |
| 317 | 317 | ||
| 318 | #if ANDROID | ||
| 319 | if (Settings::IsGPULevelHigh()) { | ||
| 320 | // This is problematic on Android, disable on GPU Normal. | ||
| 321 | query_cache.UpdateCounters(); | ||
| 322 | } | ||
| 323 | #else | ||
| 318 | query_cache.UpdateCounters(); | 324 | query_cache.UpdateCounters(); |
| 325 | #endif | ||
| 319 | 326 | ||
| 320 | auto& regs = maxwell3d->regs; | 327 | auto& regs = maxwell3d->regs; |
| 321 | const bool use_color = regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B || | 328 | const bool use_color = regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B || |
| @@ -925,7 +932,7 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg | |||
| 925 | } | 932 | } |
| 926 | const bool is_rescaling{texture_cache.IsRescaling()}; | 933 | const bool is_rescaling{texture_cache.IsRescaling()}; |
| 927 | const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; | 934 | const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; |
| 928 | const std::array viewports{ | 935 | const std::array viewport_list{ |
| 929 | GetViewportState(device, regs, 0, scale), GetViewportState(device, regs, 1, scale), | 936 | GetViewportState(device, regs, 0, scale), GetViewportState(device, regs, 1, scale), |
| 930 | GetViewportState(device, regs, 2, scale), GetViewportState(device, regs, 3, scale), | 937 | GetViewportState(device, regs, 2, scale), GetViewportState(device, regs, 3, scale), |
| 931 | GetViewportState(device, regs, 4, scale), GetViewportState(device, regs, 5, scale), | 938 | GetViewportState(device, regs, 4, scale), GetViewportState(device, regs, 5, scale), |
| @@ -935,7 +942,11 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg | |||
| 935 | GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale), | 942 | GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale), |
| 936 | GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), | 943 | GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), |
| 937 | }; | 944 | }; |
| 938 | scheduler.Record([viewports](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewports); }); | 945 | scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) { |
| 946 | const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports); | ||
| 947 | const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports); | ||
| 948 | cmdbuf.SetViewport(0, viewports); | ||
| 949 | }); | ||
| 939 | } | 950 | } |
| 940 | 951 | ||
| 941 | void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs) { | 952 | void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs) { |
| @@ -948,7 +959,7 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs | |||
| 948 | up_scale = Settings::values.resolution_info.up_scale; | 959 | up_scale = Settings::values.resolution_info.up_scale; |
| 949 | down_shift = Settings::values.resolution_info.down_shift; | 960 | down_shift = Settings::values.resolution_info.down_shift; |
| 950 | } | 961 | } |
| 951 | const std::array scissors{ | 962 | const std::array scissor_list{ |
| 952 | GetScissorState(regs, 0, up_scale, down_shift), | 963 | GetScissorState(regs, 0, up_scale, down_shift), |
| 953 | GetScissorState(regs, 1, up_scale, down_shift), | 964 | GetScissorState(regs, 1, up_scale, down_shift), |
| 954 | GetScissorState(regs, 2, up_scale, down_shift), | 965 | GetScissorState(regs, 2, up_scale, down_shift), |
| @@ -966,7 +977,11 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs | |||
| 966 | GetScissorState(regs, 14, up_scale, down_shift), | 977 | GetScissorState(regs, 14, up_scale, down_shift), |
| 967 | GetScissorState(regs, 15, up_scale, down_shift), | 978 | GetScissorState(regs, 15, up_scale, down_shift), |
| 968 | }; | 979 | }; |
| 969 | scheduler.Record([scissors](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissors); }); | 980 | scheduler.Record([this, scissor_list](vk::CommandBuffer cmdbuf) { |
| 981 | const u32 num_scissors = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports); | ||
| 982 | const vk::Span<VkRect2D> scissors(scissor_list.data(), num_scissors); | ||
| 983 | cmdbuf.SetScissor(0, scissors); | ||
| 984 | }); | ||
| 970 | } | 985 | } |
| 971 | 986 | ||
| 972 | void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { | 987 | void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { |
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..ce92f66ab 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,58 +38,26 @@ 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 | 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, |
| 95 | .size = STREAM_BUFFER_SIZE, | 45 | .size = STREAM_BUFFER_SIZE, |
| 96 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | | 46 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | |
| 97 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | | 47 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, |
| 98 | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT, | ||
| 99 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 48 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 100 | .queueFamilyIndexCount = 0, | 49 | .queueFamilyIndexCount = 0, |
| 101 | .pQueueFamilyIndices = nullptr, | 50 | .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 | }; | 51 | }; |
| 121 | const auto memory_properties = device.GetPhysical().GetMemoryProperties().memoryProperties; | 52 | if (device.IsExtTransformFeedbackSupported()) { |
| 122 | VkMemoryAllocateInfo stream_memory_info{ | 53 | stream_ci.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; |
| 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 | } | 54 | } |
| 136 | 55 | stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream); | |
| 137 | if (device.HasDebuggingToolAttached()) { | 56 | if (device.HasDebuggingToolAttached()) { |
| 138 | stream_memory.SetObjectNameEXT("Stream Buffer Memory"); | 57 | stream_buffer.SetObjectNameEXT("Stream Buffer"); |
| 139 | } | 58 | } |
| 140 | stream_buffer.BindMemory(*stream_memory, 0); | 59 | stream_pointer = stream_buffer.Mapped(); |
| 141 | stream_pointer = stream_memory.Map(0, STREAM_BUFFER_SIZE); | 60 | ASSERT_MSG(!stream_pointer.empty(), "Stream buffer must be host visible!"); |
| 142 | } | 61 | } |
| 143 | 62 | ||
| 144 | StagingBufferPool::~StagingBufferPool() = default; | 63 | StagingBufferPool::~StagingBufferPool() = default; |
| @@ -199,7 +118,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { | |||
| 199 | return StagingBufferRef{ | 118 | return StagingBufferRef{ |
| 200 | .buffer = *stream_buffer, | 119 | .buffer = *stream_buffer, |
| 201 | .offset = static_cast<VkDeviceSize>(offset), | 120 | .offset = static_cast<VkDeviceSize>(offset), |
| 202 | .mapped_span = std::span<u8>(stream_pointer + offset, size), | 121 | .mapped_span = stream_pointer.subspan(offset, size), |
| 203 | .usage{}, | 122 | .usage{}, |
| 204 | .log2_level{}, | 123 | .log2_level{}, |
| 205 | .index{}, | 124 | .index{}, |
| @@ -247,29 +166,29 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s | |||
| 247 | StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, | 166 | StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, |
| 248 | bool deferred) { | 167 | bool deferred) { |
| 249 | const u32 log2 = Common::Log2Ceil64(size); | 168 | const u32 log2 = Common::Log2Ceil64(size); |
| 250 | vk::Buffer buffer = device.GetLogical().CreateBuffer({ | 169 | VkBufferCreateInfo buffer_ci = { |
| 251 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 170 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 252 | .pNext = nullptr, | 171 | .pNext = nullptr, |
| 253 | .flags = 0, | 172 | .flags = 0, |
| 254 | .size = 1ULL << log2, | 173 | .size = 1ULL << log2, |
| 255 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | 174 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | |
| 256 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | | 175 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | |
| 257 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | | 176 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, |
| 258 | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT, | ||
| 259 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 177 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 260 | .queueFamilyIndexCount = 0, | 178 | .queueFamilyIndexCount = 0, |
| 261 | .pQueueFamilyIndices = nullptr, | 179 | .pQueueFamilyIndices = nullptr, |
| 262 | }); | 180 | }; |
| 181 | if (device.IsExtTransformFeedbackSupported()) { | ||
| 182 | buffer_ci.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; | ||
| 183 | } | ||
| 184 | vk::Buffer buffer = memory_allocator.CreateBuffer(buffer_ci, usage); | ||
| 263 | if (device.HasDebuggingToolAttached()) { | 185 | if (device.HasDebuggingToolAttached()) { |
| 264 | ++buffer_index; | 186 | ++buffer_index; |
| 265 | buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str()); | 187 | buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str()); |
| 266 | } | 188 | } |
| 267 | MemoryCommit commit = memory_allocator.Commit(buffer, usage); | 189 | 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{ | 190 | StagingBuffer& entry = GetCache(usage)[log2].entries.emplace_back(StagingBuffer{ |
| 271 | .buffer = std::move(buffer), | 191 | .buffer = std::move(buffer), |
| 272 | .commit = std::move(commit), | ||
| 273 | .mapped_span = mapped_span, | 192 | .mapped_span = mapped_span, |
| 274 | .usage = usage, | 193 | .usage = usage, |
| 275 | .log2_level = log2, | 194 | .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 f025f618b..8385b5509 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) { |
| @@ -330,9 +330,9 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 330 | }; | 330 | }; |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | [[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( | 333 | [[maybe_unused]] [[nodiscard]] boost::container::small_vector<VkBufferCopy, 16> |
| 334 | std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { | 334 | TransformBufferCopies(std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { |
| 335 | std::vector<VkBufferCopy> result(copies.size()); | 335 | boost::container::small_vector<VkBufferCopy, 16> result(copies.size()); |
| 336 | std::ranges::transform( | 336 | std::ranges::transform( |
| 337 | copies, result.begin(), [buffer_offset](const VideoCommon::BufferCopy& copy) { | 337 | copies, result.begin(), [buffer_offset](const VideoCommon::BufferCopy& copy) { |
| 338 | return VkBufferCopy{ | 338 | return VkBufferCopy{ |
| @@ -344,7 +344,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 344 | return result; | 344 | return result; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | [[nodiscard]] std::vector<VkBufferImageCopy> TransformBufferImageCopies( | 347 | [[nodiscard]] boost::container::small_vector<VkBufferImageCopy, 16> TransformBufferImageCopies( |
| 348 | std::span<const BufferImageCopy> copies, size_t buffer_offset, VkImageAspectFlags aspect_mask) { | 348 | std::span<const BufferImageCopy> copies, size_t buffer_offset, VkImageAspectFlags aspect_mask) { |
| 349 | struct Maker { | 349 | struct Maker { |
| 350 | VkBufferImageCopy operator()(const BufferImageCopy& copy) const { | 350 | VkBufferImageCopy operator()(const BufferImageCopy& copy) const { |
| @@ -377,14 +377,14 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 377 | VkImageAspectFlags aspect_mask; | 377 | VkImageAspectFlags aspect_mask; |
| 378 | }; | 378 | }; |
| 379 | if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | 379 | if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { |
| 380 | std::vector<VkBufferImageCopy> result(copies.size() * 2); | 380 | boost::container::small_vector<VkBufferImageCopy, 16> result(copies.size() * 2); |
| 381 | std::ranges::transform(copies, result.begin(), | 381 | std::ranges::transform(copies, result.begin(), |
| 382 | Maker{buffer_offset, VK_IMAGE_ASPECT_DEPTH_BIT}); | 382 | Maker{buffer_offset, VK_IMAGE_ASPECT_DEPTH_BIT}); |
| 383 | std::ranges::transform(copies, result.begin() + copies.size(), | 383 | std::ranges::transform(copies, result.begin() + copies.size(), |
| 384 | Maker{buffer_offset, VK_IMAGE_ASPECT_STENCIL_BIT}); | 384 | Maker{buffer_offset, VK_IMAGE_ASPECT_STENCIL_BIT}); |
| 385 | return result; | 385 | return result; |
| 386 | } else { | 386 | } else { |
| 387 | std::vector<VkBufferImageCopy> result(copies.size()); | 387 | boost::container::small_vector<VkBufferImageCopy, 16> result(copies.size()); |
| 388 | std::ranges::transform(copies, result.begin(), Maker{buffer_offset, aspect_mask}); | 388 | std::ranges::transform(copies, result.begin(), Maker{buffer_offset, aspect_mask}); |
| 389 | return result; | 389 | return result; |
| 390 | } | 390 | } |
| @@ -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 | ||
| @@ -867,8 +866,8 @@ void TextureCacheRuntime::BarrierFeedbackLoop() { | |||
| 867 | 866 | ||
| 868 | void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, | 867 | void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, |
| 869 | std::span<const VideoCommon::ImageCopy> copies) { | 868 | std::span<const VideoCommon::ImageCopy> copies) { |
| 870 | std::vector<VkBufferImageCopy> vk_in_copies(copies.size()); | 869 | boost::container::small_vector<VkBufferImageCopy, 16> vk_in_copies(copies.size()); |
| 871 | std::vector<VkBufferImageCopy> vk_out_copies(copies.size()); | 870 | boost::container::small_vector<VkBufferImageCopy, 16> vk_out_copies(copies.size()); |
| 872 | const VkImageAspectFlags src_aspect_mask = src.AspectMask(); | 871 | const VkImageAspectFlags src_aspect_mask = src.AspectMask(); |
| 873 | const VkImageAspectFlags dst_aspect_mask = dst.AspectMask(); | 872 | const VkImageAspectFlags dst_aspect_mask = dst.AspectMask(); |
| 874 | 873 | ||
| @@ -1157,7 +1156,7 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im | |||
| 1157 | 1156 | ||
| 1158 | void TextureCacheRuntime::CopyImage(Image& dst, Image& src, | 1157 | void TextureCacheRuntime::CopyImage(Image& dst, Image& src, |
| 1159 | std::span<const VideoCommon::ImageCopy> copies) { | 1158 | std::span<const VideoCommon::ImageCopy> copies) { |
| 1160 | std::vector<VkImageCopy> vk_copies(copies.size()); | 1159 | boost::container::small_vector<VkImageCopy, 16> vk_copies(copies.size()); |
| 1161 | const VkImageAspectFlags aspect_mask = dst.AspectMask(); | 1160 | const VkImageAspectFlags aspect_mask = dst.AspectMask(); |
| 1162 | ASSERT(aspect_mask == src.AspectMask()); | 1161 | ASSERT(aspect_mask == src.AspectMask()); |
| 1163 | 1162 | ||
| @@ -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()) { |
| @@ -1280,6 +1279,10 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu | |||
| 1280 | flags |= VideoCommon::ImageFlagBits::Converted; | 1279 | flags |= VideoCommon::ImageFlagBits::Converted; |
| 1281 | flags |= VideoCommon::ImageFlagBits::CostlyLoad; | 1280 | flags |= VideoCommon::ImageFlagBits::CostlyLoad; |
| 1282 | } | 1281 | } |
| 1282 | if (IsPixelFormatBCn(info.format) && !runtime->device.IsOptimalBcnSupported()) { | ||
| 1283 | flags |= VideoCommon::ImageFlagBits::Converted; | ||
| 1284 | flags |= VideoCommon::ImageFlagBits::CostlyLoad; | ||
| 1285 | } | ||
| 1283 | if (runtime->device.HasDebuggingToolAttached()) { | 1286 | if (runtime->device.HasDebuggingToolAttached()) { |
| 1284 | original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); | 1287 | original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); |
| 1285 | } | 1288 | } |
| @@ -1332,7 +1335,7 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset, | |||
| 1332 | ScaleDown(true); | 1335 | ScaleDown(true); |
| 1333 | } | 1336 | } |
| 1334 | scheduler->RequestOutsideRenderPassOperationContext(); | 1337 | scheduler->RequestOutsideRenderPassOperationContext(); |
| 1335 | std::vector vk_copies = TransformBufferImageCopies(copies, offset, aspect_mask); | 1338 | auto vk_copies = TransformBufferImageCopies(copies, offset, aspect_mask); |
| 1336 | const VkBuffer src_buffer = buffer; | 1339 | const VkBuffer src_buffer = buffer; |
| 1337 | const VkImage vk_image = *original_image; | 1340 | const VkImage vk_image = *original_image; |
| 1338 | const VkImageAspectFlags vk_aspect_mask = aspect_mask; | 1341 | const VkImageAspectFlags vk_aspect_mask = aspect_mask; |
| @@ -1367,8 +1370,9 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS | |||
| 1367 | if (is_rescaled) { | 1370 | if (is_rescaled) { |
| 1368 | ScaleDown(); | 1371 | ScaleDown(); |
| 1369 | } | 1372 | } |
| 1370 | boost::container::small_vector<VkBuffer, 1> buffers_vector{}; | 1373 | boost::container::small_vector<VkBuffer, 8> buffers_vector{}; |
| 1371 | boost::container::small_vector<std::vector<VkBufferImageCopy>, 1> vk_copies; | 1374 | boost::container::small_vector<boost::container::small_vector<VkBufferImageCopy, 16>, 8> |
| 1375 | vk_copies; | ||
| 1372 | for (size_t index = 0; index < buffers_span.size(); index++) { | 1376 | for (size_t index = 0; index < buffers_span.size(); index++) { |
| 1373 | buffers_vector.emplace_back(buffers_span[index]); | 1377 | buffers_vector.emplace_back(buffers_span[index]); |
| 1374 | vk_copies.emplace_back( | 1378 | vk_copies.emplace_back( |
| @@ -1467,9 +1471,7 @@ bool Image::ScaleUp(bool ignore) { | |||
| 1467 | auto scaled_info = info; | 1471 | auto scaled_info = info; |
| 1468 | scaled_info.size.width = scaled_width; | 1472 | scaled_info.size.width = scaled_width; |
| 1469 | scaled_info.size.height = scaled_height; | 1473 | scaled_info.size.height = scaled_height; |
| 1470 | scaled_image = MakeImage(runtime->device, scaled_info); | 1474 | scaled_image = MakeImage(runtime->device, runtime->memory_allocator, scaled_info); |
| 1471 | auto& allocator = runtime->memory_allocator; | ||
| 1472 | scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal)); | ||
| 1473 | ignore = false; | 1475 | ignore = false; |
| 1474 | } | 1476 | } |
| 1475 | current_image = *scaled_image; | 1477 | current_image = *scaled_image; |
| @@ -1858,7 +1860,7 @@ Framebuffer::~Framebuffer() = default; | |||
| 1858 | void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, | 1860 | void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, |
| 1859 | std::span<ImageView*, NUM_RT> color_buffers, | 1861 | std::span<ImageView*, NUM_RT> color_buffers, |
| 1860 | ImageView* depth_buffer, bool is_rescaled) { | 1862 | ImageView* depth_buffer, bool is_rescaled) { |
| 1861 | std::vector<VkImageView> attachments; | 1863 | boost::container::small_vector<VkImageView, NUM_RT + 1> attachments; |
| 1862 | RenderPassKey renderpass_key{}; | 1864 | RenderPassKey renderpass_key{}; |
| 1863 | s32 num_layers = 1; | 1865 | s32 num_layers = 1; |
| 1864 | 1866 | ||
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{ |