diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/settings.cpp | 1 | ||||
| -rw-r--r-- | src/common/settings.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 51 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 128 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.h | 10 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.h | 24 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics_advanced.cpp | 10 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics_advanced.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics_advanced.ui | 10 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 20 | ||||
| -rw-r--r-- | src/yuzu/main.h | 1 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 1 |
17 files changed, 285 insertions, 68 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/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 734c379b9..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(); |
| @@ -897,27 +898,29 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 897 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { | 898 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { |
| 898 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | 899 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; |
| 899 | } | 900 | } |
| 900 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | 901 | pipeline = device.GetLogical().CreateGraphicsPipeline( |
| 901 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | 902 | { |
| 902 | .pNext = nullptr, | 903 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
| 903 | .flags = flags, | 904 | .pNext = nullptr, |
| 904 | .stageCount = static_cast<u32>(shader_stages.size()), | 905 | .flags = flags, |
| 905 | .pStages = shader_stages.data(), | 906 | .stageCount = static_cast<u32>(shader_stages.size()), |
| 906 | .pVertexInputState = &vertex_input_ci, | 907 | .pStages = shader_stages.data(), |
| 907 | .pInputAssemblyState = &input_assembly_ci, | 908 | .pVertexInputState = &vertex_input_ci, |
| 908 | .pTessellationState = &tessellation_ci, | 909 | .pInputAssemblyState = &input_assembly_ci, |
| 909 | .pViewportState = &viewport_ci, | 910 | .pTessellationState = &tessellation_ci, |
| 910 | .pRasterizationState = &rasterization_ci, | 911 | .pViewportState = &viewport_ci, |
| 911 | .pMultisampleState = &multisample_ci, | 912 | .pRasterizationState = &rasterization_ci, |
| 912 | .pDepthStencilState = &depth_stencil_ci, | 913 | .pMultisampleState = &multisample_ci, |
| 913 | .pColorBlendState = &color_blend_ci, | 914 | .pDepthStencilState = &depth_stencil_ci, |
| 914 | .pDynamicState = &dynamic_state_ci, | 915 | .pColorBlendState = &color_blend_ci, |
| 915 | .layout = *pipeline_layout, | 916 | .pDynamicState = &dynamic_state_ci, |
| 916 | .renderPass = render_pass, | 917 | .layout = *pipeline_layout, |
| 917 | .subpass = 0, | 918 | .renderPass = render_pass, |
| 918 | .basePipelineHandle = nullptr, | 919 | .subpass = 0, |
| 919 | .basePipelineIndex = 0, | 920 | .basePipelineHandle = nullptr, |
| 920 | }); | 921 | .basePipelineIndex = 0, |
| 922 | }, | ||
| 923 | *pipeline_cache); | ||
| 921 | } | 924 | } |
| 922 | 925 | ||
| 923 | 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_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); |