summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar ameerj2020-08-02 13:05:41 -0400
committerGravatar ameerj2020-08-16 12:02:22 -0400
commit31a76410e8fa09462d960c10148c075125dc385a (patch)
treea5e45c1f609cdf7d4537d1215699e741a469ba17 /src/video_core/renderer_vulkan
parentVk Async Worker directly emplace in cache (diff)
downloadyuzu-31a76410e8fa09462d960c10148c075125dc385a.tar.gz
yuzu-31a76410e8fa09462d960c10148c075125dc385a.tar.xz
yuzu-31a76410e8fa09462d960c10148c075125dc385a.zip
Address feedback, add shader compile notifier, update setting text
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h30
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp23
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h58
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp19
6 files changed, 51 insertions, 93 deletions
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index 30cd3e189..26a233db1 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -202,6 +202,7 @@ public:
202 return reported_extensions; 202 return reported_extensions;
203 } 203 }
204 204
205 /// Returns true if the setting for async shader compilation is enabled.
205 bool UseAsynchronousShaders() const { 206 bool UseAsynchronousShaders() const {
206 return use_asynchronous_shaders; 207 return use_asynchronous_shaders;
207 } 208 }
@@ -255,7 +256,9 @@ private:
255 bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color. 256 bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color.
256 bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state. 257 bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state.
257 bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config. 258 bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
258 bool use_asynchronous_shaders{}; 259
260 // Asynchronous Graphics Pipeline setting
261 bool use_asynchronous_shaders{}; ///< Setting to use asynchronous shaders/graphics pipeline
259 262
260 // Telemetry parameters 263 // Telemetry parameters
261 std::string vendor_name; ///< Device's driver name. 264 std::string vendor_name; ///< Device's driver name.
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 7d51b9836..5dc4cd5af 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -78,14 +78,15 @@ VKGraphicsPipeline::VKGraphicsPipeline(const VKDevice& device, VKScheduler& sche
78 const GraphicsPipelineCacheKey& key, 78 const GraphicsPipelineCacheKey& key,
79 vk::Span<VkDescriptorSetLayoutBinding> bindings, 79 vk::Span<VkDescriptorSetLayoutBinding> bindings,
80 const SPIRVProgram& program) 80 const SPIRVProgram& program)
81 : device{device}, scheduler{scheduler}, fixed_state{key.fixed_state}, hash{key.Hash()}, 81 : device{device}, scheduler{scheduler}, hash{key.Hash()}, cache_key{key},
82 descriptor_set_layout{CreateDescriptorSetLayout(bindings)}, 82 descriptor_set_layout{CreateDescriptorSetLayout(bindings)},
83 descriptor_allocator{descriptor_pool, *descriptor_set_layout}, 83 descriptor_allocator{descriptor_pool, *descriptor_set_layout},
84 update_descriptor_queue{update_descriptor_queue}, layout{CreatePipelineLayout()}, 84 update_descriptor_queue{update_descriptor_queue}, layout{CreatePipelineLayout()},
85 descriptor_template{CreateDescriptorUpdateTemplate(program)}, modules{CreateShaderModules( 85 descriptor_template{CreateDescriptorUpdateTemplate(program)}, modules{CreateShaderModules(
86 program)}, 86 program)},
87 renderpass{renderpass_cache.GetRenderPass(key.renderpass_params)}, 87 renderpass{renderpass_cache.GetRenderPass(key.renderpass_params)}, pipeline{CreatePipeline(
88 pipeline{CreatePipeline(key.renderpass_params, program)}, m_key{key} {} 88 key.renderpass_params,
89 program)} {}
89 90
90VKGraphicsPipeline::~VKGraphicsPipeline() = default; 91VKGraphicsPipeline::~VKGraphicsPipeline() = default;
91 92
@@ -180,7 +181,7 @@ std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
180 181
181vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params, 182vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params,
182 const SPIRVProgram& program) const { 183 const SPIRVProgram& program) const {
183 const auto& state = fixed_state; 184 const auto& state = cache_key.fixed_state;
184 const auto& viewport_swizzles = state.viewport_swizzles; 185 const auto& viewport_swizzles = state.viewport_swizzles;
185 186
186 FixedPipelineState::DynamicState dynamic; 187 FixedPipelineState::DynamicState dynamic;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index d50bd347c..9d462db0a 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -19,7 +19,27 @@ namespace Vulkan {
19 19
20using Maxwell = Tegra::Engines::Maxwell3D::Regs; 20using Maxwell = Tegra::Engines::Maxwell3D::Regs;
21 21
22struct GraphicsPipelineCacheKey; 22struct GraphicsPipelineCacheKey {
23 RenderPassParams renderpass_params;
24 u32 padding;
25 std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders;
26 FixedPipelineState fixed_state;
27
28 std::size_t Hash() const noexcept;
29
30 bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept;
31
32 bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept {
33 return !operator==(rhs);
34 }
35
36 std::size_t Size() const noexcept {
37 return sizeof(renderpass_params) + sizeof(padding) + sizeof(shaders) + fixed_state.Size();
38 }
39};
40static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>);
41static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>);
42static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>);
23 43
24class VKDescriptorPool; 44class VKDescriptorPool;
25class VKDevice; 45class VKDevice;
@@ -54,8 +74,8 @@ public:
54 return renderpass; 74 return renderpass;
55 } 75 }
56 76
57 const GraphicsPipelineCacheKey& GetCacheKey() const { 77 GraphicsPipelineCacheKey GetCacheKey() const {
58 return m_key; 78 return cache_key;
59 } 79 }
60 80
61private: 81private:
@@ -74,8 +94,8 @@ private:
74 94
75 const VKDevice& device; 95 const VKDevice& device;
76 VKScheduler& scheduler; 96 VKScheduler& scheduler;
77 const FixedPipelineState fixed_state;
78 const u64 hash; 97 const u64 hash;
98 GraphicsPipelineCacheKey cache_key;
79 99
80 vk::DescriptorSetLayout descriptor_set_layout; 100 vk::DescriptorSetLayout descriptor_set_layout;
81 DescriptorAllocator descriptor_allocator; 101 DescriptorAllocator descriptor_allocator;
@@ -86,8 +106,6 @@ private:
86 106
87 VkRenderPass renderpass; 107 VkRenderPass renderpass;
88 vk::Pipeline pipeline; 108 vk::Pipeline pipeline;
89
90 const GraphicsPipelineCacheKey& m_key;
91}; 109};
92 110
93} // namespace Vulkan 111} // 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 1a8b2c62b..20ffbeb38 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -28,6 +28,7 @@
28#include "video_core/shader/compiler_settings.h" 28#include "video_core/shader/compiler_settings.h"
29#include "video_core/shader/memory_util.h" 29#include "video_core/shader/memory_util.h"
30#include "video_core/shader_cache.h" 30#include "video_core/shader_cache.h"
31#include "video_core/shader_notify.h"
31 32
32namespace Vulkan { 33namespace Vulkan {
33 34
@@ -214,27 +215,31 @@ VKGraphicsPipeline* VKPipelineCache::GetGraphicsPipeline(
214 } 215 }
215 last_graphics_key = key; 216 last_graphics_key = key;
216 217
217 if (device.UseAsynchronousShaders()) { 218 if (device.UseAsynchronousShaders() && async_shaders.IsShaderAsync(system.GPU())) {
218 std::unique_lock lock{pipeline_cache}; 219 std::unique_lock lock{pipeline_cache};
219 const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); 220 const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key);
220 if (is_cache_miss) { 221 if (is_cache_miss) {
222 system.GPU().ShaderNotify().MarkSharderBuilding();
221 LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); 223 LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash());
222 const auto [program, bindings] = DecompileShaders(key.fixed_state); 224 const auto [program, bindings] = DecompileShaders(key.fixed_state);
223 async_shaders.QueueVulkanShader(this, bindings, program, key.renderpass_params, 225 async_shaders.QueueVulkanShader(this, device, scheduler, descriptor_pool,
224 key.padding, key.shaders, key.fixed_state); 226 update_descriptor_queue, renderpass_cache, bindings,
227 program, key);
225 } 228 }
226 last_graphics_pipeline = graphics_cache.at(key).get(); 229 last_graphics_pipeline = pair->second.get();
227 return last_graphics_pipeline; 230 return last_graphics_pipeline;
228 } 231 }
229 232
230 const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); 233 const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key);
231 auto& entry = pair->second; 234 auto& entry = pair->second;
232 if (is_cache_miss) { 235 if (is_cache_miss) {
236 system.GPU().ShaderNotify().MarkSharderBuilding();
233 LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); 237 LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash());
234 const auto [program, bindings] = DecompileShaders(key.fixed_state); 238 const auto [program, bindings] = DecompileShaders(key.fixed_state);
235 entry = std::make_unique<VKGraphicsPipeline>(device, scheduler, descriptor_pool, 239 entry = std::make_unique<VKGraphicsPipeline>(device, scheduler, descriptor_pool,
236 update_descriptor_queue, renderpass_cache, key, 240 update_descriptor_queue, renderpass_cache, key,
237 bindings, program); 241 bindings, program);
242 system.GPU().ShaderNotify().MarkShaderComplete();
238 } 243 }
239 last_graphics_pipeline = entry.get(); 244 last_graphics_pipeline = entry.get();
240 return last_graphics_pipeline; 245 return last_graphics_pipeline;
@@ -294,14 +299,8 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
294 299
295void VKPipelineCache::EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline) { 300void VKPipelineCache::EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline) {
296 std::unique_lock lock{pipeline_cache}; 301 std::unique_lock lock{pipeline_cache};
297 const auto [pair, is_cache_miss] = graphics_cache.try_emplace(pipeline->GetCacheKey()); 302 graphics_cache.at(pipeline->GetCacheKey()) = std::move(pipeline);
298 auto& entry = pair->second; 303 system.GPU().ShaderNotify().MarkShaderComplete();
299 if (entry) {
300 LOG_INFO(Render_Vulkan, "Pipeline already here 0x{:016X}", pipeline->GetCacheKey().Hash());
301 duplicates.push_back(std::move(pipeline));
302 } else {
303 entry = std::move(pipeline);
304 }
305} 304}
306 305
307void VKPipelineCache::OnShaderRemoval(Shader* shader) { 306void VKPipelineCache::OnShaderRemoval(Shader* shader) {
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 777ef2038..c04829e77 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -44,28 +44,6 @@ class VKUpdateDescriptorQueue;
44 44
45using Maxwell = Tegra::Engines::Maxwell3D::Regs; 45using Maxwell = Tegra::Engines::Maxwell3D::Regs;
46 46
47struct GraphicsPipelineCacheKey {
48 RenderPassParams renderpass_params;
49 u32 padding;
50 std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders;
51 FixedPipelineState fixed_state;
52
53 std::size_t Hash() const noexcept;
54
55 bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept;
56
57 bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept {
58 return !operator==(rhs);
59 }
60
61 std::size_t Size() const noexcept {
62 return sizeof(renderpass_params) + sizeof(padding) + sizeof(shaders) + fixed_state.Size();
63 }
64};
65static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>);
66static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>);
67static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>);
68
69struct ComputePipelineCacheKey { 47struct ComputePipelineCacheKey {
70 GPUVAddr shader; 48 GPUVAddr shader;
71 u32 shared_memory_size; 49 u32 shared_memory_size;
@@ -158,41 +136,6 @@ public:
158 136
159 VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); 137 VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key);
160 138
161 const VKDevice& GetDevice() const {
162 return device;
163 }
164
165 VKScheduler& GetScheduler() {
166 return scheduler;
167 }
168 const VKScheduler& GetScheduler() const {
169 return scheduler;
170 }
171
172 VKDescriptorPool& GetDescriptorPool() {
173 return descriptor_pool;
174 }
175
176 const VKDescriptorPool& GetDescriptorPool() const {
177 return descriptor_pool;
178 }
179
180 VKUpdateDescriptorQueue& GetUpdateDescriptorQueue() {
181 return update_descriptor_queue;
182 }
183
184 const VKUpdateDescriptorQueue& GetUpdateDescriptorQueue() const {
185 return update_descriptor_queue;
186 }
187
188 VKRenderPassCache& GetRenderpassCache() {
189 return renderpass_cache;
190 }
191
192 const VKRenderPassCache& GetRenderpassCache() const {
193 return renderpass_cache;
194 }
195
196 void EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline); 139 void EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline);
197 140
198protected: 141protected:
@@ -216,7 +159,6 @@ private:
216 159
217 GraphicsPipelineCacheKey last_graphics_key; 160 GraphicsPipelineCacheKey last_graphics_key;
218 VKGraphicsPipeline* last_graphics_pipeline = nullptr; 161 VKGraphicsPipeline* last_graphics_pipeline = nullptr;
219 std::vector<std::unique_ptr<VKGraphicsPipeline>> duplicates;
220 162
221 std::mutex pipeline_cache; 163 std::mutex pipeline_cache;
222 std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<VKGraphicsPipeline>> 164 std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<VKGraphicsPipeline>>
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index fc1b51a96..720802ad5 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -14,6 +14,7 @@
14#include "common/assert.h" 14#include "common/assert.h"
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/scope_exit.h"
17#include "core/core.h" 18#include "core/core.h"
18#include "core/settings.h" 19#include "core/settings.h"
19#include "video_core/engines/kepler_compute.h" 20#include "video_core/engines/kepler_compute.h"
@@ -408,15 +409,10 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind
408 409
409 // Max worker threads we should allow 410 // Max worker threads we should allow
410 constexpr u32 MAX_THREADS = 4; 411 constexpr u32 MAX_THREADS = 4;
411 // Amount of threads we should reserve for other parts of yuzu 412 // Deduce how many threads we can use
412 constexpr u32 RESERVED_THREADS = 6; 413 const auto threads_used = std::thread::hardware_concurrency() / 4;
413 // Get the amount of threads we can use(this can return zero)
414 const auto cpu_thread_count =
415 std::max(RESERVED_THREADS, std::thread::hardware_concurrency());
416 // Deduce how many "extra" threads we have to use.
417 const auto max_threads_unused = cpu_thread_count - RESERVED_THREADS;
418 // Always allow at least 1 thread regardless of our settings 414 // Always allow at least 1 thread regardless of our settings
419 const auto max_worker_count = std::max(1u, max_threads_unused); 415 const auto max_worker_count = std::max(1U, threads_used);
420 // Don't use more than MAX_THREADS 416 // Don't use more than MAX_THREADS
421 const auto worker_count = std::min(max_worker_count, MAX_THREADS); 417 const auto worker_count = std::min(max_worker_count, MAX_THREADS);
422 async_shaders.AllocateWorkers(worker_count); 418 async_shaders.AllocateWorkers(worker_count);
@@ -432,6 +428,8 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
432 428
433 query_cache.UpdateCounters(); 429 query_cache.UpdateCounters();
434 430
431 SCOPE_EXIT({ system.GPU().TickWork(); });
432
435 const auto& gpu = system.GPU().Maxwell3D(); 433 const auto& gpu = system.GPU().Maxwell3D();
436 GraphicsPipelineCacheKey key; 434 GraphicsPipelineCacheKey key;
437 key.fixed_state.Fill(gpu.regs, device.IsExtExtendedDynamicStateSupported()); 435 key.fixed_state.Fill(gpu.regs, device.IsExtExtendedDynamicStateSupported());
@@ -458,10 +456,9 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
458 key.renderpass_params = GetRenderPassParams(texceptions); 456 key.renderpass_params = GetRenderPassParams(texceptions);
459 key.padding = 0; 457 key.padding = 0;
460 458
461 auto pipeline = pipeline_cache.GetGraphicsPipeline(key, async_shaders); 459 auto* pipeline = pipeline_cache.GetGraphicsPipeline(key, async_shaders);
462 if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { 460 if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) {
463 // Async graphics pipeline was not ready. 461 // Async graphics pipeline was not ready.
464 system.GPU().TickWork();
465 return; 462 return;
466 } 463 }
467 464
@@ -488,8 +485,6 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
488 }); 485 });
489 486
490 EndTransformFeedback(); 487 EndTransformFeedback();
491
492 system.GPU().TickWork();
493} 488}
494 489
495void RasterizerVulkan::Clear() { 490void RasterizerVulkan::Clear() {