summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp95
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h30
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp72
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h31
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp78
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h24
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h7
9 files changed, 197 insertions, 165 deletions
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 8e544d745..1c3249e3c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -27,8 +27,9 @@ DescriptorLayoutTuple CreateLayout(const Device& device, const Shader::Info& inf
27 27
28ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, 28ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool,
29 VKUpdateDescriptorQueue& update_descriptor_queue_, 29 VKUpdateDescriptorQueue& update_descriptor_queue_,
30 const Shader::Info& info_, vk::ShaderModule spv_module_) 30 Common::ThreadWorker* thread_worker, const Shader::Info& info_,
31 : update_descriptor_queue{&update_descriptor_queue_}, info{info_}, 31 vk::ShaderModule spv_module_)
32 : update_descriptor_queue{update_descriptor_queue_}, info{info_},
32 spv_module(std::move(spv_module_)) { 33 spv_module(std::move(spv_module_)) {
33 DescriptorLayoutTuple tuple{CreateLayout(device, info)}; 34 DescriptorLayoutTuple tuple{CreateLayout(device, info)};
34 descriptor_set_layout = std::move(tuple.descriptor_set_layout); 35 descriptor_set_layout = std::move(tuple.descriptor_set_layout);
@@ -36,46 +37,55 @@ ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descrip
36 descriptor_update_template = std::move(tuple.descriptor_update_template); 37 descriptor_update_template = std::move(tuple.descriptor_update_template);
37 descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); 38 descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout);
38 39
39 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ 40 auto func{[this, &device] {
40 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, 41 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
41 .pNext = nullptr, 42 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
42 .requiredSubgroupSize = GuestWarpSize, 43 .pNext = nullptr,
43 }; 44 .requiredSubgroupSize = GuestWarpSize,
44 pipeline = device.GetLogical().CreateComputePipeline({ 45 };
45 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, 46 pipeline = device.GetLogical().CreateComputePipeline({
46 .pNext = nullptr, 47 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
47 .flags = 0, 48 .pNext = nullptr,
48 .stage{
49 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
50 .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr,
51 .flags = 0, 49 .flags = 0,
52 .stage = VK_SHADER_STAGE_COMPUTE_BIT, 50 .stage{
53 .module = *spv_module, 51 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
54 .pName = "main", 52 .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr,
55 .pSpecializationInfo = nullptr, 53 .flags = 0,
56 }, 54 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
57 .layout = *pipeline_layout, 55 .module = *spv_module,
58 .basePipelineHandle = 0, 56 .pName = "main",
59 .basePipelineIndex = 0, 57 .pSpecializationInfo = nullptr,
60 }); 58 },
59 .layout = *pipeline_layout,
60 .basePipelineHandle = 0,
61 .basePipelineIndex = 0,
62 });
63 building_flag.test_and_set();
64 building_flag.notify_all();
65 }};
66 if (thread_worker) {
67 thread_worker->QueueWork(std::move(func));
68 } else {
69 func();
70 }
61} 71}
62 72
63void ComputePipeline::ConfigureBufferCache(BufferCache& buffer_cache) { 73void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
74 Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler,
75 BufferCache& buffer_cache, TextureCache& texture_cache) {
76 update_descriptor_queue.Acquire();
77
64 buffer_cache.SetEnabledComputeUniformBuffers(info.constant_buffer_mask); 78 buffer_cache.SetEnabledComputeUniformBuffers(info.constant_buffer_mask);
65 buffer_cache.UnbindComputeStorageBuffers(); 79 buffer_cache.UnbindComputeStorageBuffers();
66 size_t index{}; 80 size_t ssbo_index{};
67 for (const auto& desc : info.storage_buffers_descriptors) { 81 for (const auto& desc : info.storage_buffers_descriptors) {
68 ASSERT(desc.count == 1); 82 ASSERT(desc.count == 1);
69 buffer_cache.BindComputeStorageBuffer(index, desc.cbuf_index, desc.cbuf_offset, true); 83 buffer_cache.BindComputeStorageBuffer(ssbo_index, desc.cbuf_index, desc.cbuf_offset, true);
70 ++index; 84 ++ssbo_index;
71 } 85 }
72 buffer_cache.UpdateComputeBuffers(); 86 buffer_cache.UpdateComputeBuffers();
73 buffer_cache.BindHostComputeBuffers(); 87 buffer_cache.BindHostComputeBuffers();
74}
75 88
76void ComputePipeline::ConfigureTextureCache(Tegra::Engines::KeplerCompute& kepler_compute,
77 Tegra::MemoryManager& gpu_memory,
78 TextureCache& texture_cache) {
79 texture_cache.SynchronizeComputeDescriptors(); 89 texture_cache.SynchronizeComputeDescriptors();
80 90
81 static constexpr size_t max_elements = 64; 91 static constexpr size_t max_elements = 64;
@@ -103,15 +113,26 @@ void ComputePipeline::ConfigureTextureCache(Tegra::Engines::KeplerCompute& keple
103 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 113 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
104 texture_cache.FillComputeImageViews(indices_span, image_view_ids); 114 texture_cache.FillComputeImageViews(indices_span, image_view_ids);
105 115
106 size_t index{}; 116 size_t image_index{};
107 PushImageDescriptors(info, samplers.data(), image_view_ids.data(), texture_cache, 117 PushImageDescriptors(info, samplers.data(), image_view_ids.data(), texture_cache,
108 *update_descriptor_queue, index); 118 update_descriptor_queue, image_index);
109}
110 119
111VkDescriptorSet ComputePipeline::UpdateDescriptorSet() { 120 if (!building_flag.test()) {
121 // Wait for the pipeline to be built
122 scheduler.Record([this](vk::CommandBuffer) { building_flag.wait(false); });
123 }
124 scheduler.Record([this](vk::CommandBuffer cmdbuf) {
125 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
126 });
127 if (!descriptor_set_layout) {
128 return;
129 }
112 const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; 130 const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
113 update_descriptor_queue->Send(*descriptor_update_template, descriptor_set); 131 update_descriptor_queue.Send(*descriptor_update_template, descriptor_set);
114 return descriptor_set; 132 scheduler.Record([this, descriptor_set](vk::CommandBuffer cmdbuf) {
133 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
134 descriptor_set, nullptr);
135 });
115} 136}
116 137
117} // namespace Vulkan 138} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index e82e5816b..02da504f7 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -4,7 +4,10 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
8
7#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/thread_worker.h"
8#include "shader_recompiler/shader_info.h" 11#include "shader_recompiler/shader_info.h"
9#include "video_core/memory_manager.h" 12#include "video_core/memory_manager.h"
10#include "video_core/renderer_vulkan/vk_buffer_cache.h" 13#include "video_core/renderer_vulkan/vk_buffer_cache.h"
@@ -16,36 +19,26 @@
16namespace Vulkan { 19namespace Vulkan {
17 20
18class Device; 21class Device;
22class VKScheduler;
19 23
20class ComputePipeline { 24class ComputePipeline {
21public: 25public:
22 explicit ComputePipeline() = default;
23 explicit ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, 26 explicit ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool,
24 VKUpdateDescriptorQueue& update_descriptor_queue, 27 VKUpdateDescriptorQueue& update_descriptor_queue,
25 const Shader::Info& info, vk::ShaderModule spv_module); 28 Common::ThreadWorker* thread_worker, const Shader::Info& info,
29 vk::ShaderModule spv_module);
26 30
27 ComputePipeline& operator=(ComputePipeline&&) noexcept = default; 31 ComputePipeline& operator=(ComputePipeline&&) noexcept = delete;
28 ComputePipeline(ComputePipeline&&) noexcept = default; 32 ComputePipeline(ComputePipeline&&) noexcept = delete;
29 33
30 ComputePipeline& operator=(const ComputePipeline&) = delete; 34 ComputePipeline& operator=(const ComputePipeline&) = delete;
31 ComputePipeline(const ComputePipeline&) = delete; 35 ComputePipeline(const ComputePipeline&) = delete;
32 36
33 void ConfigureBufferCache(BufferCache& buffer_cache); 37 void Configure(Tegra::Engines::KeplerCompute& kepler_compute, Tegra::MemoryManager& gpu_memory,
34 void ConfigureTextureCache(Tegra::Engines::KeplerCompute& kepler_compute, 38 VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache);
35 Tegra::MemoryManager& gpu_memory, TextureCache& texture_cache);
36
37 [[nodiscard]] VkDescriptorSet UpdateDescriptorSet();
38
39 [[nodiscard]] VkPipeline Handle() const noexcept {
40 return *pipeline;
41 }
42
43 [[nodiscard]] VkPipelineLayout PipelineLayout() const noexcept {
44 return *pipeline_layout;
45 }
46 39
47private: 40private:
48 VKUpdateDescriptorQueue* update_descriptor_queue; 41 VKUpdateDescriptorQueue& update_descriptor_queue;
49 Shader::Info info; 42 Shader::Info info;
50 43
51 vk::ShaderModule spv_module; 44 vk::ShaderModule spv_module;
@@ -54,6 +47,7 @@ private:
54 vk::PipelineLayout pipeline_layout; 47 vk::PipelineLayout pipeline_layout;
55 vk::DescriptorUpdateTemplateKHR descriptor_update_template; 48 vk::DescriptorUpdateTemplateKHR descriptor_update_template;
56 vk::Pipeline pipeline; 49 vk::Pipeline pipeline;
50 std::atomic_flag building_flag{};
57}; 51};
58 52
59} // namespace Vulkan 53} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 278509bf0..ddc08b8c4 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -112,13 +112,15 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
112 BufferCache& buffer_cache_, TextureCache& texture_cache_, 112 BufferCache& buffer_cache_, TextureCache& texture_cache_,
113 const Device& device, VKDescriptorPool& descriptor_pool, 113 const Device& device, VKDescriptorPool& descriptor_pool,
114 VKUpdateDescriptorQueue& update_descriptor_queue_, 114 VKUpdateDescriptorQueue& update_descriptor_queue_,
115 Common::ThreadWorker* worker_thread,
115 RenderPassCache& render_pass_cache, 116 RenderPassCache& render_pass_cache,
116 const FixedPipelineState& state, 117 const FixedPipelineState& state_,
117 std::array<vk::ShaderModule, NUM_STAGES> stages, 118 std::array<vk::ShaderModule, NUM_STAGES> stages,
118 const std::array<const Shader::Info*, NUM_STAGES>& infos) 119 const std::array<const Shader::Info*, NUM_STAGES>& infos)
119 : maxwell3d{&maxwell3d_}, gpu_memory{&gpu_memory_}, texture_cache{&texture_cache_}, 120 : maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, texture_cache{texture_cache_},
120 buffer_cache{&buffer_cache_}, scheduler{&scheduler_}, 121 buffer_cache{buffer_cache_}, scheduler{scheduler_},
121 update_descriptor_queue{&update_descriptor_queue_}, spv_modules{std::move(stages)} { 122 update_descriptor_queue{update_descriptor_queue_}, state{state_}, spv_modules{
123 std::move(stages)} {
122 std::ranges::transform(infos, stage_infos.begin(), 124 std::ranges::transform(infos, stage_infos.begin(),
123 [](const Shader::Info* info) { return info ? *info : Shader::Info{}; }); 125 [](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
124 126
@@ -128,8 +130,17 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
128 descriptor_update_template = std::move(tuple.descriptor_update_template); 130 descriptor_update_template = std::move(tuple.descriptor_update_template);
129 descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); 131 descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout);
130 132
131 const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(state))}; 133 auto func{[this, &device, &render_pass_cache] {
132 MakePipeline(device, state, render_pass); 134 const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(state))};
135 MakePipeline(device, render_pass);
136 building_flag.test_and_set();
137 building_flag.notify_all();
138 }};
139 if (worker_thread) {
140 worker_thread->QueueWork(std::move(func));
141 } else {
142 func();
143 }
133} 144}
134 145
135void GraphicsPipeline::Configure(bool is_indexed) { 146void GraphicsPipeline::Configure(bool is_indexed) {
@@ -138,67 +149,72 @@ void GraphicsPipeline::Configure(bool is_indexed) {
138 static_vector<u32, max_images_elements> image_view_indices; 149 static_vector<u32, max_images_elements> image_view_indices;
139 static_vector<VkSampler, max_images_elements> samplers; 150 static_vector<VkSampler, max_images_elements> samplers;
140 151
141 texture_cache->SynchronizeGraphicsDescriptors(); 152 texture_cache.SynchronizeGraphicsDescriptors();
142 153
143 const auto& regs{maxwell3d->regs}; 154 const auto& regs{maxwell3d.regs};
144 const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; 155 const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
145 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 156 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
146 const Shader::Info& info{stage_infos[stage]}; 157 const Shader::Info& info{stage_infos[stage]};
147 buffer_cache->SetEnabledUniformBuffers(stage, info.constant_buffer_mask); 158 buffer_cache.SetEnabledUniformBuffers(stage, info.constant_buffer_mask);
148 buffer_cache->UnbindGraphicsStorageBuffers(stage); 159 buffer_cache.UnbindGraphicsStorageBuffers(stage);
149 size_t index{}; 160 size_t index{};
150 for (const auto& desc : info.storage_buffers_descriptors) { 161 for (const auto& desc : info.storage_buffers_descriptors) {
151 ASSERT(desc.count == 1); 162 ASSERT(desc.count == 1);
152 buffer_cache->BindGraphicsStorageBuffer(stage, index, desc.cbuf_index, desc.cbuf_offset, 163 buffer_cache.BindGraphicsStorageBuffer(stage, index, desc.cbuf_index, desc.cbuf_offset,
153 true); 164 true);
154 ++index; 165 ++index;
155 } 166 }
156 const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers}; 167 const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers};
157 for (const auto& desc : info.texture_descriptors) { 168 for (const auto& desc : info.texture_descriptors) {
158 const u32 cbuf_index{desc.cbuf_index}; 169 const u32 cbuf_index{desc.cbuf_index};
159 const u32 cbuf_offset{desc.cbuf_offset}; 170 const u32 cbuf_offset{desc.cbuf_offset};
160 ASSERT(cbufs[cbuf_index].enabled); 171 ASSERT(cbufs[cbuf_index].enabled);
161 const GPUVAddr addr{cbufs[cbuf_index].address + cbuf_offset}; 172 const GPUVAddr addr{cbufs[cbuf_index].address + cbuf_offset};
162 const u32 raw_handle{gpu_memory->Read<u32>(addr)}; 173 const u32 raw_handle{gpu_memory.Read<u32>(addr)};
163 174
164 const TextureHandle handle(raw_handle, via_header_index); 175 const TextureHandle handle(raw_handle, via_header_index);
165 image_view_indices.push_back(handle.image); 176 image_view_indices.push_back(handle.image);
166 177
167 Sampler* const sampler{texture_cache->GetGraphicsSampler(handle.sampler)}; 178 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)};
168 samplers.push_back(sampler->Handle()); 179 samplers.push_back(sampler->Handle());
169 } 180 }
170 } 181 }
171 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 182 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
172 buffer_cache->UpdateGraphicsBuffers(is_indexed); 183 buffer_cache.UpdateGraphicsBuffers(is_indexed);
173 texture_cache->FillGraphicsImageViews(indices_span, image_view_ids); 184 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
174 185
175 buffer_cache->BindHostGeometryBuffers(is_indexed); 186 buffer_cache.BindHostGeometryBuffers(is_indexed);
176 187
177 size_t index{}; 188 size_t index{};
178 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 189 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
179 buffer_cache->BindHostStageBuffers(stage); 190 buffer_cache.BindHostStageBuffers(stage);
180 PushImageDescriptors(stage_infos[stage], samplers.data(), image_view_ids.data(), 191 PushImageDescriptors(stage_infos[stage], samplers.data(), image_view_ids.data(),
181 *texture_cache, *update_descriptor_queue, index); 192 texture_cache, update_descriptor_queue, index);
182 } 193 }
183 texture_cache->UpdateRenderTargets(false); 194 texture_cache.UpdateRenderTargets(false);
184 scheduler->RequestRenderpass(texture_cache->GetFramebuffer()); 195 scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
185
186 scheduler->BindGraphicsPipeline(*pipeline);
187 196
197 if (!building_flag.test()) {
198 scheduler.Record([this](vk::CommandBuffer) { building_flag.wait(false); });
199 }
200 if (scheduler.UpdateGraphicsPipeline(this)) {
201 scheduler.Record([this](vk::CommandBuffer cmdbuf) {
202 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
203 });
204 }
188 if (!descriptor_set_layout) { 205 if (!descriptor_set_layout) {
189 return; 206 return;
190 } 207 }
191 const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; 208 const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
192 update_descriptor_queue->Send(*descriptor_update_template, descriptor_set); 209 update_descriptor_queue.Send(*descriptor_update_template, descriptor_set);
193 210
194 scheduler->Record([descriptor_set, layout = *pipeline_layout](vk::CommandBuffer cmdbuf) { 211 scheduler.Record([descriptor_set, layout = *pipeline_layout](vk::CommandBuffer cmdbuf) {
195 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, 212 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
196 nullptr); 213 nullptr);
197 }); 214 });
198} 215}
199 216
200void GraphicsPipeline::MakePipeline(const Device& device, const FixedPipelineState& state, 217void GraphicsPipeline::MakePipeline(const Device& device, VkRenderPass render_pass) {
201 VkRenderPass render_pass) {
202 FixedPipelineState::DynamicState dynamic{}; 218 FixedPipelineState::DynamicState dynamic{};
203 if (!device.IsExtExtendedDynamicStateSupported()) { 219 if (!device.IsExtExtendedDynamicStateSupported()) {
204 dynamic = state.dynamic_state; 220 dynamic = state.dynamic_state;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index ba1d34a83..4e0583157 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -5,13 +5,15 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <atomic>
8 9
10#include "common/thread_worker.h"
9#include "shader_recompiler/shader_info.h" 11#include "shader_recompiler/shader_info.h"
10#include "video_core/engines/maxwell_3d.h" 12#include "video_core/engines/maxwell_3d.h"
11#include "video_core/renderer_vulkan/fixed_pipeline_state.h" 13#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
14#include "video_core/renderer_vulkan/vk_buffer_cache.h"
12#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 15#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
13#include "video_core/renderer_vulkan/vk_texture_cache.h" 16#include "video_core/renderer_vulkan/vk_texture_cache.h"
14#include "video_core/renderer_vulkan/vk_buffer_cache.h"
15#include "video_core/vulkan_common/vulkan_wrapper.h" 17#include "video_core/vulkan_common/vulkan_wrapper.h"
16 18
17namespace Vulkan { 19namespace Vulkan {
@@ -25,34 +27,34 @@ class GraphicsPipeline {
25 static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; 27 static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
26 28
27public: 29public:
28 explicit GraphicsPipeline() = default;
29 explicit GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d, 30 explicit GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d,
30 Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler, 31 Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler,
31 BufferCache& buffer_cache, 32 BufferCache& buffer_cache, TextureCache& texture_cache,
32 TextureCache& texture_cache, const Device& device, VKDescriptorPool& descriptor_pool, 33 const Device& device, VKDescriptorPool& descriptor_pool,
33 VKUpdateDescriptorQueue& update_descriptor_queue, 34 VKUpdateDescriptorQueue& update_descriptor_queue,
35 Common::ThreadWorker* worker_thread,
34 RenderPassCache& render_pass_cache, const FixedPipelineState& state, 36 RenderPassCache& render_pass_cache, const FixedPipelineState& state,
35 std::array<vk::ShaderModule, NUM_STAGES> stages, 37 std::array<vk::ShaderModule, NUM_STAGES> stages,
36 const std::array<const Shader::Info*, NUM_STAGES>& infos); 38 const std::array<const Shader::Info*, NUM_STAGES>& infos);
37 39
38 void Configure(bool is_indexed); 40 void Configure(bool is_indexed);
39 41
40 GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = default; 42 GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete;
41 GraphicsPipeline(GraphicsPipeline&&) noexcept = default; 43 GraphicsPipeline(GraphicsPipeline&&) noexcept = delete;
42 44
43 GraphicsPipeline& operator=(const GraphicsPipeline&) = delete; 45 GraphicsPipeline& operator=(const GraphicsPipeline&) = delete;
44 GraphicsPipeline(const GraphicsPipeline&) = delete; 46 GraphicsPipeline(const GraphicsPipeline&) = delete;
45 47
46private: 48private:
47 void MakePipeline(const Device& device, const FixedPipelineState& state, 49 void MakePipeline(const Device& device, VkRenderPass render_pass);
48 VkRenderPass render_pass);
49 50
50 Tegra::Engines::Maxwell3D* maxwell3d{}; 51 Tegra::Engines::Maxwell3D& maxwell3d;
51 Tegra::MemoryManager* gpu_memory{}; 52 Tegra::MemoryManager& gpu_memory;
52 TextureCache* texture_cache{}; 53 TextureCache& texture_cache;
53 BufferCache* buffer_cache{}; 54 BufferCache& buffer_cache;
54 VKScheduler* scheduler{}; 55 VKScheduler& scheduler;
55 VKUpdateDescriptorQueue* update_descriptor_queue{}; 56 VKUpdateDescriptorQueue& update_descriptor_queue;
57 const FixedPipelineState state;
56 58
57 std::array<vk::ShaderModule, NUM_STAGES> spv_modules; 59 std::array<vk::ShaderModule, NUM_STAGES> spv_modules;
58 std::array<Shader::Info, NUM_STAGES> stage_infos; 60 std::array<Shader::Info, NUM_STAGES> stage_infos;
@@ -61,6 +63,7 @@ private:
61 vk::PipelineLayout pipeline_layout; 63 vk::PipelineLayout pipeline_layout;
62 vk::DescriptorUpdateTemplateKHR descriptor_update_template; 64 vk::DescriptorUpdateTemplateKHR descriptor_update_template;
63 vk::Pipeline pipeline; 65 vk::Pipeline pipeline;
66 std::atomic_flag building_flag{};
64}; 67};
65 68
66} // namespace Vulkan 69} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 30a707599..e3d9debf4 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -518,9 +518,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
518 } 518 }
519 pipeline_cache_filename = fmt::format("{}/{:016x}.bin", transferable_dir, title_id); 519 pipeline_cache_filename = fmt::format("{}/{:016x}.bin", transferable_dir, title_id);
520 520
521 Common::ThreadWorker worker(11, "PipelineBuilder");
522 std::mutex cache_mutex;
523 struct { 521 struct {
522 std::mutex mutex;
524 size_t total{0}; 523 size_t total{0};
525 size_t built{0}; 524 size_t built{0};
526 bool has_loaded{false}; 525 bool has_loaded{false};
@@ -542,51 +541,53 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
542 } 541 }
543 u32 num_envs{}; 542 u32 num_envs{};
544 file.read(reinterpret_cast<char*>(&num_envs), sizeof(num_envs)); 543 file.read(reinterpret_cast<char*>(&num_envs), sizeof(num_envs));
545 auto envs{std::make_shared<std::vector<FileEnvironment>>(num_envs)}; 544 std::vector<FileEnvironment> envs(num_envs);
546 for (FileEnvironment& env : *envs) { 545 for (FileEnvironment& env : envs) {
547 env.Deserialize(file); 546 env.Deserialize(file);
548 } 547 }
549 if (envs->front().ShaderStage() == Shader::Stage::Compute) { 548 if (envs.front().ShaderStage() == Shader::Stage::Compute) {
550 ComputePipelineCacheKey key; 549 ComputePipelineCacheKey key;
551 file.read(reinterpret_cast<char*>(&key), sizeof(key)); 550 file.read(reinterpret_cast<char*>(&key), sizeof(key));
552 551
553 worker.QueueWork([this, key, envs, &cache_mutex, &state, &callback] { 552 workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable {
554 ShaderPools pools; 553 ShaderPools pools;
555 ComputePipeline pipeline{CreateComputePipeline(pools, key, envs->front())}; 554 auto pipeline{CreateComputePipeline(pools, key, envs.front(), false)};
556 555
557 std::lock_guard lock{cache_mutex}; 556 std::lock_guard lock{state.mutex};
558 compute_cache.emplace(key, std::move(pipeline)); 557 compute_cache.emplace(key, std::move(pipeline));
558 ++state.built;
559 if (state.has_loaded) { 559 if (state.has_loaded) {
560 callback(VideoCore::LoadCallbackStage::Build, ++state.built, state.total); 560 callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
561 } 561 }
562 }); 562 });
563 } else { 563 } else {
564 GraphicsPipelineCacheKey key; 564 GraphicsPipelineCacheKey key;
565 file.read(reinterpret_cast<char*>(&key), sizeof(key)); 565 file.read(reinterpret_cast<char*>(&key), sizeof(key));
566 566
567 worker.QueueWork([this, key, envs, &cache_mutex, &state, &callback] { 567 workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable {
568 ShaderPools pools; 568 ShaderPools pools;
569 boost::container::static_vector<Shader::Environment*, 5> env_ptrs; 569 boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
570 for (auto& env : *envs) { 570 for (auto& env : envs) {
571 env_ptrs.push_back(&env); 571 env_ptrs.push_back(&env);
572 } 572 }
573 GraphicsPipeline pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs))}; 573 auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), false)};
574 574
575 std::lock_guard lock{cache_mutex}; 575 std::lock_guard lock{state.mutex};
576 graphics_cache.emplace(key, std::move(pipeline)); 576 graphics_cache.emplace(key, std::move(pipeline));
577 ++state.built;
577 if (state.has_loaded) { 578 if (state.has_loaded) {
578 callback(VideoCore::LoadCallbackStage::Build, ++state.built, state.total); 579 callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
579 } 580 }
580 }); 581 });
581 } 582 }
582 ++state.total; 583 ++state.total;
583 } 584 }
584 { 585 {
585 std::lock_guard lock{cache_mutex}; 586 std::lock_guard lock{state.mutex};
586 callback(VideoCore::LoadCallbackStage::Build, 0, state.total); 587 callback(VideoCore::LoadCallbackStage::Build, 0, state.total);
587 state.has_loaded = true; 588 state.has_loaded = true;
588 } 589 }
589 worker.WaitForRequests(); 590 workers.WaitForRequests();
590} 591}
591 592
592size_t ComputePipelineCacheKey::Hash() const noexcept { 593size_t ComputePipelineCacheKey::Hash() const noexcept {
@@ -619,7 +620,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_,
619 kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_}, 620 kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_},
620 scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, 621 scheduler{scheduler_}, descriptor_pool{descriptor_pool_},
621 update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_}, 622 update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_},
622 buffer_cache{buffer_cache_}, texture_cache{texture_cache_} { 623 buffer_cache{buffer_cache_}, texture_cache{texture_cache_}, workers(11, "PipelineBuilder") {
623 const auto& float_control{device.FloatControlProperties()}; 624 const auto& float_control{device.FloatControlProperties()};
624 const VkDriverIdKHR driver_id{device.GetDriverID()}; 625 const VkDriverIdKHR driver_id{device.GetDriverID()};
625 base_profile = Shader::Profile{ 626 base_profile = Shader::Profile{
@@ -662,10 +663,10 @@ GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() {
662 const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; 663 const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)};
663 auto& pipeline{pair->second}; 664 auto& pipeline{pair->second};
664 if (!is_new) { 665 if (!is_new) {
665 return &pipeline; 666 return pipeline.get();
666 } 667 }
667 pipeline = CreateGraphicsPipeline(); 668 pipeline = CreateGraphicsPipeline();
668 return &pipeline; 669 return pipeline.get();
669} 670}
670 671
671ComputePipeline* PipelineCache::CurrentComputePipeline() { 672ComputePipeline* PipelineCache::CurrentComputePipeline() {
@@ -691,10 +692,10 @@ ComputePipeline* PipelineCache::CurrentComputePipeline() {
691 const auto [pair, is_new]{compute_cache.try_emplace(key)}; 692 const auto [pair, is_new]{compute_cache.try_emplace(key)};
692 auto& pipeline{pair->second}; 693 auto& pipeline{pair->second};
693 if (!is_new) { 694 if (!is_new) {
694 return &pipeline; 695 return pipeline.get();
695 } 696 }
696 pipeline = CreateComputePipeline(key, shader); 697 pipeline = CreateComputePipeline(key, shader);
697 return &pipeline; 698 return pipeline.get();
698} 699}
699 700
700bool PipelineCache::RefreshStages() { 701bool PipelineCache::RefreshStages() {
@@ -743,9 +744,9 @@ const ShaderInfo* PipelineCache::MakeShaderInfo(GenericEnvironment& env, VAddr c
743 return result; 744 return result;
744} 745}
745 746
746GraphicsPipeline PipelineCache::CreateGraphicsPipeline(ShaderPools& pools, 747std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
747 const GraphicsPipelineCacheKey& key, 748 ShaderPools& pools, const GraphicsPipelineCacheKey& key,
748 std::span<Shader::Environment* const> envs) { 749 std::span<Shader::Environment* const> envs, bool build_in_parallel) {
749 LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); 750 LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash());
750 size_t env_index{0}; 751 size_t env_index{0};
751 std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; 752 std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
@@ -783,12 +784,14 @@ GraphicsPipeline PipelineCache::CreateGraphicsPipeline(ShaderPools& pools,
783 modules[stage_index].SetObjectNameEXT(name.c_str()); 784 modules[stage_index].SetObjectNameEXT(name.c_str());
784 } 785 }
785 } 786 }
786 return GraphicsPipeline(maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, device, 787 Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
787 descriptor_pool, update_descriptor_queue, render_pass_cache, key.state, 788 return std::make_unique<GraphicsPipeline>(
788 std::move(modules), infos); 789 maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, device, descriptor_pool,
790 update_descriptor_queue, thread_worker, render_pass_cache, key.state, std::move(modules),
791 infos);
789} 792}
790 793
791GraphicsPipeline PipelineCache::CreateGraphicsPipeline() { 794std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
792 main_pools.ReleaseContents(); 795 main_pools.ReleaseContents();
793 796
794 std::array<GraphicsEnvironment, Maxwell::MaxShaderProgram> graphics_envs; 797 std::array<GraphicsEnvironment, Maxwell::MaxShaderProgram> graphics_envs;
@@ -809,22 +812,22 @@ GraphicsPipeline PipelineCache::CreateGraphicsPipeline() {
809 generic_envs.push_back(&env); 812 generic_envs.push_back(&env);
810 envs.push_back(&env); 813 envs.push_back(&env);
811 } 814 }
812 GraphicsPipeline pipeline{CreateGraphicsPipeline(main_pools, graphics_key, MakeSpan(envs))}; 815 auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, MakeSpan(envs), true)};
813 if (!pipeline_cache_filename.empty()) { 816 if (!pipeline_cache_filename.empty()) {
814 SerializePipeline(graphics_key, generic_envs, pipeline_cache_filename); 817 SerializePipeline(graphics_key, generic_envs, pipeline_cache_filename);
815 } 818 }
816 return pipeline; 819 return pipeline;
817} 820}
818 821
819ComputePipeline PipelineCache::CreateComputePipeline(const ComputePipelineCacheKey& key, 822std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
820 const ShaderInfo* shader) { 823 const ComputePipelineCacheKey& key, const ShaderInfo* shader) {
821 const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()}; 824 const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()};
822 const auto& qmd{kepler_compute.launch_description}; 825 const auto& qmd{kepler_compute.launch_description};
823 ComputeEnvironment env{kepler_compute, gpu_memory, program_base, qmd.program_start}; 826 ComputeEnvironment env{kepler_compute, gpu_memory, program_base, qmd.program_start};
824 env.SetCachedSize(shader->size_bytes); 827 env.SetCachedSize(shader->size_bytes);
825 828
826 main_pools.ReleaseContents(); 829 main_pools.ReleaseContents();
827 ComputePipeline pipeline{CreateComputePipeline(main_pools, key, env)}; 830 auto pipeline{CreateComputePipeline(main_pools, key, env, true)};
828 if (!pipeline_cache_filename.empty()) { 831 if (!pipeline_cache_filename.empty()) {
829 SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env}, 832 SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
830 pipeline_cache_filename); 833 pipeline_cache_filename);
@@ -832,9 +835,9 @@ ComputePipeline PipelineCache::CreateComputePipeline(const ComputePipelineCacheK
832 return pipeline; 835 return pipeline;
833} 836}
834 837
835ComputePipeline PipelineCache::CreateComputePipeline(ShaderPools& pools, 838std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
836 const ComputePipelineCacheKey& key, 839 ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env,
837 Shader::Environment& env) const { 840 bool build_in_parallel) {
838 LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); 841 LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash());
839 842
840 Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; 843 Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
@@ -846,8 +849,9 @@ ComputePipeline PipelineCache::CreateComputePipeline(ShaderPools& pools,
846 const auto name{fmt::format("{:016x}{:016x}", key.unique_hash[0], key.unique_hash[1])}; 849 const auto name{fmt::format("{:016x}{:016x}", key.unique_hash[0], key.unique_hash[1])};
847 spv_module.SetObjectNameEXT(name.c_str()); 850 spv_module.SetObjectNameEXT(name.c_str());
848 } 851 }
849 return ComputePipeline{device, descriptor_pool, update_descriptor_queue, program.info, 852 Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
850 std::move(spv_module)}; 853 return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue,
854 thread_worker, program.info, std::move(spv_module));
851} 855}
852 856
853static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribute& attr) { 857static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribute& attr) {
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index b55e14189..609f00898 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -14,6 +14,7 @@
14#include <vector> 14#include <vector>
15 15
16#include "common/common_types.h" 16#include "common/common_types.h"
17#include "common/thread_worker.h"
17#include "shader_recompiler/frontend/ir/basic_block.h" 18#include "shader_recompiler/frontend/ir/basic_block.h"
18#include "shader_recompiler/frontend/ir/microinstruction.h" 19#include "shader_recompiler/frontend/ir/microinstruction.h"
19#include "shader_recompiler/frontend/maxwell/control_flow.h" 20#include "shader_recompiler/frontend/maxwell/control_flow.h"
@@ -145,16 +146,19 @@ private:
145 146
146 const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr); 147 const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr);
147 148
148 GraphicsPipeline CreateGraphicsPipeline(); 149 std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline();
149 150
150 GraphicsPipeline CreateGraphicsPipeline(ShaderPools& pools, const GraphicsPipelineCacheKey& key, 151 std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(
151 std::span<Shader::Environment* const> envs); 152 ShaderPools& pools, const GraphicsPipelineCacheKey& key,
153 std::span<Shader::Environment* const> envs, bool build_in_parallel);
152 154
153 ComputePipeline CreateComputePipeline(const ComputePipelineCacheKey& key, 155 std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineCacheKey& key,
154 const ShaderInfo* shader); 156 const ShaderInfo* shader);
155 157
156 ComputePipeline CreateComputePipeline(ShaderPools& pools, const ComputePipelineCacheKey& key, 158 std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderPools& pools,
157 Shader::Environment& env) const; 159 const ComputePipelineCacheKey& key,
160 Shader::Environment& env,
161 bool build_in_parallel);
158 162
159 Shader::Profile MakeProfile(const GraphicsPipelineCacheKey& key, Shader::Stage stage); 163 Shader::Profile MakeProfile(const GraphicsPipelineCacheKey& key, Shader::Stage stage);
160 164
@@ -174,13 +178,15 @@ private:
174 GraphicsPipelineCacheKey graphics_key{}; 178 GraphicsPipelineCacheKey graphics_key{};
175 std::array<const ShaderInfo*, 6> shader_infos{}; 179 std::array<const ShaderInfo*, 6> shader_infos{};
176 180
177 std::unordered_map<ComputePipelineCacheKey, ComputePipeline> compute_cache; 181 std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache;
178 std::unordered_map<GraphicsPipelineCacheKey, GraphicsPipeline> graphics_cache; 182 std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
179 183
180 ShaderPools main_pools; 184 ShaderPools main_pools;
181 185
182 Shader::Profile base_profile; 186 Shader::Profile base_profile;
183 std::string pipeline_cache_filename; 187 std::string pipeline_cache_filename;
188
189 Common::ThreadWorker workers;
184}; 190};
185 191
186} // namespace Vulkan 192} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index d7d9927dd..f0bd4b8af 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -276,22 +276,11 @@ void RasterizerVulkan::DispatchCompute() {
276 return; 276 return;
277 } 277 }
278 std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex}; 278 std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex};
279 update_descriptor_queue.Acquire(); 279 pipeline->Configure(kepler_compute, gpu_memory, scheduler, buffer_cache, texture_cache);
280 pipeline->ConfigureBufferCache(buffer_cache);
281 pipeline->ConfigureTextureCache(kepler_compute, gpu_memory, texture_cache);
282 const VkDescriptorSet descriptor_set{pipeline->UpdateDescriptorSet()};
283 280
284 const auto& qmd{kepler_compute.launch_description}; 281 const auto& qmd{kepler_compute.launch_description};
285 const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; 282 const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
286 const VkPipeline pipeline_handle{pipeline->Handle()}; 283 scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
287 const VkPipelineLayout pipeline_layout{pipeline->PipelineLayout()};
288 scheduler.Record(
289 [pipeline_handle, pipeline_layout, dim, descriptor_set](vk::CommandBuffer cmdbuf) {
290 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_handle);
291 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0,
292 descriptor_set, nullptr);
293 cmdbuf.Dispatch(dim[0], dim[1], dim[2]);
294 });
295} 284}
296 285
297void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) { 286void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) {
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index f35c120b0..25a4933e5 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -124,18 +124,16 @@ void VKScheduler::RequestOutsideRenderPassOperationContext() {
124 EndRenderPass(); 124 EndRenderPass();
125} 125}
126 126
127void VKScheduler::BindGraphicsPipeline(VkPipeline pipeline) { 127bool VKScheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
128 if (state.graphics_pipeline == pipeline) { 128 if (state.graphics_pipeline == pipeline) {
129 return; 129 return false;
130 } 130 }
131 state.graphics_pipeline = pipeline; 131 state.graphics_pipeline = pipeline;
132 Record([pipeline](vk::CommandBuffer cmdbuf) { 132 return true;
133 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
134 });
135} 133}
136 134
137void VKScheduler::WorkerThread() { 135void VKScheduler::WorkerThread() {
138 Common::SetCurrentThreadPriority(Common::ThreadPriority::High); 136 Common::SetCurrentThreadName("yuzu:VulkanWorker");
139 std::unique_lock lock{mutex}; 137 std::unique_lock lock{mutex};
140 do { 138 do {
141 cv.wait(lock, [this] { return !chunk_queue.Empty() || quit; }); 139 cv.wait(lock, [this] { return !chunk_queue.Empty() || quit; });
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
index 3ce48e9d2..a40bb8bcd 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
@@ -22,6 +22,7 @@ namespace Vulkan {
22class CommandPool; 22class CommandPool;
23class Device; 23class Device;
24class Framebuffer; 24class Framebuffer;
25class GraphicsPipeline;
25class StateTracker; 26class StateTracker;
26class VKQueryCache; 27class VKQueryCache;
27 28
@@ -52,8 +53,8 @@ public:
52 /// of a renderpass. 53 /// of a renderpass.
53 void RequestOutsideRenderPassOperationContext(); 54 void RequestOutsideRenderPassOperationContext();
54 55
55 /// Binds a pipeline to the current execution context. 56 /// Update the pipeline to the current execution context.
56 void BindGraphicsPipeline(VkPipeline pipeline); 57 bool UpdateGraphicsPipeline(GraphicsPipeline* pipeline);
57 58
58 /// Invalidates current command buffer state except for render passes 59 /// Invalidates current command buffer state except for render passes
59 void InvalidateState(); 60 void InvalidateState();
@@ -170,7 +171,7 @@ private:
170 VkRenderPass renderpass = nullptr; 171 VkRenderPass renderpass = nullptr;
171 VkFramebuffer framebuffer = nullptr; 172 VkFramebuffer framebuffer = nullptr;
172 VkExtent2D render_area = {0, 0}; 173 VkExtent2D render_area = {0, 0};
173 VkPipeline graphics_pipeline = nullptr; 174 GraphicsPipeline* graphics_pipeline = nullptr;
174 }; 175 };
175 176
176 void WorkerThread(); 177 void WorkerThread();