diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 95c67f865a..127a23637f 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -811,7 +811,7 @@ void BufferCache
::BindHostVertexBuffers() {
if (use_optimized_vertex_buffers) {
auto& flags = maxwell3d->dirty.flags;
const u32 enabled_mask = enabled_vertex_buffers_mask;
- bool any_dirty = false;
+ u32 dirty_mask = 0;
u32 pending_mask = enabled_mask;
while (pending_mask != 0) {
const u32 index = std::countr_zero(pending_mask);
@@ -820,13 +820,15 @@ void BufferCache
::BindHostVertexBuffers() {
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer, binding.buffer_id);
SynchronizeBuffer(buffer, binding.device_addr, binding.size);
- any_dirty |= flags[Dirty::VertexBuffer0 + index];
+ if (flags[Dirty::VertexBuffer0 + index]) {
+ dirty_mask |= 1u << index;
+ }
}
- if (enabled_mask == 0 || !any_dirty) {
+ if (dirty_mask == 0) {
return;
}
- const u32 min_index = static_cast(std::countr_zero(enabled_mask));
- const u32 max_index = 32u - static_cast(std::countl_zero(enabled_mask));
+ const u32 min_index = static_cast(std::countr_zero(dirty_mask));
+ const u32 max_index = 32u - static_cast(std::countl_zero(dirty_mask));
HostBindings bindings{};
bindings.min_index = min_index;
bindings.max_index = max_index;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 29356cfcec..6c2ba89026 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -32,6 +32,7 @@ using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
using Tegra::Texture::TexturePair;
ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk::PipelineCache& pipeline_cache_,
+ std::shared_mutex& pipeline_cache_mutex_,
DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue_,
DescriptorBufferRing& descriptor_buffer_ring_,
@@ -40,7 +41,8 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk
VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_,
vk::ShaderModule spv_module_, u64 shader_hash_)
: device{device_},
- pipeline_cache(pipeline_cache_), guest_descriptor_queue{guest_descriptor_queue_},
+ pipeline_cache(pipeline_cache_), pipeline_cache_mutex(pipeline_cache_mutex_),
+ guest_descriptor_queue{guest_descriptor_queue_},
descriptor_buffer_ring{descriptor_buffer_ring_}, info{info_},
shader_hash{shader_hash_}, spv_module(std::move(spv_module_)) {
if (shader_notify) {
@@ -111,6 +113,7 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk
.basePipelineIndex = 0,
};
try {
+ std::shared_lock cache_lock{pipeline_cache_mutex};
pipeline = device.GetLogical().CreateComputePipeline(compute_ci, *pipeline_cache);
} catch (const vk::Exception& exception) {
LOG_CRITICAL(Render_Vulkan, "Adreno rejected compute shader {:016X}: {}", shader_hash,
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index fba0519b58..65d4bb1382 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include "common/common_types.h"
#include "common/thread_worker.h"
@@ -34,6 +35,7 @@ class Scheduler;
class ComputePipeline {
public:
explicit ComputePipeline(const Device& device, Scheduler& scheduler, vk::PipelineCache& pipeline_cache,
+ std::shared_mutex& pipeline_cache_mutex,
DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue,
DescriptorBufferRing& descriptor_buffer_ring,
@@ -59,6 +61,7 @@ public:
private:
const Device& device;
vk::PipelineCache& pipeline_cache;
+ std::shared_mutex& pipeline_cache_mutex;
GuestDescriptorQueue& guest_descriptor_queue;
DescriptorBufferRing& descriptor_buffer_ring;
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 a2eee7f16d..554cc038ef 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -251,7 +251,8 @@ ConfigureFuncPtr ConfigureFunc(const std::array& m
// TODO(crueter): This is the worst-formatted code I have EVER seen
GraphicsPipeline::GraphicsPipeline(
Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
- vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify,
+ vk::PipelineCache& pipeline_cache_, std::shared_mutex& pipeline_cache_mutex_,
+ VideoCore::ShaderNotify* shader_notify,
const Device& device_, DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue_, DescriptorBufferRing& descriptor_buffer_ring_,
Common::ThreadWorker* worker_thread,
@@ -259,7 +260,8 @@ GraphicsPipeline::GraphicsPipeline(
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_), scheduler{scheduler_},
+ pipeline_cache(pipeline_cache_), pipeline_cache_mutex(pipeline_cache_mutex_),
+ scheduler{scheduler_},
guest_descriptor_queue{guest_descriptor_queue_},
descriptor_buffer_ring{descriptor_buffer_ring_}, spv_modules{std::move(stages)} {
if (shader_notify) {
@@ -1081,6 +1083,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
+ std::shared_lock cache_lock{pipeline_cache_mutex};
pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index b1ac5a3fcc..ebb92a8f16 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include
#include
@@ -78,7 +79,8 @@ class GraphicsPipeline {
public:
explicit GraphicsPipeline(
Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
- vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify,
+ vk::PipelineCache& pipeline_cache, std::shared_mutex& pipeline_cache_mutex,
+ VideoCore::ShaderNotify* shader_notify,
const Device& device, DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue,
DescriptorBufferRing& descriptor_buffer_ring, Common::ThreadWorker* worker_thread,
@@ -151,6 +153,7 @@ private:
TextureCache& texture_cache;
BufferCache& buffer_cache;
vk::PipelineCache& pipeline_cache;
+ std::shared_mutex& pipeline_cache_mutex;
Scheduler& scheduler;
GuestDescriptorQueue& guest_descriptor_queue;
DescriptorBufferRing& descriptor_buffer_ring;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 96007ec276..d1948fa59b 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -553,6 +553,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
PipelineCache::~PipelineCache() {
if (use_vulkan_pipeline_cache && !vulkan_pipeline_cache_filename.empty()) {
+ std::unique_lock lock{vulkan_pipeline_cache_mutex};
SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
CACHE_VERSION);
}
@@ -612,6 +613,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
if (use_vulkan_pipeline_cache) {
vulkan_pipeline_cache_filename = base_dir / "vulkan_pipelines.bin";
+ std::unique_lock lock{vulkan_pipeline_cache_mutex};
vulkan_pipeline_cache =
LoadVulkanPipelineCache(vulkan_pipeline_cache_filename, CACHE_VERSION);
}
@@ -710,6 +712,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
workers.WaitForRequests(stop_loading);
if (use_vulkan_pipeline_cache) {
+ std::unique_lock lock{vulkan_pipeline_cache_mutex};
SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
CACHE_VERSION);
size_t size = 0;
@@ -743,11 +746,14 @@ void PipelineCache::QueueVulkanPipelineCacheFlush() {
pipelines_since_flush = 0;
last_flush = now;
serialization_thread.QueueWork([this] {
- SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
- CACHE_VERSION);
- size_t size = 0;
- vulkan_pipeline_cache.Read(&size, nullptr);
- last_cache_size.store(size, std::memory_order_relaxed);
+ {
+ std::unique_lock lock{vulkan_pipeline_cache_mutex};
+ SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
+ CACHE_VERSION);
+ size_t size = 0;
+ vulkan_pipeline_cache.Read(&size, nullptr);
+ last_cache_size.store(size, std::memory_order_relaxed);
+ }
flush_in_flight.store(false, std::memory_order_release);
});
}
@@ -890,7 +896,8 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline(
}
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique(
- scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device,
+ scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache,
+ vulkan_pipeline_cache_mutex, &shader_notify, device,
descriptor_pool, guest_descriptor_queue, descriptor_buffer_ring, thread_worker, statistics,
render_pass_cache, key, std::move(modules), infos);
@@ -1014,7 +1021,8 @@ 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, scheduler, vulkan_pipeline_cache, descriptor_pool,
+ return std::make_unique(device, scheduler, vulkan_pipeline_cache,
+ vulkan_pipeline_cache_mutex, descriptor_pool,
guest_descriptor_queue, descriptor_buffer_ring,
thread_worker, statistics,
&shader_notify, program.info, std::move(spv_module),
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 9d66b663f5..94cf733890 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -12,6 +12,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -175,6 +177,7 @@ private:
std::filesystem::path vulkan_pipeline_cache_filename;
vk::PipelineCache vulkan_pipeline_cache;
+ std::shared_mutex vulkan_pipeline_cache_mutex;
size_t pipelines_since_flush{};
std::chrono::steady_clock::time_point last_flush{};
std::atomic last_cache_size{};