diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index e96a04b00..73e585c2b 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -25,14 +25,14 @@ using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; using Tegra::Texture::TexturePair; ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_, - std::mutex& pipeline_cache_mutex_, DescriptorPool& descriptor_pool, + DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue_, Common::ThreadWorker* thread_worker, PipelineStatistics* pipeline_statistics, VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, vk::ShaderModule spv_module_) - : device{device_}, pipeline_cache(pipeline_cache_), pipeline_cache_mutex(pipeline_cache_mutex_), - guest_descriptor_queue{guest_descriptor_queue_}, info{info_}, + : device{device_}, + pipeline_cache(pipeline_cache_), guest_descriptor_queue{guest_descriptor_queue_}, info{info_}, spv_module(std::move(spv_module_)) { if (shader_notify) { shader_notify->MarkShaderBuilding(); @@ -58,7 +58,6 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel if (device.IsKhrPipelineExecutablePropertiesEnabled()) { flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; } - std::scoped_lock cache_lock{pipeline_cache_mutex}; pipeline = device.GetLogical().CreateComputePipeline( { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 28e894ded..d1a1e2c46 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h @@ -3,12 +3,10 @@ #pragma once -#include #include #include #include - #include "common/common_types.h" #include "common/thread_worker.h" #include "shader_recompiler/shader_info.h" @@ -31,7 +29,7 @@ class Scheduler; class ComputePipeline { public: explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache, - std::mutex& pipeline_cache_mutex, DescriptorPool& descriptor_pool, + DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue, Common::ThreadWorker* thread_worker, PipelineStatistics* pipeline_statistics, @@ -50,7 +48,6 @@ public: private: const Device& device; vk::PipelineCache& pipeline_cache; - std::mutex& pipeline_cache_mutex; GuestDescriptorQueue& guest_descriptor_queue; Shader::Info info; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 6b705c298..d92af0ece 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -88,8 +88,7 @@ bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { bool IsLine(VkPrimitiveTopology topology) { static constexpr std::array line_topologies{ - VK_PRIMITIVE_TOPOLOGY_LINE_LIST, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, // VK_PRIMITIVE_TOPOLOGY_LINE_LOOP_EXT, }; return std::ranges::find(line_topologies, topology) == line_topologies.end(); @@ -238,16 +237,15 @@ ConfigureFuncPtr ConfigureFunc(const std::array& m GraphicsPipeline::GraphicsPipeline( Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, - vk::PipelineCache& pipeline_cache_, std::mutex& pipeline_cache_mutex_, - VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, + vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify, + const Device& device_, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue_, Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key_, std::array stages, const std::array& infos) : key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, - pipeline_cache(pipeline_cache_), pipeline_cache_mutex(pipeline_cache_mutex_), - scheduler{scheduler_}, guest_descriptor_queue{guest_descriptor_queue_}, - spv_modules{std::move(stages)} { + pipeline_cache(pipeline_cache_), scheduler{scheduler_}, + guest_descriptor_queue{guest_descriptor_queue_}, spv_modules{std::move(stages)} { if (shader_notify) { shader_notify->MarkShaderBuilding(); } @@ -927,7 +925,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { if (device.IsKhrPipelineExecutablePropertiesEnabled()) { flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; } - std::scoped_lock lock{pipeline_cache_mutex}; pipeline = device.GetLogical().CreateGraphicsPipeline( { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index e4d1b30fc..99e56e9ad 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -71,12 +71,11 @@ class GraphicsPipeline { public: explicit GraphicsPipeline( Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, - vk::PipelineCache& pipeline_cache, std::mutex& pipeline_cache_mutex, - VideoCore::ShaderNotify* shader_notify, const Device& device, - DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue, - Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics, - RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key, - std::array stages, + vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify, + const Device& device, DescriptorPool& descriptor_pool, + GuestDescriptorQueue& guest_descriptor_queue, Common::ThreadWorker* worker_thread, + PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, + const GraphicsPipelineCacheKey& key, std::array stages, const std::array& infos); GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; @@ -132,7 +131,6 @@ private: TextureCache& texture_cache; BufferCache& buffer_cache; vk::PipelineCache& pipeline_cache; - std::mutex& pipeline_cache_mutex; Scheduler& scheduler; GuestDescriptorQueue& guest_descriptor_queue; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 250ce5373..772e7634c 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -677,6 +677,11 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const if (pipeline->IsBuilt()) { return pipeline; } + if (!use_asynchronous_shaders) { + return pipeline; + } + // When asynchronous shaders are enabled, avoid blocking the main thread completely. + // Skip the draw until the pipeline is ready to prevent stutter. return nullptr; } @@ -764,11 +769,10 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( previous_stage = &program; } Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; - auto pipeline{std::make_unique( - scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, pipeline_cache_mutex, - &shader_notify, device, descriptor_pool, guest_descriptor_queue, thread_worker, statistics, - render_pass_cache, key, std::move(modules), infos)}; - return pipeline; + return std::make_unique( + scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device, + descriptor_pool, guest_descriptor_queue, thread_worker, statistics, render_pass_cache, key, + std::move(modules), infos); } catch (const vk::Exception& exception) { if (exception.GetResult() == VK_ERROR_OUT_OF_DEVICE_MEMORY) { @@ -800,7 +804,6 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline() { GraphicsEnvironments environments; GetGraphicsEnvironments(environments, graphics_key.unique_hashes); - std::scoped_lock lock{pools_mutex}; main_pools.ReleaseContents(); auto pipeline{ CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), nullptr, true)}; @@ -827,7 +830,6 @@ std::unique_ptr PipelineCache::CreateComputePipeline( ComputeEnvironment env{*kepler_compute, *gpu_memory, program_base, qmd.program_start}; env.SetCachedSize(shader->size_bytes); - std::scoped_lock lock{pools_mutex}; main_pools.ReleaseContents(); auto pipeline{CreateComputePipeline(main_pools, key, env, nullptr, true)}; if (!pipeline || pipeline_cache_filename.empty()) { @@ -872,10 +874,9 @@ std::unique_ptr PipelineCache::CreateComputePipeline( spv_module.SetObjectNameEXT(name.c_str()); } Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; - return std::make_unique(device, vulkan_pipeline_cache, pipeline_cache_mutex, - descriptor_pool, guest_descriptor_queue, thread_worker, - statistics, &shader_notify, program.info, - std::move(spv_module)); + return std::make_unique(device, vulkan_pipeline_cache, descriptor_pool, + guest_descriptor_queue, thread_worker, statistics, + &shader_notify, program.info, std::move(spv_module)); } catch (const vk::Exception& exception) { if (exception.GetResult() == VK_ERROR_OUT_OF_DEVICE_MEMORY) { @@ -903,7 +904,6 @@ void PipelineCache::SerializeVulkanPipelineCache(const std::filesystem::path& fi file.write(VULKAN_CACHE_MAGIC_NUMBER.data(), VULKAN_CACHE_MAGIC_NUMBER.size()) .write(reinterpret_cast(&cache_version), sizeof(cache_version)); - std::scoped_lock lock{pipeline_cache_mutex}; size_t cache_size = 0; std::vector cache_data; if (pipeline_cache) { diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index e3cb3078a..8846a8337 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -177,8 +176,6 @@ public: static constexpr u64 MEMORY_PRESSURE_COOLDOWN = 300; ShaderPools main_pools; - std::mutex pools_mutex; - std::mutex pipeline_cache_mutex; Shader::Profile profile; Shader::HostTranslateInfo host_info; diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 523ca42ce..456dcf17c 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -64,35 +64,35 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, return mode; } switch (mode) { - case Settings::VSyncMode::Fifo: - case Settings::VSyncMode::FifoRelaxed: - if (has_mailbox) { - return Settings::VSyncMode::Mailbox; - } else if (has_imm) { - return Settings::VSyncMode::Immediate; - } - [[fallthrough]]; - default: - return mode; + case Settings::VSyncMode::Fifo: + case Settings::VSyncMode::FifoRelaxed: + if (has_mailbox) { + return Settings::VSyncMode::Mailbox; + } else if (has_imm) { + return Settings::VSyncMode::Immediate; + } + [[fallthrough]]; + default: + return mode; } }(); if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) || (setting == Settings::VSyncMode::Immediate && !has_imm) || (setting == Settings::VSyncMode::FifoRelaxed && !has_fifo_relaxed)) { setting = Settings::VSyncMode::Fifo; - } + } - switch (setting) { - case Settings::VSyncMode::Immediate: - return VK_PRESENT_MODE_IMMEDIATE_KHR; - case Settings::VSyncMode::Mailbox: - return VK_PRESENT_MODE_MAILBOX_KHR; - case Settings::VSyncMode::Fifo: - return VK_PRESENT_MODE_FIFO_KHR; - case Settings::VSyncMode::FifoRelaxed: - return VK_PRESENT_MODE_FIFO_RELAXED_KHR; - default: - return VK_PRESENT_MODE_FIFO_KHR; + switch (setting) { + case Settings::VSyncMode::Immediate: + return VK_PRESENT_MODE_IMMEDIATE_KHR; + case Settings::VSyncMode::Mailbox: + return VK_PRESENT_MODE_MAILBOX_KHR; + case Settings::VSyncMode::Fifo: + return VK_PRESENT_MODE_FIFO_KHR; + case Settings::VSyncMode::FifoRelaxed: + return VK_PRESENT_MODE_FIFO_RELAXED_KHR; + default: + return VK_PRESENT_MODE_FIFO_KHR; } } @@ -174,7 +174,7 @@ bool Swapchain::AcquireNextImage() { break; } - scheduler.GetMasterSemaphore().Wait(resource_ticks[image_index]); + scheduler.Wait(resource_ticks[image_index]); resource_ticks[image_index] = scheduler.CurrentTick(); return is_suboptimal || is_outdated;