diff options
Diffstat (limited to 'src')
25 files changed, 325 insertions, 129 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 149e621f9..2eaded242 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -200,6 +200,7 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 200 | values.use_asynchronous_shaders.SetGlobal(true); | 200 | values.use_asynchronous_shaders.SetGlobal(true); |
| 201 | values.use_fast_gpu_time.SetGlobal(true); | 201 | values.use_fast_gpu_time.SetGlobal(true); |
| 202 | values.use_pessimistic_flushes.SetGlobal(true); | 202 | values.use_pessimistic_flushes.SetGlobal(true); |
| 203 | values.use_vulkan_driver_pipeline_cache.SetGlobal(true); | ||
| 203 | values.bg_red.SetGlobal(true); | 204 | values.bg_red.SetGlobal(true); |
| 204 | values.bg_green.SetGlobal(true); | 205 | values.bg_green.SetGlobal(true); |
| 205 | values.bg_blue.SetGlobal(true); | 206 | values.bg_blue.SetGlobal(true); |
diff --git a/src/common/settings.h b/src/common/settings.h index 5017951c5..d9e82087d 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -451,6 +451,8 @@ struct Values { | |||
| 451 | SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | 451 | SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; |
| 452 | SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | 452 | SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; |
| 453 | SwitchableSetting<bool> use_pessimistic_flushes{false, "use_pessimistic_flushes"}; | 453 | SwitchableSetting<bool> use_pessimistic_flushes{false, "use_pessimistic_flushes"}; |
| 454 | SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true, | ||
| 455 | "use_vulkan_driver_pipeline_cache"}; | ||
| 454 | 456 | ||
| 455 | SwitchableSetting<u8> bg_red{0, "bg_red"}; | 457 | SwitchableSetting<u8> bg_red{0, "bg_red"}; |
| 456 | SwitchableSetting<u8> bg_green{0, "bg_green"}; | 458 | SwitchableSetting<u8> bg_green{0, "bg_green"}; |
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index a5476e795..6272a4652 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -50,38 +50,6 @@ protected: | |||
| 50 | Maxwell3D& maxwell3d; | 50 | Maxwell3D& maxwell3d; |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | class HLE_DrawArrays final : public HLEMacroImpl { | ||
| 54 | public: | ||
| 55 | explicit HLE_DrawArrays(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 56 | |||
| 57 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 58 | maxwell3d.RefreshParameters(); | ||
| 59 | |||
| 60 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); | ||
| 61 | maxwell3d.draw_manager->DrawArray(topology, parameters[1], parameters[2], | ||
| 62 | maxwell3d.regs.global_base_instance_index, 1); | ||
| 63 | } | ||
| 64 | }; | ||
| 65 | |||
| 66 | class HLE_DrawIndexed final : public HLEMacroImpl { | ||
| 67 | public: | ||
| 68 | explicit HLE_DrawIndexed(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 69 | |||
| 70 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 71 | maxwell3d.RefreshParameters(); | ||
| 72 | maxwell3d.regs.index_buffer.start_addr_high = parameters[1]; | ||
| 73 | maxwell3d.regs.index_buffer.start_addr_low = parameters[2]; | ||
| 74 | maxwell3d.regs.index_buffer.format = | ||
| 75 | static_cast<Engines::Maxwell3D::Regs::IndexFormat>(parameters[3]); | ||
| 76 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 77 | |||
| 78 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); | ||
| 79 | maxwell3d.draw_manager->DrawIndex(topology, 0, parameters[4], | ||
| 80 | maxwell3d.regs.global_base_vertex_index, | ||
| 81 | maxwell3d.regs.global_base_instance_index, 1); | ||
| 82 | } | ||
| 83 | }; | ||
| 84 | |||
| 85 | /* | 53 | /* |
| 86 | * @note: these macros have two versions, a normal and extended version, with the extended version | 54 | * @note: these macros have two versions, a normal and extended version, with the extended version |
| 87 | * also assigning the base vertex/instance. | 55 | * also assigning the base vertex/instance. |
| @@ -497,11 +465,6 @@ public: | |||
| 497 | } // Anonymous namespace | 465 | } // Anonymous namespace |
| 498 | 466 | ||
| 499 | HLEMacro::HLEMacro(Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} { | 467 | HLEMacro::HLEMacro(Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} { |
| 500 | builders.emplace(0xDD6A7FA92A7D2674ULL, | ||
| 501 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 502 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 503 | return std::make_unique<HLE_DrawArrays>(maxwell3d__); | ||
| 504 | })); | ||
| 505 | builders.emplace(0x0D61FC9FAAC9FCADULL, | 468 | builders.emplace(0x0D61FC9FAAC9FCADULL, |
| 506 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | 469 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( |
| 507 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | 470 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { |
| @@ -512,11 +475,6 @@ HLEMacro::HLEMacro(Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} { | |||
| 512 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | 475 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { |
| 513 | return std::make_unique<HLE_DrawArraysIndirect<true>>(maxwell3d__); | 476 | return std::make_unique<HLE_DrawArraysIndirect<true>>(maxwell3d__); |
| 514 | })); | 477 | })); |
| 515 | builders.emplace(0x2DB33AADB741839CULL, | ||
| 516 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 517 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 518 | return std::make_unique<HLE_DrawIndexed>(maxwell3d__); | ||
| 519 | })); | ||
| 520 | builders.emplace(0x771BB18C62444DA0ULL, | 478 | builders.emplace(0x771BB18C62444DA0ULL, |
| 521 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | 479 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( |
| 522 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | 480 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 3d328a250..f8398b511 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -148,7 +148,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe | |||
| 148 | }); | 148 | }); |
| 149 | } | 149 | } |
| 150 | if (!extended_dynamic_state_2_extra) { | 150 | if (!extended_dynamic_state_2_extra) { |
| 151 | dynamic_state.Refresh2(regs, topology, extended_dynamic_state_2); | 151 | dynamic_state.Refresh2(regs, topology_, extended_dynamic_state_2); |
| 152 | } | 152 | } |
| 153 | if (!extended_dynamic_state_3_blend) { | 153 | if (!extended_dynamic_state_3_blend) { |
| 154 | if (maxwell3d.dirty.flags[Dirty::Blending]) { | 154 | if (maxwell3d.dirty.flags[Dirty::Blending]) { |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index f502a7d09..bf97d25a4 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -98,7 +98,7 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 98 | : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), | 98 | : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), |
| 99 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary()), | 99 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary()), |
| 100 | instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | 100 | instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, |
| 101 | true, Settings::values.renderer_debug.GetValue())), | 101 | Settings::values.renderer_debug.GetValue())), |
| 102 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | 102 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), |
| 103 | surface(CreateSurface(instance, render_window)), | 103 | surface(CreateSurface(instance, render_window)), |
| 104 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device, false), | 104 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device, false), |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 487d8b416..b0153a502 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -336,6 +336,9 @@ void BufferCacheRuntime::Finish() { | |||
| 336 | 336 | ||
| 337 | void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer, | 337 | void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer, |
| 338 | std::span<const VideoCommon::BufferCopy> copies, bool barrier) { | 338 | std::span<const VideoCommon::BufferCopy> copies, bool barrier) { |
| 339 | if (dst_buffer == VK_NULL_HANDLE || src_buffer == VK_NULL_HANDLE) { | ||
| 340 | return; | ||
| 341 | } | ||
| 339 | static constexpr VkMemoryBarrier READ_BARRIER{ | 342 | static constexpr VkMemoryBarrier READ_BARRIER{ |
| 340 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | 343 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, |
| 341 | .pNext = nullptr, | 344 | .pNext = nullptr, |
| @@ -394,6 +397,9 @@ void BufferCacheRuntime::PostCopyBarrier() { | |||
| 394 | } | 397 | } |
| 395 | 398 | ||
| 396 | void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value) { | 399 | void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value) { |
| 400 | if (dest_buffer == VK_NULL_HANDLE) { | ||
| 401 | return; | ||
| 402 | } | ||
| 397 | static constexpr VkMemoryBarrier READ_BARRIER{ | 403 | static constexpr VkMemoryBarrier READ_BARRIER{ |
| 398 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | 404 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, |
| 399 | .pNext = nullptr, | 405 | .pNext = nullptr, |
| @@ -473,6 +479,11 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset | |||
| 473 | cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); | 479 | cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); |
| 474 | }); | 480 | }); |
| 475 | } else { | 481 | } else { |
| 482 | if (!device.HasNullDescriptor() && buffer == VK_NULL_HANDLE) { | ||
| 483 | ReserveNullBuffer(); | ||
| 484 | buffer = *null_buffer; | ||
| 485 | offset = 0; | ||
| 486 | } | ||
| 476 | scheduler.Record([index, buffer, offset](vk::CommandBuffer cmdbuf) { | 487 | scheduler.Record([index, buffer, offset](vk::CommandBuffer cmdbuf) { |
| 477 | cmdbuf.BindVertexBuffer(index, buffer, offset); | 488 | cmdbuf.BindVertexBuffer(index, buffer, offset); |
| 478 | }); | 489 | }); |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 04a3a861e..2a0f0dbf0 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -24,13 +24,15 @@ using Shader::ImageBufferDescriptor; | |||
| 24 | using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; | 24 | using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; |
| 25 | using Tegra::Texture::TexturePair; | 25 | using Tegra::Texture::TexturePair; |
| 26 | 26 | ||
| 27 | ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, | 27 | ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_, |
| 28 | DescriptorPool& descriptor_pool, | ||
| 28 | UpdateDescriptorQueue& update_descriptor_queue_, | 29 | UpdateDescriptorQueue& update_descriptor_queue_, |
| 29 | Common::ThreadWorker* thread_worker, | 30 | Common::ThreadWorker* thread_worker, |
| 30 | PipelineStatistics* pipeline_statistics, | 31 | PipelineStatistics* pipeline_statistics, |
| 31 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, | 32 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, |
| 32 | vk::ShaderModule spv_module_) | 33 | vk::ShaderModule spv_module_) |
| 33 | : device{device_}, update_descriptor_queue{update_descriptor_queue_}, info{info_}, | 34 | : device{device_}, pipeline_cache(pipeline_cache_), |
| 35 | update_descriptor_queue{update_descriptor_queue_}, info{info_}, | ||
| 34 | spv_module(std::move(spv_module_)) { | 36 | spv_module(std::move(spv_module_)) { |
| 35 | if (shader_notify) { | 37 | if (shader_notify) { |
| 36 | shader_notify->MarkShaderBuilding(); | 38 | shader_notify->MarkShaderBuilding(); |
| @@ -56,23 +58,27 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 56 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { | 58 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { |
| 57 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | 59 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; |
| 58 | } | 60 | } |
| 59 | pipeline = device.GetLogical().CreateComputePipeline({ | 61 | pipeline = device.GetLogical().CreateComputePipeline( |
| 60 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | 62 | { |
| 61 | .pNext = nullptr, | 63 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, |
| 62 | .flags = flags, | 64 | .pNext = nullptr, |
| 63 | .stage{ | 65 | .flags = flags, |
| 64 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 66 | .stage{ |
| 65 | .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr, | 67 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| 66 | .flags = 0, | 68 | .pNext = |
| 67 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | 69 | device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr, |
| 68 | .module = *spv_module, | 70 | .flags = 0, |
| 69 | .pName = "main", | 71 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, |
| 70 | .pSpecializationInfo = nullptr, | 72 | .module = *spv_module, |
| 73 | .pName = "main", | ||
| 74 | .pSpecializationInfo = nullptr, | ||
| 75 | }, | ||
| 76 | .layout = *pipeline_layout, | ||
| 77 | .basePipelineHandle = 0, | ||
| 78 | .basePipelineIndex = 0, | ||
| 71 | }, | 79 | }, |
| 72 | .layout = *pipeline_layout, | 80 | *pipeline_cache); |
| 73 | .basePipelineHandle = 0, | 81 | |
| 74 | .basePipelineIndex = 0, | ||
| 75 | }); | ||
| 76 | if (pipeline_statistics) { | 82 | if (pipeline_statistics) { |
| 77 | pipeline_statistics->Collect(*pipeline); | 83 | pipeline_statistics->Collect(*pipeline); |
| 78 | } | 84 | } |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index d70837fc5..78d77027f 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h | |||
| @@ -28,7 +28,8 @@ class Scheduler; | |||
| 28 | 28 | ||
| 29 | class ComputePipeline { | 29 | class ComputePipeline { |
| 30 | public: | 30 | public: |
| 31 | explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, | 31 | explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache, |
| 32 | DescriptorPool& descriptor_pool, | ||
| 32 | UpdateDescriptorQueue& update_descriptor_queue, | 33 | UpdateDescriptorQueue& update_descriptor_queue, |
| 33 | Common::ThreadWorker* thread_worker, | 34 | Common::ThreadWorker* thread_worker, |
| 34 | PipelineStatistics* pipeline_statistics, | 35 | PipelineStatistics* pipeline_statistics, |
| @@ -46,6 +47,7 @@ public: | |||
| 46 | 47 | ||
| 47 | private: | 48 | private: |
| 48 | const Device& device; | 49 | const Device& device; |
| 50 | vk::PipelineCache& pipeline_cache; | ||
| 49 | UpdateDescriptorQueue& update_descriptor_queue; | 51 | UpdateDescriptorQueue& update_descriptor_queue; |
| 50 | Shader::Info info; | 52 | Shader::Info info; |
| 51 | 53 | ||
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index d11383bf1..f91bb5a1d 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -234,13 +234,14 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m | |||
| 234 | 234 | ||
| 235 | GraphicsPipeline::GraphicsPipeline( | 235 | GraphicsPipeline::GraphicsPipeline( |
| 236 | Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, | 236 | Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, |
| 237 | VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, | 237 | vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify, |
| 238 | const Device& device_, DescriptorPool& descriptor_pool, | ||
| 238 | UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, | 239 | UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, |
| 239 | PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, | 240 | PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, |
| 240 | const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages, | 241 | const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 241 | const std::array<const Shader::Info*, NUM_STAGES>& infos) | 242 | const std::array<const Shader::Info*, NUM_STAGES>& infos) |
| 242 | : key{key_}, device{device_}, texture_cache{texture_cache_}, | 243 | : key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 243 | buffer_cache{buffer_cache_}, scheduler{scheduler_}, | 244 | pipeline_cache(pipeline_cache_), scheduler{scheduler_}, |
| 244 | update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} { | 245 | update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} { |
| 245 | if (shader_notify) { | 246 | if (shader_notify) { |
| 246 | shader_notify->MarkShaderBuilding(); | 247 | shader_notify->MarkShaderBuilding(); |
| @@ -644,12 +645,15 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 644 | .pNext = nullptr, | 645 | .pNext = nullptr, |
| 645 | .flags = 0, | 646 | .flags = 0, |
| 646 | .topology = input_assembly_topology, | 647 | .topology = input_assembly_topology, |
| 647 | .primitiveRestartEnable = dynamic.primitive_restart_enable != 0 && | 648 | .primitiveRestartEnable = |
| 648 | ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && | 649 | dynamic.primitive_restart_enable != 0 && |
| 649 | device.IsTopologyListPrimitiveRestartSupported()) || | 650 | ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && |
| 650 | SupportsPrimitiveRestart(input_assembly_topology) || | 651 | device.IsTopologyListPrimitiveRestartSupported()) || |
| 651 | (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && | 652 | SupportsPrimitiveRestart(input_assembly_topology) || |
| 652 | device.IsPatchListPrimitiveRestartSupported())), | 653 | (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && |
| 654 | device.IsPatchListPrimitiveRestartSupported())) | ||
| 655 | ? VK_TRUE | ||
| 656 | : VK_FALSE, | ||
| 653 | }; | 657 | }; |
| 654 | const VkPipelineTessellationStateCreateInfo tessellation_ci{ | 658 | const VkPipelineTessellationStateCreateInfo tessellation_ci{ |
| 655 | .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, | 659 | .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, |
| @@ -699,7 +703,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 699 | .cullMode = static_cast<VkCullModeFlags>( | 703 | .cullMode = static_cast<VkCullModeFlags>( |
| 700 | dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE), | 704 | dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE), |
| 701 | .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()), | 705 | .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()), |
| 702 | .depthBiasEnable = (dynamic.depth_bias_enable == 0 ? VK_TRUE : VK_FALSE), | 706 | .depthBiasEnable = (dynamic.depth_bias_enable != 0 ? VK_TRUE : VK_FALSE), |
| 703 | .depthBiasConstantFactor = 0.0f, | 707 | .depthBiasConstantFactor = 0.0f, |
| 704 | .depthBiasClamp = 0.0f, | 708 | .depthBiasClamp = 0.0f, |
| 705 | .depthBiasSlopeFactor = 0.0f, | 709 | .depthBiasSlopeFactor = 0.0f, |
| @@ -894,27 +898,29 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 894 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { | 898 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { |
| 895 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | 899 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; |
| 896 | } | 900 | } |
| 897 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | 901 | pipeline = device.GetLogical().CreateGraphicsPipeline( |
| 898 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | 902 | { |
| 899 | .pNext = nullptr, | 903 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
| 900 | .flags = flags, | 904 | .pNext = nullptr, |
| 901 | .stageCount = static_cast<u32>(shader_stages.size()), | 905 | .flags = flags, |
| 902 | .pStages = shader_stages.data(), | 906 | .stageCount = static_cast<u32>(shader_stages.size()), |
| 903 | .pVertexInputState = &vertex_input_ci, | 907 | .pStages = shader_stages.data(), |
| 904 | .pInputAssemblyState = &input_assembly_ci, | 908 | .pVertexInputState = &vertex_input_ci, |
| 905 | .pTessellationState = &tessellation_ci, | 909 | .pInputAssemblyState = &input_assembly_ci, |
| 906 | .pViewportState = &viewport_ci, | 910 | .pTessellationState = &tessellation_ci, |
| 907 | .pRasterizationState = &rasterization_ci, | 911 | .pViewportState = &viewport_ci, |
| 908 | .pMultisampleState = &multisample_ci, | 912 | .pRasterizationState = &rasterization_ci, |
| 909 | .pDepthStencilState = &depth_stencil_ci, | 913 | .pMultisampleState = &multisample_ci, |
| 910 | .pColorBlendState = &color_blend_ci, | 914 | .pDepthStencilState = &depth_stencil_ci, |
| 911 | .pDynamicState = &dynamic_state_ci, | 915 | .pColorBlendState = &color_blend_ci, |
| 912 | .layout = *pipeline_layout, | 916 | .pDynamicState = &dynamic_state_ci, |
| 913 | .renderPass = render_pass, | 917 | .layout = *pipeline_layout, |
| 914 | .subpass = 0, | 918 | .renderPass = render_pass, |
| 915 | .basePipelineHandle = nullptr, | 919 | .subpass = 0, |
| 916 | .basePipelineIndex = 0, | 920 | .basePipelineHandle = nullptr, |
| 917 | }); | 921 | .basePipelineIndex = 0, |
| 922 | }, | ||
| 923 | *pipeline_cache); | ||
| 918 | } | 924 | } |
| 919 | 925 | ||
| 920 | void GraphicsPipeline::Validate() { | 926 | void GraphicsPipeline::Validate() { |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 1ed2967be..67c657d0e 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -70,16 +70,14 @@ class GraphicsPipeline { | |||
| 70 | static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; | 70 | static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; |
| 71 | 71 | ||
| 72 | public: | 72 | public: |
| 73 | explicit GraphicsPipeline(Scheduler& scheduler, BufferCache& buffer_cache, | 73 | explicit GraphicsPipeline( |
| 74 | TextureCache& texture_cache, VideoCore::ShaderNotify* shader_notify, | 74 | Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, |
| 75 | const Device& device, DescriptorPool& descriptor_pool, | 75 | vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify, |
| 76 | UpdateDescriptorQueue& update_descriptor_queue, | 76 | const Device& device, DescriptorPool& descriptor_pool, |
| 77 | Common::ThreadWorker* worker_thread, | 77 | UpdateDescriptorQueue& update_descriptor_queue, Common::ThreadWorker* worker_thread, |
| 78 | PipelineStatistics* pipeline_statistics, | 78 | PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, |
| 79 | RenderPassCache& render_pass_cache, | 79 | const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 80 | const GraphicsPipelineCacheKey& key, | 80 | const std::array<const Shader::Info*, NUM_STAGES>& infos); |
| 81 | std::array<vk::ShaderModule, NUM_STAGES> stages, | ||
| 82 | const std::array<const Shader::Info*, NUM_STAGES>& infos); | ||
| 83 | 81 | ||
| 84 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; | 82 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; |
| 85 | GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; | 83 | GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; |
| @@ -133,6 +131,7 @@ private: | |||
| 133 | const Device& device; | 131 | const Device& device; |
| 134 | TextureCache& texture_cache; | 132 | TextureCache& texture_cache; |
| 135 | BufferCache& buffer_cache; | 133 | BufferCache& buffer_cache; |
| 134 | vk::PipelineCache& pipeline_cache; | ||
| 136 | Scheduler& scheduler; | 135 | Scheduler& scheduler; |
| 137 | UpdateDescriptorQueue& update_descriptor_queue; | 136 | UpdateDescriptorQueue& update_descriptor_queue; |
| 138 | 137 | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 3046b72ab..67e5bc648 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -55,6 +55,7 @@ using VideoCommon::GenericEnvironment; | |||
| 55 | using VideoCommon::GraphicsEnvironment; | 55 | using VideoCommon::GraphicsEnvironment; |
| 56 | 56 | ||
| 57 | constexpr u32 CACHE_VERSION = 10; | 57 | constexpr u32 CACHE_VERSION = 10; |
| 58 | constexpr std::array<char, 8> VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'}; | ||
| 58 | 59 | ||
| 59 | template <typename Container> | 60 | template <typename Container> |
| 60 | auto MakeSpan(Container& container) { | 61 | auto MakeSpan(Container& container) { |
| @@ -284,6 +285,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 284 | render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, | 285 | render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, |
| 285 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, | 286 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, |
| 286 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, | 287 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, |
| 288 | use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()}, | ||
| 287 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), | 289 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), |
| 288 | serialization_thread(1, "VkPipelineSerialization") { | 290 | serialization_thread(1, "VkPipelineSerialization") { |
| 289 | const auto& float_control{device.FloatControlProperties()}; | 291 | const auto& float_control{device.FloatControlProperties()}; |
| @@ -362,7 +364,12 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 362 | }; | 364 | }; |
| 363 | } | 365 | } |
| 364 | 366 | ||
| 365 | PipelineCache::~PipelineCache() = default; | 367 | PipelineCache::~PipelineCache() { |
| 368 | if (use_vulkan_pipeline_cache && !vulkan_pipeline_cache_filename.empty()) { | ||
| 369 | SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache, | ||
| 370 | CACHE_VERSION); | ||
| 371 | } | ||
| 372 | } | ||
| 366 | 373 | ||
| 367 | GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() { | 374 | GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() { |
| 368 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); | 375 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); |
| @@ -418,6 +425,12 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 418 | } | 425 | } |
| 419 | pipeline_cache_filename = base_dir / "vulkan.bin"; | 426 | pipeline_cache_filename = base_dir / "vulkan.bin"; |
| 420 | 427 | ||
| 428 | if (use_vulkan_pipeline_cache) { | ||
| 429 | vulkan_pipeline_cache_filename = base_dir / "vulkan_pipelines.bin"; | ||
| 430 | vulkan_pipeline_cache = | ||
| 431 | LoadVulkanPipelineCache(vulkan_pipeline_cache_filename, CACHE_VERSION); | ||
| 432 | } | ||
| 433 | |||
| 421 | struct { | 434 | struct { |
| 422 | std::mutex mutex; | 435 | std::mutex mutex; |
| 423 | size_t total{}; | 436 | size_t total{}; |
| @@ -496,6 +509,11 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 496 | 509 | ||
| 497 | workers.WaitForRequests(stop_loading); | 510 | workers.WaitForRequests(stop_loading); |
| 498 | 511 | ||
| 512 | if (use_vulkan_pipeline_cache) { | ||
| 513 | SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache, | ||
| 514 | CACHE_VERSION); | ||
| 515 | } | ||
| 516 | |||
| 499 | if (state.statistics) { | 517 | if (state.statistics) { |
| 500 | state.statistics->Report(); | 518 | state.statistics->Report(); |
| 501 | } | 519 | } |
| @@ -616,10 +634,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 616 | previous_stage = &program; | 634 | previous_stage = &program; |
| 617 | } | 635 | } |
| 618 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 636 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 619 | return std::make_unique<GraphicsPipeline>(scheduler, buffer_cache, texture_cache, | 637 | return std::make_unique<GraphicsPipeline>( |
| 620 | &shader_notify, device, descriptor_pool, | 638 | scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device, |
| 621 | update_descriptor_queue, thread_worker, statistics, | 639 | descriptor_pool, update_descriptor_queue, thread_worker, statistics, render_pass_cache, key, |
| 622 | render_pass_cache, key, std::move(modules), infos); | 640 | std::move(modules), infos); |
| 623 | 641 | ||
| 624 | } catch (const Shader::Exception& exception) { | 642 | } catch (const Shader::Exception& exception) { |
| 625 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); | 643 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); |
| @@ -689,13 +707,107 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 689 | spv_module.SetObjectNameEXT(name.c_str()); | 707 | spv_module.SetObjectNameEXT(name.c_str()); |
| 690 | } | 708 | } |
| 691 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 709 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 692 | return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue, | 710 | return std::make_unique<ComputePipeline>(device, vulkan_pipeline_cache, descriptor_pool, |
| 693 | thread_worker, statistics, &shader_notify, | 711 | update_descriptor_queue, thread_worker, statistics, |
| 694 | program.info, std::move(spv_module)); | 712 | &shader_notify, program.info, std::move(spv_module)); |
| 695 | 713 | ||
| 696 | } catch (const Shader::Exception& exception) { | 714 | } catch (const Shader::Exception& exception) { |
| 697 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); | 715 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); |
| 698 | return nullptr; | 716 | return nullptr; |
| 699 | } | 717 | } |
| 700 | 718 | ||
| 719 | void PipelineCache::SerializeVulkanPipelineCache(const std::filesystem::path& filename, | ||
| 720 | const vk::PipelineCache& pipeline_cache, | ||
| 721 | u32 cache_version) try { | ||
| 722 | std::ofstream file(filename, std::ios::binary); | ||
| 723 | file.exceptions(std::ifstream::failbit); | ||
| 724 | if (!file.is_open()) { | ||
| 725 | LOG_ERROR(Common_Filesystem, "Failed to open Vulkan driver pipeline cache file {}", | ||
| 726 | Common::FS::PathToUTF8String(filename)); | ||
| 727 | return; | ||
| 728 | } | ||
| 729 | file.write(VULKAN_CACHE_MAGIC_NUMBER.data(), VULKAN_CACHE_MAGIC_NUMBER.size()) | ||
| 730 | .write(reinterpret_cast<const char*>(&cache_version), sizeof(cache_version)); | ||
| 731 | |||
| 732 | size_t cache_size = 0; | ||
| 733 | std::vector<char> cache_data; | ||
| 734 | if (pipeline_cache) { | ||
| 735 | pipeline_cache.Read(&cache_size, nullptr); | ||
| 736 | cache_data.resize(cache_size); | ||
| 737 | pipeline_cache.Read(&cache_size, cache_data.data()); | ||
| 738 | } | ||
| 739 | file.write(cache_data.data(), cache_size); | ||
| 740 | |||
| 741 | LOG_INFO(Render_Vulkan, "Vulkan driver pipelines cached at: {}", | ||
| 742 | Common::FS::PathToUTF8String(filename)); | ||
| 743 | |||
| 744 | } catch (const std::ios_base::failure& e) { | ||
| 745 | LOG_ERROR(Common_Filesystem, "{}", e.what()); | ||
| 746 | if (!Common::FS::RemoveFile(filename)) { | ||
| 747 | LOG_ERROR(Common_Filesystem, "Failed to delete Vulkan driver pipeline cache file {}", | ||
| 748 | Common::FS::PathToUTF8String(filename)); | ||
| 749 | } | ||
| 750 | } | ||
| 751 | |||
| 752 | vk::PipelineCache PipelineCache::LoadVulkanPipelineCache(const std::filesystem::path& filename, | ||
| 753 | u32 expected_cache_version) { | ||
| 754 | const auto create_pipeline_cache = [this](size_t data_size, const void* data) { | ||
| 755 | VkPipelineCacheCreateInfo pipeline_cache_ci = { | ||
| 756 | .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, | ||
| 757 | .pNext = nullptr, | ||
| 758 | .flags = 0, | ||
| 759 | .initialDataSize = data_size, | ||
| 760 | .pInitialData = data}; | ||
| 761 | return device.GetLogical().CreatePipelineCache(pipeline_cache_ci); | ||
| 762 | }; | ||
| 763 | try { | ||
| 764 | std::ifstream file(filename, std::ios::binary | std::ios::ate); | ||
| 765 | if (!file.is_open()) { | ||
| 766 | return create_pipeline_cache(0, nullptr); | ||
| 767 | } | ||
| 768 | file.exceptions(std::ifstream::failbit); | ||
| 769 | const auto end{file.tellg()}; | ||
| 770 | file.seekg(0, std::ios::beg); | ||
| 771 | |||
| 772 | std::array<char, 8> magic_number; | ||
| 773 | u32 cache_version; | ||
| 774 | file.read(magic_number.data(), magic_number.size()) | ||
| 775 | .read(reinterpret_cast<char*>(&cache_version), sizeof(cache_version)); | ||
| 776 | if (magic_number != VULKAN_CACHE_MAGIC_NUMBER || cache_version != expected_cache_version) { | ||
| 777 | file.close(); | ||
| 778 | if (Common::FS::RemoveFile(filename)) { | ||
| 779 | if (magic_number != VULKAN_CACHE_MAGIC_NUMBER) { | ||
| 780 | LOG_ERROR(Common_Filesystem, "Invalid Vulkan driver pipeline cache file"); | ||
| 781 | } | ||
| 782 | if (cache_version != expected_cache_version) { | ||
| 783 | LOG_INFO(Common_Filesystem, "Deleting old Vulkan driver pipeline cache"); | ||
| 784 | } | ||
| 785 | } else { | ||
| 786 | LOG_ERROR(Common_Filesystem, | ||
| 787 | "Invalid Vulkan pipeline cache file and failed to delete it in \"{}\"", | ||
| 788 | Common::FS::PathToUTF8String(filename)); | ||
| 789 | } | ||
| 790 | return create_pipeline_cache(0, nullptr); | ||
| 791 | } | ||
| 792 | |||
| 793 | const size_t cache_size = static_cast<size_t>(end) - magic_number.size(); | ||
| 794 | std::vector<char> cache_data(cache_size); | ||
| 795 | file.read(cache_data.data(), cache_size); | ||
| 796 | |||
| 797 | LOG_INFO(Render_Vulkan, | ||
| 798 | "Loaded Vulkan driver pipeline cache: ", Common::FS::PathToUTF8String(filename)); | ||
| 799 | |||
| 800 | return create_pipeline_cache(cache_size, cache_data.data()); | ||
| 801 | |||
| 802 | } catch (const std::ios_base::failure& e) { | ||
| 803 | LOG_ERROR(Common_Filesystem, "{}", e.what()); | ||
| 804 | if (!Common::FS::RemoveFile(filename)) { | ||
| 805 | LOG_ERROR(Common_Filesystem, "Failed to delete Vulkan driver pipeline cache file {}", | ||
| 806 | Common::FS::PathToUTF8String(filename)); | ||
| 807 | } | ||
| 808 | |||
| 809 | return create_pipeline_cache(0, nullptr); | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 701 | } // namespace Vulkan | 813 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index b4f593ef5..5171912d7 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -135,6 +135,12 @@ private: | |||
| 135 | PipelineStatistics* statistics, | 135 | PipelineStatistics* statistics, |
| 136 | bool build_in_parallel); | 136 | bool build_in_parallel); |
| 137 | 137 | ||
| 138 | void SerializeVulkanPipelineCache(const std::filesystem::path& filename, | ||
| 139 | const vk::PipelineCache& pipeline_cache, u32 cache_version); | ||
| 140 | |||
| 141 | vk::PipelineCache LoadVulkanPipelineCache(const std::filesystem::path& filename, | ||
| 142 | u32 expected_cache_version); | ||
| 143 | |||
| 138 | const Device& device; | 144 | const Device& device; |
| 139 | Scheduler& scheduler; | 145 | Scheduler& scheduler; |
| 140 | DescriptorPool& descriptor_pool; | 146 | DescriptorPool& descriptor_pool; |
| @@ -144,6 +150,7 @@ private: | |||
| 144 | TextureCache& texture_cache; | 150 | TextureCache& texture_cache; |
| 145 | VideoCore::ShaderNotify& shader_notify; | 151 | VideoCore::ShaderNotify& shader_notify; |
| 146 | bool use_asynchronous_shaders{}; | 152 | bool use_asynchronous_shaders{}; |
| 153 | bool use_vulkan_pipeline_cache{}; | ||
| 147 | 154 | ||
| 148 | GraphicsPipelineCacheKey graphics_key{}; | 155 | GraphicsPipelineCacheKey graphics_key{}; |
| 149 | GraphicsPipeline* current_pipeline{}; | 156 | GraphicsPipeline* current_pipeline{}; |
| @@ -158,6 +165,9 @@ private: | |||
| 158 | 165 | ||
| 159 | std::filesystem::path pipeline_cache_filename; | 166 | std::filesystem::path pipeline_cache_filename; |
| 160 | 167 | ||
| 168 | std::filesystem::path vulkan_pipeline_cache_filename; | ||
| 169 | vk::PipelineCache vulkan_pipeline_cache; | ||
| 170 | |||
| 161 | Common::ThreadWorker workers; | 171 | Common::ThreadWorker workers; |
| 162 | Common::ThreadWorker serialization_thread; | 172 | Common::ThreadWorker serialization_thread; |
| 163 | DynamicFeatures dynamic_features; | 173 | DynamicFeatures dynamic_features; |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 5c5bfa18d..8e77f5aa3 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -1487,6 +1487,9 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1487 | 1487 | ||
| 1488 | max_push_descriptors = push_descriptor.maxPushDescriptors; | 1488 | max_push_descriptors = push_descriptor.maxPushDescriptors; |
| 1489 | } | 1489 | } |
| 1490 | |||
| 1491 | has_null_descriptor = true; | ||
| 1492 | |||
| 1490 | return extensions; | 1493 | return extensions; |
| 1491 | } | 1494 | } |
| 1492 | 1495 | ||
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 920a8f4e3..6042046e1 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -397,6 +397,10 @@ public: | |||
| 397 | return must_emulate_bgr565; | 397 | return must_emulate_bgr565; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | bool HasNullDescriptor() const { | ||
| 401 | return has_null_descriptor; | ||
| 402 | } | ||
| 403 | |||
| 400 | u32 GetMaxVertexInputAttributes() const { | 404 | u32 GetMaxVertexInputAttributes() const { |
| 401 | return max_vertex_input_attributes; | 405 | return max_vertex_input_attributes; |
| 402 | } | 406 | } |
| @@ -511,6 +515,7 @@ private: | |||
| 511 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. | 515 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. |
| 512 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. | 516 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. |
| 513 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. | 517 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. |
| 518 | bool has_null_descriptor{}; ///< Has support for null descriptors. | ||
| 514 | u32 max_vertex_input_attributes{}; ///< Max vertex input attributes in pipeline | 519 | u32 max_vertex_input_attributes{}; ///< Max vertex input attributes in pipeline |
| 515 | u32 max_vertex_input_bindings{}; ///< Max vertex input buffers in pipeline | 520 | u32 max_vertex_input_bindings{}; ///< Max vertex input buffers in pipeline |
| 516 | 521 | ||
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp index 562039b56..b6d83e446 100644 --- a/src/video_core/vulkan_common/vulkan_instance.cpp +++ b/src/video_core/vulkan_common/vulkan_instance.cpp | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | namespace Vulkan { | 32 | namespace Vulkan { |
| 33 | namespace { | 33 | namespace { |
| 34 | [[nodiscard]] std::vector<const char*> RequiredExtensions( | 34 | [[nodiscard]] std::vector<const char*> RequiredExtensions( |
| 35 | Core::Frontend::WindowSystemType window_type, bool enable_debug_utils) { | 35 | Core::Frontend::WindowSystemType window_type, bool enable_validation) { |
| 36 | std::vector<const char*> extensions; | 36 | std::vector<const char*> extensions; |
| 37 | extensions.reserve(6); | 37 | extensions.reserve(6); |
| 38 | switch (window_type) { | 38 | switch (window_type) { |
| @@ -65,7 +65,7 @@ namespace { | |||
| 65 | if (window_type != Core::Frontend::WindowSystemType::Headless) { | 65 | if (window_type != Core::Frontend::WindowSystemType::Headless) { |
| 66 | extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); | 66 | extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); |
| 67 | } | 67 | } |
| 68 | if (enable_debug_utils) { | 68 | if (enable_validation) { |
| 69 | extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); | 69 | extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); |
| 70 | } | 70 | } |
| 71 | extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); | 71 | extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| @@ -95,9 +95,9 @@ namespace { | |||
| 95 | return true; | 95 | return true; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | [[nodiscard]] std::vector<const char*> Layers(bool enable_layers) { | 98 | [[nodiscard]] std::vector<const char*> Layers(bool enable_validation) { |
| 99 | std::vector<const char*> layers; | 99 | std::vector<const char*> layers; |
| 100 | if (enable_layers) { | 100 | if (enable_validation) { |
| 101 | layers.push_back("VK_LAYER_KHRONOS_validation"); | 101 | layers.push_back("VK_LAYER_KHRONOS_validation"); |
| 102 | } | 102 | } |
| 103 | return layers; | 103 | return layers; |
| @@ -125,7 +125,7 @@ void RemoveUnavailableLayers(const vk::InstanceDispatch& dld, std::vector<const | |||
| 125 | 125 | ||
| 126 | vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, | 126 | vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, |
| 127 | u32 required_version, Core::Frontend::WindowSystemType window_type, | 127 | u32 required_version, Core::Frontend::WindowSystemType window_type, |
| 128 | bool enable_debug_utils, bool enable_layers) { | 128 | bool enable_validation) { |
| 129 | if (!library.IsOpen()) { | 129 | if (!library.IsOpen()) { |
| 130 | LOG_ERROR(Render_Vulkan, "Vulkan library not available"); | 130 | LOG_ERROR(Render_Vulkan, "Vulkan library not available"); |
| 131 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | 131 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| @@ -138,11 +138,11 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD | |||
| 138 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers"); | 138 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers"); |
| 139 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | 139 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 140 | } | 140 | } |
| 141 | const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_debug_utils); | 141 | const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_validation); |
| 142 | if (!AreExtensionsSupported(dld, extensions)) { | 142 | if (!AreExtensionsSupported(dld, extensions)) { |
| 143 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); | 143 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); |
| 144 | } | 144 | } |
| 145 | std::vector<const char*> layers = Layers(enable_layers); | 145 | std::vector<const char*> layers = Layers(enable_validation); |
| 146 | RemoveUnavailableLayers(dld, layers); | 146 | RemoveUnavailableLayers(dld, layers); |
| 147 | 147 | ||
| 148 | const u32 available_version = vk::AvailableVersion(dld); | 148 | const u32 available_version = vk::AvailableVersion(dld); |
diff --git a/src/video_core/vulkan_common/vulkan_instance.h b/src/video_core/vulkan_common/vulkan_instance.h index 40419d802..b59b92f83 100644 --- a/src/video_core/vulkan_common/vulkan_instance.h +++ b/src/video_core/vulkan_common/vulkan_instance.h | |||
| @@ -17,8 +17,7 @@ namespace Vulkan { | |||
| 17 | * @param dld Dispatch table to load function pointers into | 17 | * @param dld Dispatch table to load function pointers into |
| 18 | * @param required_version Required Vulkan version (for example, VK_API_VERSION_1_1) | 18 | * @param required_version Required Vulkan version (for example, VK_API_VERSION_1_1) |
| 19 | * @param window_type Window system type's enabled extension | 19 | * @param window_type Window system type's enabled extension |
| 20 | * @param enable_debug_utils Whether to enable VK_EXT_debug_utils_extension_name or not | 20 | * @param enable_validation Whether to enable Vulkan validation layers or not |
| 21 | * @param enable_layers Whether to enable Vulkan validation layers or not | ||
| 22 | * | 21 | * |
| 23 | * @return A new Vulkan instance | 22 | * @return A new Vulkan instance |
| 24 | * @throw vk::Exception on failure | 23 | * @throw vk::Exception on failure |
| @@ -26,6 +25,6 @@ namespace Vulkan { | |||
| 26 | [[nodiscard]] vk::Instance CreateInstance( | 25 | [[nodiscard]] vk::Instance CreateInstance( |
| 27 | const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, u32 required_version, | 26 | const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, u32 required_version, |
| 28 | Core::Frontend::WindowSystemType window_type = Core::Frontend::WindowSystemType::Headless, | 27 | Core::Frontend::WindowSystemType window_type = Core::Frontend::WindowSystemType::Headless, |
| 29 | bool enable_debug_utils = false, bool enable_layers = false); | 28 | bool enable_validation = false); |
| 30 | 29 | ||
| 31 | } // namespace Vulkan | 30 | } // namespace Vulkan |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 861767c13..61be1fce1 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -152,6 +152,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 152 | X(vkCreateGraphicsPipelines); | 152 | X(vkCreateGraphicsPipelines); |
| 153 | X(vkCreateImage); | 153 | X(vkCreateImage); |
| 154 | X(vkCreateImageView); | 154 | X(vkCreateImageView); |
| 155 | X(vkCreatePipelineCache); | ||
| 155 | X(vkCreatePipelineLayout); | 156 | X(vkCreatePipelineLayout); |
| 156 | X(vkCreateQueryPool); | 157 | X(vkCreateQueryPool); |
| 157 | X(vkCreateRenderPass); | 158 | X(vkCreateRenderPass); |
| @@ -171,6 +172,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 171 | X(vkDestroyImage); | 172 | X(vkDestroyImage); |
| 172 | X(vkDestroyImageView); | 173 | X(vkDestroyImageView); |
| 173 | X(vkDestroyPipeline); | 174 | X(vkDestroyPipeline); |
| 175 | X(vkDestroyPipelineCache); | ||
| 174 | X(vkDestroyPipelineLayout); | 176 | X(vkDestroyPipelineLayout); |
| 175 | X(vkDestroyQueryPool); | 177 | X(vkDestroyQueryPool); |
| 176 | X(vkDestroyRenderPass); | 178 | X(vkDestroyRenderPass); |
| @@ -188,6 +190,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 188 | X(vkGetEventStatus); | 190 | X(vkGetEventStatus); |
| 189 | X(vkGetFenceStatus); | 191 | X(vkGetFenceStatus); |
| 190 | X(vkGetImageMemoryRequirements); | 192 | X(vkGetImageMemoryRequirements); |
| 193 | X(vkGetPipelineCacheData); | ||
| 191 | X(vkGetMemoryFdKHR); | 194 | X(vkGetMemoryFdKHR); |
| 192 | #ifdef _WIN32 | 195 | #ifdef _WIN32 |
| 193 | X(vkGetMemoryWin32HandleKHR); | 196 | X(vkGetMemoryWin32HandleKHR); |
| @@ -431,6 +434,10 @@ void Destroy(VkDevice device, VkPipeline handle, const DeviceDispatch& dld) noex | |||
| 431 | dld.vkDestroyPipeline(device, handle, nullptr); | 434 | dld.vkDestroyPipeline(device, handle, nullptr); |
| 432 | } | 435 | } |
| 433 | 436 | ||
| 437 | void Destroy(VkDevice device, VkPipelineCache handle, const DeviceDispatch& dld) noexcept { | ||
| 438 | dld.vkDestroyPipelineCache(device, handle, nullptr); | ||
| 439 | } | ||
| 440 | |||
| 434 | void Destroy(VkDevice device, VkPipelineLayout handle, const DeviceDispatch& dld) noexcept { | 441 | void Destroy(VkDevice device, VkPipelineLayout handle, const DeviceDispatch& dld) noexcept { |
| 435 | dld.vkDestroyPipelineLayout(device, handle, nullptr); | 442 | dld.vkDestroyPipelineLayout(device, handle, nullptr); |
| 436 | } | 443 | } |
| @@ -651,6 +658,10 @@ void ShaderModule::SetObjectNameEXT(const char* name) const { | |||
| 651 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SHADER_MODULE, name); | 658 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SHADER_MODULE, name); |
| 652 | } | 659 | } |
| 653 | 660 | ||
| 661 | void PipelineCache::SetObjectNameEXT(const char* name) const { | ||
| 662 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_PIPELINE_CACHE, name); | ||
| 663 | } | ||
| 664 | |||
| 654 | void Semaphore::SetObjectNameEXT(const char* name) const { | 665 | void Semaphore::SetObjectNameEXT(const char* name) const { |
| 655 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SEMAPHORE, name); | 666 | SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SEMAPHORE, name); |
| 656 | } | 667 | } |
| @@ -746,21 +757,29 @@ DescriptorSetLayout Device::CreateDescriptorSetLayout( | |||
| 746 | return DescriptorSetLayout(object, handle, *dld); | 757 | return DescriptorSetLayout(object, handle, *dld); |
| 747 | } | 758 | } |
| 748 | 759 | ||
| 760 | PipelineCache Device::CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const { | ||
| 761 | VkPipelineCache cache; | ||
| 762 | Check(dld->vkCreatePipelineCache(handle, &ci, nullptr, &cache)); | ||
| 763 | return PipelineCache(cache, handle, *dld); | ||
| 764 | } | ||
| 765 | |||
| 749 | PipelineLayout Device::CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const { | 766 | PipelineLayout Device::CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const { |
| 750 | VkPipelineLayout object; | 767 | VkPipelineLayout object; |
| 751 | Check(dld->vkCreatePipelineLayout(handle, &ci, nullptr, &object)); | 768 | Check(dld->vkCreatePipelineLayout(handle, &ci, nullptr, &object)); |
| 752 | return PipelineLayout(object, handle, *dld); | 769 | return PipelineLayout(object, handle, *dld); |
| 753 | } | 770 | } |
| 754 | 771 | ||
| 755 | Pipeline Device::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const { | 772 | Pipeline Device::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci, |
| 773 | VkPipelineCache cache) const { | ||
| 756 | VkPipeline object; | 774 | VkPipeline object; |
| 757 | Check(dld->vkCreateGraphicsPipelines(handle, nullptr, 1, &ci, nullptr, &object)); | 775 | Check(dld->vkCreateGraphicsPipelines(handle, cache, 1, &ci, nullptr, &object)); |
| 758 | return Pipeline(object, handle, *dld); | 776 | return Pipeline(object, handle, *dld); |
| 759 | } | 777 | } |
| 760 | 778 | ||
| 761 | Pipeline Device::CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const { | 779 | Pipeline Device::CreateComputePipeline(const VkComputePipelineCreateInfo& ci, |
| 780 | VkPipelineCache cache) const { | ||
| 762 | VkPipeline object; | 781 | VkPipeline object; |
| 763 | Check(dld->vkCreateComputePipelines(handle, nullptr, 1, &ci, nullptr, &object)); | 782 | Check(dld->vkCreateComputePipelines(handle, cache, 1, &ci, nullptr, &object)); |
| 764 | return Pipeline(object, handle, *dld); | 783 | return Pipeline(object, handle, *dld); |
| 765 | } | 784 | } |
| 766 | 785 | ||
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index accfad8c1..412779b51 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -270,6 +270,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 270 | PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines{}; | 270 | PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines{}; |
| 271 | PFN_vkCreateImage vkCreateImage{}; | 271 | PFN_vkCreateImage vkCreateImage{}; |
| 272 | PFN_vkCreateImageView vkCreateImageView{}; | 272 | PFN_vkCreateImageView vkCreateImageView{}; |
| 273 | PFN_vkCreatePipelineCache vkCreatePipelineCache{}; | ||
| 273 | PFN_vkCreatePipelineLayout vkCreatePipelineLayout{}; | 274 | PFN_vkCreatePipelineLayout vkCreatePipelineLayout{}; |
| 274 | PFN_vkCreateQueryPool vkCreateQueryPool{}; | 275 | PFN_vkCreateQueryPool vkCreateQueryPool{}; |
| 275 | PFN_vkCreateRenderPass vkCreateRenderPass{}; | 276 | PFN_vkCreateRenderPass vkCreateRenderPass{}; |
| @@ -289,6 +290,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 289 | PFN_vkDestroyImage vkDestroyImage{}; | 290 | PFN_vkDestroyImage vkDestroyImage{}; |
| 290 | PFN_vkDestroyImageView vkDestroyImageView{}; | 291 | PFN_vkDestroyImageView vkDestroyImageView{}; |
| 291 | PFN_vkDestroyPipeline vkDestroyPipeline{}; | 292 | PFN_vkDestroyPipeline vkDestroyPipeline{}; |
| 293 | PFN_vkDestroyPipelineCache vkDestroyPipelineCache{}; | ||
| 292 | PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{}; | 294 | PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{}; |
| 293 | PFN_vkDestroyQueryPool vkDestroyQueryPool{}; | 295 | PFN_vkDestroyQueryPool vkDestroyQueryPool{}; |
| 294 | PFN_vkDestroyRenderPass vkDestroyRenderPass{}; | 296 | PFN_vkDestroyRenderPass vkDestroyRenderPass{}; |
| @@ -306,6 +308,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 306 | PFN_vkGetEventStatus vkGetEventStatus{}; | 308 | PFN_vkGetEventStatus vkGetEventStatus{}; |
| 307 | PFN_vkGetFenceStatus vkGetFenceStatus{}; | 309 | PFN_vkGetFenceStatus vkGetFenceStatus{}; |
| 308 | PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements{}; | 310 | PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements{}; |
| 311 | PFN_vkGetPipelineCacheData vkGetPipelineCacheData{}; | ||
| 309 | PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR{}; | 312 | PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR{}; |
| 310 | #ifdef _WIN32 | 313 | #ifdef _WIN32 |
| 311 | PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{}; | 314 | PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{}; |
| @@ -351,6 +354,7 @@ void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept; | |||
| 351 | void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept; | 354 | void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept; |
| 352 | void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept; | 355 | void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept; |
| 353 | void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept; | 356 | void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept; |
| 357 | void Destroy(VkDevice, VkPipelineCache, const DeviceDispatch&) noexcept; | ||
| 354 | void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept; | 358 | void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept; |
| 355 | void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept; | 359 | void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept; |
| 356 | void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept; | 360 | void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept; |
| @@ -773,6 +777,18 @@ public: | |||
| 773 | void SetObjectNameEXT(const char* name) const; | 777 | void SetObjectNameEXT(const char* name) const; |
| 774 | }; | 778 | }; |
| 775 | 779 | ||
| 780 | class PipelineCache : public Handle<VkPipelineCache, VkDevice, DeviceDispatch> { | ||
| 781 | using Handle<VkPipelineCache, VkDevice, DeviceDispatch>::Handle; | ||
| 782 | |||
| 783 | public: | ||
| 784 | /// Set object name. | ||
| 785 | void SetObjectNameEXT(const char* name) const; | ||
| 786 | |||
| 787 | VkResult Read(size_t* size, void* data) const noexcept { | ||
| 788 | return dld->vkGetPipelineCacheData(owner, handle, size, data); | ||
| 789 | } | ||
| 790 | }; | ||
| 791 | |||
| 776 | class Semaphore : public Handle<VkSemaphore, VkDevice, DeviceDispatch> { | 792 | class Semaphore : public Handle<VkSemaphore, VkDevice, DeviceDispatch> { |
| 777 | using Handle<VkSemaphore, VkDevice, DeviceDispatch>::Handle; | 793 | using Handle<VkSemaphore, VkDevice, DeviceDispatch>::Handle; |
| 778 | 794 | ||
| @@ -844,11 +860,15 @@ public: | |||
| 844 | 860 | ||
| 845 | DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const; | 861 | DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const; |
| 846 | 862 | ||
| 863 | PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const; | ||
| 864 | |||
| 847 | PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const; | 865 | PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const; |
| 848 | 866 | ||
| 849 | Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const; | 867 | Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci, |
| 868 | VkPipelineCache cache = nullptr) const; | ||
| 850 | 869 | ||
| 851 | Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const; | 870 | Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci, |
| 871 | VkPipelineCache cache = nullptr) const; | ||
| 852 | 872 | ||
| 853 | Sampler CreateSampler(const VkSamplerCreateInfo& ci) const; | 873 | Sampler CreateSampler(const VkSamplerCreateInfo& ci) const; |
| 854 | 874 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index e9425b5bd..fbfa3ba35 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -709,6 +709,7 @@ void Config::ReadRendererValues() { | |||
| 709 | ReadGlobalSetting(Settings::values.use_asynchronous_shaders); | 709 | ReadGlobalSetting(Settings::values.use_asynchronous_shaders); |
| 710 | ReadGlobalSetting(Settings::values.use_fast_gpu_time); | 710 | ReadGlobalSetting(Settings::values.use_fast_gpu_time); |
| 711 | ReadGlobalSetting(Settings::values.use_pessimistic_flushes); | 711 | ReadGlobalSetting(Settings::values.use_pessimistic_flushes); |
| 712 | ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 712 | ReadGlobalSetting(Settings::values.bg_red); | 713 | ReadGlobalSetting(Settings::values.bg_red); |
| 713 | ReadGlobalSetting(Settings::values.bg_green); | 714 | ReadGlobalSetting(Settings::values.bg_green); |
| 714 | ReadGlobalSetting(Settings::values.bg_blue); | 715 | ReadGlobalSetting(Settings::values.bg_blue); |
| @@ -1348,6 +1349,7 @@ void Config::SaveRendererValues() { | |||
| 1348 | WriteGlobalSetting(Settings::values.use_asynchronous_shaders); | 1349 | WriteGlobalSetting(Settings::values.use_asynchronous_shaders); |
| 1349 | WriteGlobalSetting(Settings::values.use_fast_gpu_time); | 1350 | WriteGlobalSetting(Settings::values.use_fast_gpu_time); |
| 1350 | WriteGlobalSetting(Settings::values.use_pessimistic_flushes); | 1351 | WriteGlobalSetting(Settings::values.use_pessimistic_flushes); |
| 1352 | WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 1351 | WriteGlobalSetting(Settings::values.bg_red); | 1353 | WriteGlobalSetting(Settings::values.bg_red); |
| 1352 | WriteGlobalSetting(Settings::values.bg_green); | 1354 | WriteGlobalSetting(Settings::values.bg_green); |
| 1353 | WriteGlobalSetting(Settings::values.bg_blue); | 1355 | WriteGlobalSetting(Settings::values.bg_blue); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 01f074699..a3fbe2ad0 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -29,6 +29,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 29 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); | 29 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); |
| 30 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); | 30 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); |
| 31 | ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue()); | 31 | ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue()); |
| 32 | ui->use_vulkan_driver_pipeline_cache->setChecked( | ||
| 33 | Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); | ||
| 32 | 34 | ||
| 33 | if (Settings::IsConfiguringGlobal()) { | 35 | if (Settings::IsConfiguringGlobal()) { |
| 34 | ui->gpu_accuracy->setCurrentIndex( | 36 | ui->gpu_accuracy->setCurrentIndex( |
| @@ -58,6 +60,9 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 58 | ui->use_fast_gpu_time, use_fast_gpu_time); | 60 | ui->use_fast_gpu_time, use_fast_gpu_time); |
| 59 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_pessimistic_flushes, | 61 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_pessimistic_flushes, |
| 60 | ui->use_pessimistic_flushes, use_pessimistic_flushes); | 62 | ui->use_pessimistic_flushes, use_pessimistic_flushes); |
| 63 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache, | ||
| 64 | ui->use_vulkan_driver_pipeline_cache, | ||
| 65 | use_vulkan_driver_pipeline_cache); | ||
| 61 | } | 66 | } |
| 62 | 67 | ||
| 63 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { | 68 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { |
| @@ -82,6 +87,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 82 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); | 87 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); |
| 83 | ui->use_pessimistic_flushes->setEnabled( | 88 | ui->use_pessimistic_flushes->setEnabled( |
| 84 | Settings::values.use_pessimistic_flushes.UsingGlobal()); | 89 | Settings::values.use_pessimistic_flushes.UsingGlobal()); |
| 90 | ui->use_vulkan_driver_pipeline_cache->setEnabled( | ||
| 91 | Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal()); | ||
| 85 | ui->anisotropic_filtering_combobox->setEnabled( | 92 | ui->anisotropic_filtering_combobox->setEnabled( |
| 86 | Settings::values.max_anisotropy.UsingGlobal()); | 93 | Settings::values.max_anisotropy.UsingGlobal()); |
| 87 | 94 | ||
| @@ -97,6 +104,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 97 | ConfigurationShared::SetColoredTristate(ui->use_pessimistic_flushes, | 104 | ConfigurationShared::SetColoredTristate(ui->use_pessimistic_flushes, |
| 98 | Settings::values.use_pessimistic_flushes, | 105 | Settings::values.use_pessimistic_flushes, |
| 99 | use_pessimistic_flushes); | 106 | use_pessimistic_flushes); |
| 107 | ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache, | ||
| 108 | Settings::values.use_vulkan_driver_pipeline_cache, | ||
| 109 | use_vulkan_driver_pipeline_cache); | ||
| 100 | ConfigurationShared::SetColoredComboBox( | 110 | ConfigurationShared::SetColoredComboBox( |
| 101 | ui->gpu_accuracy, ui->label_gpu_accuracy, | 111 | ui->gpu_accuracy, ui->label_gpu_accuracy, |
| 102 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); | 112 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index 12e816905..891efc068 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h | |||
| @@ -40,6 +40,7 @@ private: | |||
| 40 | ConfigurationShared::CheckState use_asynchronous_shaders; | 40 | ConfigurationShared::CheckState use_asynchronous_shaders; |
| 41 | ConfigurationShared::CheckState use_fast_gpu_time; | 41 | ConfigurationShared::CheckState use_fast_gpu_time; |
| 42 | ConfigurationShared::CheckState use_pessimistic_flushes; | 42 | ConfigurationShared::CheckState use_pessimistic_flushes; |
| 43 | ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; | ||
| 43 | 44 | ||
| 44 | const Core::System& system; | 45 | const Core::System& system; |
| 45 | }; | 46 | }; |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 87a121471..ccbdcf08f 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui | |||
| @@ -110,6 +110,16 @@ | |||
| 110 | </widget> | 110 | </widget> |
| 111 | </item> | 111 | </item> |
| 112 | <item> | 112 | <item> |
| 113 | <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache"> | ||
| 114 | <property name="toolTip"> | ||
| 115 | <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string> | ||
| 116 | </property> | ||
| 117 | <property name="text"> | ||
| 118 | <string>Use Vulkan pipeline cache</string> | ||
| 119 | </property> | ||
| 120 | </widget> | ||
| 121 | </item> | ||
| 122 | <item> | ||
| 113 | <widget class="QWidget" name="af_layout" native="true"> | 123 | <widget class="QWidget" name="af_layout" native="true"> |
| 114 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | 124 | <layout class="QHBoxLayout" name="horizontalLayout_1"> |
| 115 | <property name="leftMargin"> | 125 | <property name="leftMargin"> |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 524650144..c55f81c2f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2229,8 +2229,10 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ | |||
| 2229 | } | 2229 | } |
| 2230 | 2230 | ||
| 2231 | switch (target) { | 2231 | switch (target) { |
| 2232 | case GameListRemoveTarget::GlShaderCache: | ||
| 2233 | case GameListRemoveTarget::VkShaderCache: | 2232 | case GameListRemoveTarget::VkShaderCache: |
| 2233 | RemoveVulkanDriverPipelineCache(program_id); | ||
| 2234 | [[fallthrough]]; | ||
| 2235 | case GameListRemoveTarget::GlShaderCache: | ||
| 2234 | RemoveTransferableShaderCache(program_id, target); | 2236 | RemoveTransferableShaderCache(program_id, target); |
| 2235 | break; | 2237 | break; |
| 2236 | case GameListRemoveTarget::AllShaderCache: | 2238 | case GameListRemoveTarget::AllShaderCache: |
| @@ -2271,6 +2273,22 @@ void GMainWindow::RemoveTransferableShaderCache(u64 program_id, GameListRemoveTa | |||
| 2271 | } | 2273 | } |
| 2272 | } | 2274 | } |
| 2273 | 2275 | ||
| 2276 | void GMainWindow::RemoveVulkanDriverPipelineCache(u64 program_id) { | ||
| 2277 | static constexpr std::string_view target_file_name = "vulkan_pipelines.bin"; | ||
| 2278 | |||
| 2279 | const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir); | ||
| 2280 | const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id); | ||
| 2281 | const auto target_file = shader_cache_folder_path / target_file_name; | ||
| 2282 | |||
| 2283 | if (!Common::FS::Exists(target_file)) { | ||
| 2284 | return; | ||
| 2285 | } | ||
| 2286 | if (!Common::FS::RemoveFile(target_file)) { | ||
| 2287 | QMessageBox::warning(this, tr("Error Removing Vulkan Driver Pipeline Cache"), | ||
| 2288 | tr("Failed to remove the driver pipeline cache.")); | ||
| 2289 | } | ||
| 2290 | } | ||
| 2291 | |||
| 2274 | void GMainWindow::RemoveAllTransferableShaderCaches(u64 program_id) { | 2292 | void GMainWindow::RemoveAllTransferableShaderCaches(u64 program_id) { |
| 2275 | const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir); | 2293 | const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir); |
| 2276 | const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id); | 2294 | const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id); |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index db318485d..f25ce65a8 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -347,6 +347,7 @@ private: | |||
| 347 | void RemoveUpdateContent(u64 program_id, InstalledEntryType type); | 347 | void RemoveUpdateContent(u64 program_id, InstalledEntryType type); |
| 348 | void RemoveAddOnContent(u64 program_id, InstalledEntryType type); | 348 | void RemoveAddOnContent(u64 program_id, InstalledEntryType type); |
| 349 | void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target); | 349 | void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target); |
| 350 | void RemoveVulkanDriverPipelineCache(u64 program_id); | ||
| 350 | void RemoveAllTransferableShaderCaches(u64 program_id); | 351 | void RemoveAllTransferableShaderCaches(u64 program_id); |
| 351 | void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); | 352 | void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); |
| 352 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); | 353 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 1e45e57bc..b2d690bb6 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -321,6 +321,7 @@ void Config::ReadValues() { | |||
| 321 | ReadSetting("Renderer", Settings::values.accelerate_astc); | 321 | ReadSetting("Renderer", Settings::values.accelerate_astc); |
| 322 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | 322 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); |
| 323 | ReadSetting("Renderer", Settings::values.use_pessimistic_flushes); | 323 | ReadSetting("Renderer", Settings::values.use_pessimistic_flushes); |
| 324 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 324 | 325 | ||
| 325 | ReadSetting("Renderer", Settings::values.bg_red); | 326 | ReadSetting("Renderer", Settings::values.bg_red); |
| 326 | ReadSetting("Renderer", Settings::values.bg_green); | 327 | ReadSetting("Renderer", Settings::values.bg_green); |