diff options
| author | 2021-06-06 00:11:36 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:35 -0400 | |
| commit | cffd4716c5ebf9b93505b5bfa96d9b407f349336 (patch) | |
| tree | e94c3daa5420fc066695b1082b0f0af60c5cb555 | |
| parent | vk_pipeline_cache: Add asynchronous shaders (diff) | |
| download | yuzu-cffd4716c5ebf9b93505b5bfa96d9b407f349336.tar.gz yuzu-cffd4716c5ebf9b93505b5bfa96d9b407f349336.tar.xz yuzu-cffd4716c5ebf9b93505b5bfa96d9b407f349336.zip | |
vk_pipeline_cache,shader_notify: Add shader notifications
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.h | 22 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 50 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader_notify.cpp | 51 | ||||
| -rw-r--r-- | src/video_core/shader_notify.h | 28 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 12 |
10 files changed, 127 insertions, 96 deletions
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index ca59042ff..cc855a62e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 14 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| 15 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 15 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 16 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 16 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 17 | #include "video_core/shader_notify.h" | ||
| 17 | #include "video_core/vulkan_common/vulkan_device.h" | 18 | #include "video_core/vulkan_common/vulkan_device.h" |
| 18 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 19 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 19 | 20 | ||
| @@ -24,14 +25,18 @@ using Tegra::Texture::TexturePair; | |||
| 24 | 25 | ||
| 25 | ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, | 26 | ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, |
| 26 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 27 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 27 | Common::ThreadWorker* thread_worker, const Shader::Info& info_, | 28 | Common::ThreadWorker* thread_worker, |
| 29 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, | ||
| 28 | vk::ShaderModule spv_module_) | 30 | vk::ShaderModule spv_module_) |
| 29 | : device{device_}, update_descriptor_queue{update_descriptor_queue_}, info{info_}, | 31 | : device{device_}, update_descriptor_queue{update_descriptor_queue_}, info{info_}, |
| 30 | spv_module(std::move(spv_module_)) { | 32 | spv_module(std::move(spv_module_)) { |
| 33 | if (shader_notify) { | ||
| 34 | shader_notify->MarkShaderBuilding(); | ||
| 35 | } | ||
| 31 | std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), | 36 | std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), |
| 32 | uniform_buffer_sizes.begin()); | 37 | uniform_buffer_sizes.begin()); |
| 33 | 38 | ||
| 34 | auto func{[this, &descriptor_pool] { | 39 | auto func{[this, &descriptor_pool, shader_notify] { |
| 35 | DescriptorLayoutBuilder builder{device.GetLogical()}; | 40 | DescriptorLayoutBuilder builder{device.GetLogical()}; |
| 36 | builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); | 41 | builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); |
| 37 | 42 | ||
| @@ -66,6 +71,9 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 66 | std::lock_guard lock{build_mutex}; | 71 | std::lock_guard lock{build_mutex}; |
| 67 | is_built = true; | 72 | is_built = true; |
| 68 | build_condvar.notify_one(); | 73 | build_condvar.notify_one(); |
| 74 | if (shader_notify) { | ||
| 75 | shader_notify->MarkShaderComplete(); | ||
| 76 | } | ||
| 69 | }}; | 77 | }}; |
| 70 | if (thread_worker) { | 78 | if (thread_worker) { |
| 71 | thread_worker->QueueWork(std::move(func)); | 79 | thread_worker->QueueWork(std::move(func)); |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index a6043866d..52fec04d3 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h | |||
| @@ -18,6 +18,10 @@ | |||
| 18 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 18 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 19 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 19 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 20 | 20 | ||
| 21 | namespace VideoCore { | ||
| 22 | class ShaderNotify; | ||
| 23 | } | ||
| 24 | |||
| 21 | namespace Vulkan { | 25 | namespace Vulkan { |
| 22 | 26 | ||
| 23 | class Device; | 27 | class Device; |
| @@ -27,7 +31,8 @@ class ComputePipeline { | |||
| 27 | public: | 31 | public: |
| 28 | explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, | 32 | explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, |
| 29 | VKUpdateDescriptorQueue& update_descriptor_queue, | 33 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 30 | Common::ThreadWorker* thread_worker, const Shader::Info& info, | 34 | Common::ThreadWorker* thread_worker, |
| 35 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info, | ||
| 31 | vk::ShaderModule spv_module); | 36 | vk::ShaderModule spv_module); |
| 32 | 37 | ||
| 33 | ComputePipeline& operator=(ComputePipeline&&) noexcept = delete; | 38 | ComputePipeline& operator=(ComputePipeline&&) noexcept = delete; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 627ca0158..5c916c869 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 17 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 18 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 18 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 19 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 19 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 20 | #include "video_core/shader_notify.h" | ||
| 20 | #include "video_core/vulkan_common/vulkan_device.h" | 21 | #include "video_core/vulkan_common/vulkan_device.h" |
| 21 | 22 | ||
| 22 | #if defined(_MSC_VER) && defined(NDEBUG) | 23 | #if defined(_MSC_VER) && defined(NDEBUG) |
| @@ -203,30 +204,30 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m | |||
| 203 | } | 204 | } |
| 204 | } // Anonymous namespace | 205 | } // Anonymous namespace |
| 205 | 206 | ||
| 206 | GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_, | 207 | GraphicsPipeline::GraphicsPipeline( |
| 207 | Tegra::MemoryManager& gpu_memory_, VKScheduler& scheduler_, | 208 | Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, |
| 208 | BufferCache& buffer_cache_, TextureCache& texture_cache_, | 209 | VKScheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, |
| 209 | const Device& device_, DescriptorPool& descriptor_pool, | 210 | VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, |
| 210 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 211 | VKUpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, |
| 211 | Common::ThreadWorker* worker_thread, | 212 | RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key_, |
| 212 | RenderPassCache& render_pass_cache, | 213 | std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 213 | const GraphicsPipelineCacheKey& key_, | 214 | const std::array<const Shader::Info*, NUM_STAGES>& infos) |
| 214 | std::array<vk::ShaderModule, NUM_STAGES> stages, | ||
| 215 | const std::array<const Shader::Info*, NUM_STAGES>& infos) | ||
| 216 | : key{key_}, maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, device{device_}, | 215 | : key{key_}, maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, device{device_}, |
| 217 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, scheduler{scheduler_}, | 216 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, scheduler{scheduler_}, |
| 218 | update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} { | 217 | update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} { |
| 219 | std::ranges::transform(infos, stage_infos.begin(), | 218 | if (shader_notify) { |
| 220 | [](const Shader::Info* info) { return info ? *info : Shader::Info{}; }); | 219 | shader_notify->MarkShaderBuilding(); |
| 220 | } | ||
| 221 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | 221 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { |
| 222 | const Shader::Info* const info{infos[stage]}; | 222 | const Shader::Info* const info{infos[stage]}; |
| 223 | if (!info) { | 223 | if (!info) { |
| 224 | continue; | 224 | continue; |
| 225 | } | 225 | } |
| 226 | stage_infos[stage] = *info; | ||
| 226 | enabled_uniform_buffer_masks[stage] = info->constant_buffer_mask; | 227 | enabled_uniform_buffer_masks[stage] = info->constant_buffer_mask; |
| 227 | std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); | 228 | std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); |
| 228 | } | 229 | } |
| 229 | auto func{[this, &render_pass_cache, &descriptor_pool] { | 230 | auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool] { |
| 230 | DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; | 231 | DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; |
| 231 | descriptor_set_layout = builder.CreateDescriptorSetLayout(); | 232 | descriptor_set_layout = builder.CreateDescriptorSetLayout(); |
| 232 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos); | 233 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos); |
| @@ -242,6 +243,9 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_, | |||
| 242 | std::lock_guard lock{build_mutex}; | 243 | std::lock_guard lock{build_mutex}; |
| 243 | is_built = true; | 244 | is_built = true; |
| 244 | build_condvar.notify_one(); | 245 | build_condvar.notify_one(); |
| 246 | if (shader_notify) { | ||
| 247 | shader_notify->MarkShaderComplete(); | ||
| 248 | } | ||
| 245 | }}; | 249 | }}; |
| 246 | if (worker_thread) { | 250 | if (worker_thread) { |
| 247 | worker_thread->QueueWork(std::move(func)); | 251 | worker_thread->QueueWork(std::move(func)); |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 3f8895927..40d1edabd 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -20,6 +20,10 @@ | |||
| 20 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 20 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 21 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 21 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 22 | 22 | ||
| 23 | namespace VideoCore { | ||
| 24 | class ShaderNotify; | ||
| 25 | } | ||
| 26 | |||
| 23 | namespace Vulkan { | 27 | namespace Vulkan { |
| 24 | 28 | ||
| 25 | struct GraphicsPipelineCacheKey { | 29 | struct GraphicsPipelineCacheKey { |
| @@ -64,16 +68,14 @@ class GraphicsPipeline { | |||
| 64 | static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; | 68 | static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; |
| 65 | 69 | ||
| 66 | public: | 70 | public: |
| 67 | explicit GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d, | 71 | explicit GraphicsPipeline( |
| 68 | Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler, | 72 | Tegra::Engines::Maxwell3D& maxwell3d, Tegra::MemoryManager& gpu_memory, |
| 69 | BufferCache& buffer_cache, TextureCache& texture_cache, | 73 | VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, |
| 70 | const Device& device, DescriptorPool& descriptor_pool, | 74 | VideoCore::ShaderNotify* shader_notify, const Device& device, |
| 71 | VKUpdateDescriptorQueue& update_descriptor_queue, | 75 | DescriptorPool& descriptor_pool, VKUpdateDescriptorQueue& update_descriptor_queue, |
| 72 | Common::ThreadWorker* worker_thread, | 76 | Common::ThreadWorker* worker_thread, RenderPassCache& render_pass_cache, |
| 73 | RenderPassCache& render_pass_cache, | 77 | const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 74 | const GraphicsPipelineCacheKey& key, | 78 | const std::array<const Shader::Info*, NUM_STAGES>& infos); |
| 75 | std::array<vk::ShaderModule, NUM_STAGES> stages, | ||
| 76 | const std::array<const Shader::Info*, NUM_STAGES>& infos); | ||
| 77 | 79 | ||
| 78 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; | 80 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; |
| 79 | GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; | 81 | GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 741ed1a98..e61d76490 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -235,11 +235,11 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw | |||
| 235 | VKScheduler& scheduler_, DescriptorPool& descriptor_pool_, | 235 | VKScheduler& scheduler_, DescriptorPool& descriptor_pool_, |
| 236 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 236 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 237 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, | 237 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, |
| 238 | TextureCache& texture_cache_) | 238 | TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) |
| 239 | : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, | 239 | : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, |
| 240 | device{device_}, scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, | 240 | device{device_}, scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, |
| 241 | update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_}, | 241 | update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_}, |
| 242 | buffer_cache{buffer_cache_}, texture_cache{texture_cache_}, | 242 | buffer_cache{buffer_cache_}, texture_cache{texture_cache_}, shader_notify{shader_notify_}, |
| 243 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, | 243 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, |
| 244 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:PipelineBuilder"), | 244 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:PipelineBuilder"), |
| 245 | serialization_thread(1, "yuzu:PipelineSerialization") { | 245 | serialization_thread(1, "yuzu:PipelineSerialization") { |
| @@ -307,19 +307,7 @@ GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() { | |||
| 307 | return BuiltPipeline(current_pipeline); | 307 | return BuiltPipeline(current_pipeline); |
| 308 | } | 308 | } |
| 309 | } | 309 | } |
| 310 | const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; | 310 | return CurrentGraphicsPipelineSlowPath(); |
| 311 | auto& pipeline{pair->second}; | ||
| 312 | if (is_new) { | ||
| 313 | pipeline = CreateGraphicsPipeline(); | ||
| 314 | } | ||
| 315 | if (!pipeline) { | ||
| 316 | return nullptr; | ||
| 317 | } | ||
| 318 | if (current_pipeline) { | ||
| 319 | current_pipeline->AddTransition(pipeline.get()); | ||
| 320 | } | ||
| 321 | current_pipeline = pipeline.get(); | ||
| 322 | return BuiltPipeline(current_pipeline); | ||
| 323 | } | 311 | } |
| 324 | 312 | ||
| 325 | ComputePipeline* PipelineCache::CurrentComputePipeline() { | 313 | ComputePipeline* PipelineCache::CurrentComputePipeline() { |
| @@ -416,6 +404,22 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 416 | workers.WaitForRequests(); | 404 | workers.WaitForRequests(); |
| 417 | } | 405 | } |
| 418 | 406 | ||
| 407 | GraphicsPipeline* PipelineCache::CurrentGraphicsPipelineSlowPath() { | ||
| 408 | const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; | ||
| 409 | auto& pipeline{pair->second}; | ||
| 410 | if (is_new) { | ||
| 411 | pipeline = CreateGraphicsPipeline(); | ||
| 412 | } | ||
| 413 | if (!pipeline) { | ||
| 414 | return nullptr; | ||
| 415 | } | ||
| 416 | if (current_pipeline) { | ||
| 417 | current_pipeline->AddTransition(pipeline.get()); | ||
| 418 | } | ||
| 419 | current_pipeline = pipeline.get(); | ||
| 420 | return BuiltPipeline(current_pipeline); | ||
| 421 | } | ||
| 422 | |||
| 419 | GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const noexcept { | 423 | GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const noexcept { |
| 420 | if (pipeline->IsBuilt()) { | 424 | if (pipeline->IsBuilt()) { |
| 421 | return pipeline; | 425 | return pipeline; |
| @@ -484,14 +488,16 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 484 | device.SaveShader(code); | 488 | device.SaveShader(code); |
| 485 | modules[stage_index] = BuildShader(device, code); | 489 | modules[stage_index] = BuildShader(device, code); |
| 486 | if (device.HasDebuggingToolAttached()) { | 490 | if (device.HasDebuggingToolAttached()) { |
| 487 | const std::string name{fmt::format("{:016x}", key.unique_hashes[index])}; | 491 | const std::string name{fmt::format("Shader {:016x}", key.unique_hashes[index])}; |
| 488 | modules[stage_index].SetObjectNameEXT(name.c_str()); | 492 | modules[stage_index].SetObjectNameEXT(name.c_str()); |
| 489 | } | 493 | } |
| 490 | } | 494 | } |
| 491 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 495 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 492 | return std::make_unique<GraphicsPipeline>( | 496 | VideoCore::ShaderNotify* const notify{build_in_parallel ? &shader_notify : nullptr}; |
| 493 | maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, device, descriptor_pool, | 497 | return std::make_unique<GraphicsPipeline>(maxwell3d, gpu_memory, scheduler, buffer_cache, |
| 494 | update_descriptor_queue, thread_worker, render_pass_cache, key, std::move(modules), infos); | 498 | texture_cache, notify, device, descriptor_pool, |
| 499 | update_descriptor_queue, thread_worker, | ||
| 500 | render_pass_cache, key, std::move(modules), infos); | ||
| 495 | 501 | ||
| 496 | } catch (const Shader::Exception& exception) { | 502 | } catch (const Shader::Exception& exception) { |
| 497 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); | 503 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); |
| @@ -550,12 +556,14 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 550 | device.SaveShader(code); | 556 | device.SaveShader(code); |
| 551 | vk::ShaderModule spv_module{BuildShader(device, code)}; | 557 | vk::ShaderModule spv_module{BuildShader(device, code)}; |
| 552 | if (device.HasDebuggingToolAttached()) { | 558 | if (device.HasDebuggingToolAttached()) { |
| 553 | const auto name{fmt::format("{:016x}", key.unique_hash)}; | 559 | const auto name{fmt::format("Shader {:016x}", key.unique_hash)}; |
| 554 | spv_module.SetObjectNameEXT(name.c_str()); | 560 | spv_module.SetObjectNameEXT(name.c_str()); |
| 555 | } | 561 | } |
| 556 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 562 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 563 | VideoCore::ShaderNotify* const notify{build_in_parallel ? &shader_notify : nullptr}; | ||
| 557 | return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue, | 564 | return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue, |
| 558 | thread_worker, program.info, std::move(spv_module)); | 565 | thread_worker, notify, program.info, |
| 566 | std::move(spv_module)); | ||
| 559 | 567 | ||
| 560 | } catch (const Shader::Exception& exception) { | 568 | } catch (const Shader::Exception& exception) { |
| 561 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); | 569 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 869c63baf..167a2ee2e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -38,6 +38,10 @@ namespace Shader::IR { | |||
| 38 | struct Program; | 38 | struct Program; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | namespace VideoCore { | ||
| 42 | class ShaderNotify; | ||
| 43 | } | ||
| 44 | |||
| 41 | namespace Vulkan { | 45 | namespace Vulkan { |
| 42 | 46 | ||
| 43 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 47 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| @@ -104,7 +108,7 @@ public: | |||
| 104 | VKScheduler& scheduler, DescriptorPool& descriptor_pool, | 108 | VKScheduler& scheduler, DescriptorPool& descriptor_pool, |
| 105 | VKUpdateDescriptorQueue& update_descriptor_queue, | 109 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 106 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, | 110 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, |
| 107 | TextureCache& texture_cache); | 111 | TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); |
| 108 | ~PipelineCache(); | 112 | ~PipelineCache(); |
| 109 | 113 | ||
| 110 | [[nodiscard]] GraphicsPipeline* CurrentGraphicsPipeline(); | 114 | [[nodiscard]] GraphicsPipeline* CurrentGraphicsPipeline(); |
| @@ -115,6 +119,8 @@ public: | |||
| 115 | const VideoCore::DiskResourceLoadCallback& callback); | 119 | const VideoCore::DiskResourceLoadCallback& callback); |
| 116 | 120 | ||
| 117 | private: | 121 | private: |
| 122 | [[nodiscard]] GraphicsPipeline* CurrentGraphicsPipelineSlowPath(); | ||
| 123 | |||
| 118 | [[nodiscard]] GraphicsPipeline* BuiltPipeline(GraphicsPipeline* pipeline) const noexcept; | 124 | [[nodiscard]] GraphicsPipeline* BuiltPipeline(GraphicsPipeline* pipeline) const noexcept; |
| 119 | 125 | ||
| 120 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(); | 126 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(); |
| @@ -138,6 +144,7 @@ private: | |||
| 138 | RenderPassCache& render_pass_cache; | 144 | RenderPassCache& render_pass_cache; |
| 139 | BufferCache& buffer_cache; | 145 | BufferCache& buffer_cache; |
| 140 | TextureCache& texture_cache; | 146 | TextureCache& texture_cache; |
| 147 | VideoCore::ShaderNotify& shader_notify; | ||
| 141 | 148 | ||
| 142 | GraphicsPipelineCacheKey graphics_key{}; | 149 | GraphicsPipelineCacheKey graphics_key{}; |
| 143 | GraphicsPipeline* current_pipeline{}; | 150 | GraphicsPipeline* current_pipeline{}; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index e72f8426b..d284b3653 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -140,7 +140,7 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 140 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), | 140 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), |
| 141 | pipeline_cache(*this, maxwell3d, kepler_compute, gpu_memory, device, scheduler, | 141 | pipeline_cache(*this, maxwell3d, kepler_compute, gpu_memory, device, scheduler, |
| 142 | descriptor_pool, update_descriptor_queue, render_pass_cache, buffer_cache, | 142 | descriptor_pool, update_descriptor_queue, render_pass_cache, buffer_cache, |
| 143 | texture_cache), | 143 | texture_cache, gpu.ShaderNotify()), |
| 144 | query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, accelerate_dma{ buffer_cache }, | 144 | query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, accelerate_dma{ buffer_cache }, |
| 145 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), | 145 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), |
| 146 | wfi_event(device.GetLogical().CreateEvent()) { | 146 | wfi_event(device.GetLogical().CreateEvent()) { |
diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp index 693e47158..dc6995b46 100644 --- a/src/video_core/shader_notify.cpp +++ b/src/video_core/shader_notify.cpp | |||
| @@ -2,42 +2,35 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <mutex> | 5 | #include <atomic> |
| 6 | #include <chrono> | ||
| 7 | #include <optional> | ||
| 8 | |||
| 6 | #include "video_core/shader_notify.h" | 9 | #include "video_core/shader_notify.h" |
| 7 | 10 | ||
| 8 | using namespace std::chrono_literals; | 11 | using namespace std::chrono_literals; |
| 9 | 12 | ||
| 10 | namespace VideoCore { | 13 | namespace VideoCore { |
| 11 | namespace { | ||
| 12 | constexpr auto UPDATE_TICK = 32ms; | ||
| 13 | } | ||
| 14 | |||
| 15 | ShaderNotify::ShaderNotify() = default; | ||
| 16 | ShaderNotify::~ShaderNotify() = default; | ||
| 17 | 14 | ||
| 18 | std::size_t ShaderNotify::GetShadersBuilding() { | 15 | const auto TIME_TO_STOP_REPORTING = 2s; |
| 19 | const auto now = std::chrono::high_resolution_clock::now(); | 16 | |
| 20 | const auto diff = now - last_update; | 17 | int ShaderNotify::ShadersBuilding() noexcept { |
| 21 | if (diff > UPDATE_TICK) { | 18 | const int now_complete = num_complete.load(std::memory_order::relaxed); |
| 22 | std::shared_lock lock(mutex); | 19 | const int now_building = num_building.load(std::memory_order::relaxed); |
| 23 | last_updated_count = accurate_count; | 20 | if (now_complete == now_building) { |
| 21 | const auto now = std::chrono::high_resolution_clock::now(); | ||
| 22 | if (completed && num_complete == num_when_completed) { | ||
| 23 | if (now - complete_time > TIME_TO_STOP_REPORTING) { | ||
| 24 | report_base = now_complete; | ||
| 25 | completed = false; | ||
| 26 | } | ||
| 27 | } else { | ||
| 28 | completed = true; | ||
| 29 | num_when_completed = num_complete; | ||
| 30 | complete_time = now; | ||
| 31 | } | ||
| 24 | } | 32 | } |
| 25 | return last_updated_count; | 33 | return now_building - report_base; |
| 26 | } | ||
| 27 | |||
| 28 | std::size_t ShaderNotify::GetShadersBuildingAccurate() { | ||
| 29 | std::shared_lock lock{mutex}; | ||
| 30 | return accurate_count; | ||
| 31 | } | ||
| 32 | |||
| 33 | void ShaderNotify::MarkShaderComplete() { | ||
| 34 | std::unique_lock lock{mutex}; | ||
| 35 | accurate_count--; | ||
| 36 | } | ||
| 37 | |||
| 38 | void ShaderNotify::MarkSharderBuilding() { | ||
| 39 | std::unique_lock lock{mutex}; | ||
| 40 | accurate_count++; | ||
| 41 | } | 34 | } |
| 42 | 35 | ||
| 43 | } // namespace VideoCore | 36 | } // namespace VideoCore |
diff --git a/src/video_core/shader_notify.h b/src/video_core/shader_notify.h index a9c92d179..ad363bfb5 100644 --- a/src/video_core/shader_notify.h +++ b/src/video_core/shader_notify.h | |||
| @@ -4,26 +4,30 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 7 | #include <chrono> | 8 | #include <chrono> |
| 8 | #include <shared_mutex> | 9 | #include <optional> |
| 9 | #include "common/common_types.h" | ||
| 10 | 10 | ||
| 11 | namespace VideoCore { | 11 | namespace VideoCore { |
| 12 | class ShaderNotify { | 12 | class ShaderNotify { |
| 13 | public: | 13 | public: |
| 14 | ShaderNotify(); | 14 | [[nodiscard]] int ShadersBuilding() noexcept; |
| 15 | ~ShaderNotify(); | ||
| 16 | 15 | ||
| 17 | std::size_t GetShadersBuilding(); | 16 | void MarkShaderComplete() noexcept { |
| 18 | std::size_t GetShadersBuildingAccurate(); | 17 | ++num_complete; |
| 18 | } | ||
| 19 | 19 | ||
| 20 | void MarkShaderComplete(); | 20 | void MarkShaderBuilding() noexcept { |
| 21 | void MarkSharderBuilding(); | 21 | ++num_building; |
| 22 | } | ||
| 22 | 23 | ||
| 23 | private: | 24 | private: |
| 24 | std::size_t last_updated_count{}; | 25 | std::atomic_int num_building{}; |
| 25 | std::size_t accurate_count{}; | 26 | std::atomic_int num_complete{}; |
| 26 | std::shared_mutex mutex; | 27 | int report_base{}; |
| 27 | std::chrono::high_resolution_clock::time_point last_update{}; | 28 | |
| 29 | bool completed{}; | ||
| 30 | int num_when_completed{}; | ||
| 31 | std::chrono::high_resolution_clock::time_point complete_time; | ||
| 28 | }; | 32 | }; |
| 29 | } // namespace VideoCore | 33 | } // namespace VideoCore |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 03a909d17..7e0b1adc4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2900,13 +2900,13 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2900 | return; | 2900 | return; |
| 2901 | } | 2901 | } |
| 2902 | 2902 | ||
| 2903 | auto results = Core::System::GetInstance().GetAndResetPerfStats(); | 2903 | auto& system = Core::System::GetInstance(); |
| 2904 | auto& shader_notify = Core::System::GetInstance().GPU().ShaderNotify(); | 2904 | auto results = system.GetAndResetPerfStats(); |
| 2905 | const auto shaders_building = shader_notify.GetShadersBuilding(); | 2905 | auto& shader_notify = system.GPU().ShaderNotify(); |
| 2906 | const int shaders_building = shader_notify.ShadersBuilding(); | ||
| 2906 | 2907 | ||
| 2907 | if (shaders_building != 0) { | 2908 | if (shaders_building > 0) { |
| 2908 | shader_building_label->setText( | 2909 | shader_building_label->setText(tr("Building: %n shader(s)", "", shaders_building)); |
| 2909 | tr("Building: %n shader(s)", "", static_cast<int>(shaders_building))); | ||
| 2910 | shader_building_label->setVisible(true); | 2910 | shader_building_label->setVisible(true); |
| 2911 | } else { | 2911 | } else { |
| 2912 | shader_building_label->setVisible(false); | 2912 | shader_building_label->setVisible(false); |