diff options
Diffstat (limited to 'src')
27 files changed, 332 insertions, 38 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index cfc1ab46f..a88ee045d 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -319,6 +319,7 @@ struct Values { | |||
| 319 | // Renderer | 319 | // Renderer |
| 320 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; | 320 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; |
| 321 | BasicSetting<bool> renderer_debug{false, "debug"}; | 321 | BasicSetting<bool> renderer_debug{false, "debug"}; |
| 322 | BasicSetting<bool> renderer_shader_feedback{false, "shader_feedback"}; | ||
| 322 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | 323 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; |
| 323 | BasicSetting<bool> disable_shader_loop_safety_checks{false, | 324 | BasicSetting<bool> disable_shader_loop_safety_checks{false, |
| 324 | "disable_shader_loop_safety_checks"}; | 325 | "disable_shader_loop_safety_checks"}; |
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp index 7cae90609..673abb755 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp | |||
| @@ -377,7 +377,7 @@ void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) { | |||
| 377 | 377 | ||
| 378 | if (swkbd_config_common.use_utf8) { | 378 | if (swkbd_config_common.use_utf8) { |
| 379 | std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text); | 379 | std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text); |
| 380 | const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size(); | 380 | const u64 buffer_size = utf8_submitted_text.size(); |
| 381 | 381 | ||
| 382 | LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size, | 382 | LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size, |
| 383 | utf8_submitted_text); | 383 | utf8_submitted_text); |
| @@ -386,7 +386,7 @@ void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) { | |||
| 386 | std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(), | 386 | std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(), |
| 387 | utf8_submitted_text.size()); | 387 | utf8_submitted_text.size()); |
| 388 | } else { | 388 | } else { |
| 389 | const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t); | 389 | const u64 buffer_size = current_text.size() * sizeof(char16_t); |
| 390 | 390 | ||
| 391 | LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size, | 391 | LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size, |
| 392 | Common::UTF16ToUTF8(current_text)); | 392 | Common::UTF16ToUTF8(current_text)); |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 007ecc13e..333f6f35f 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -106,6 +106,8 @@ add_library(video_core STATIC | |||
| 106 | renderer_vulkan/maxwell_to_vk.cpp | 106 | renderer_vulkan/maxwell_to_vk.cpp |
| 107 | renderer_vulkan/maxwell_to_vk.h | 107 | renderer_vulkan/maxwell_to_vk.h |
| 108 | renderer_vulkan/pipeline_helper.h | 108 | renderer_vulkan/pipeline_helper.h |
| 109 | renderer_vulkan/pipeline_statistics.cpp | ||
| 110 | renderer_vulkan/pipeline_statistics.h | ||
| 109 | renderer_vulkan/renderer_vulkan.h | 111 | renderer_vulkan/renderer_vulkan.h |
| 110 | renderer_vulkan/renderer_vulkan.cpp | 112 | renderer_vulkan/renderer_vulkan.cpp |
| 111 | renderer_vulkan/vk_blit_screen.cpp | 113 | renderer_vulkan/vk_blit_screen.cpp |
diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.cpp b/src/video_core/renderer_vulkan/pipeline_statistics.cpp new file mode 100644 index 000000000..bfec931a6 --- /dev/null +++ b/src/video_core/renderer_vulkan/pipeline_statistics.cpp | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <string_view> | ||
| 6 | |||
| 7 | #include <fmt/format.h> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "video_core/renderer_vulkan/pipeline_statistics.h" | ||
| 12 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 14 | |||
| 15 | namespace Vulkan { | ||
| 16 | |||
| 17 | using namespace std::string_view_literals; | ||
| 18 | |||
| 19 | static u64 GetUint64(const VkPipelineExecutableStatisticKHR& statistic) { | ||
| 20 | switch (statistic.format) { | ||
| 21 | case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR: | ||
| 22 | return static_cast<u64>(statistic.value.i64); | ||
| 23 | case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR: | ||
| 24 | return statistic.value.u64; | ||
| 25 | case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR: | ||
| 26 | return static_cast<u64>(statistic.value.f64); | ||
| 27 | default: | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | PipelineStatistics::PipelineStatistics(const Device& device_) : device{device_} {} | ||
| 33 | |||
| 34 | void PipelineStatistics::Collect(VkPipeline pipeline) { | ||
| 35 | const auto& dev{device.GetLogical()}; | ||
| 36 | const std::vector properties{dev.GetPipelineExecutablePropertiesKHR(pipeline)}; | ||
| 37 | const u32 num_executables{static_cast<u32>(properties.size())}; | ||
| 38 | for (u32 executable = 0; executable < num_executables; ++executable) { | ||
| 39 | const auto statistics{dev.GetPipelineExecutableStatisticsKHR(pipeline, executable)}; | ||
| 40 | if (statistics.empty()) { | ||
| 41 | continue; | ||
| 42 | } | ||
| 43 | Stats stage_stats; | ||
| 44 | for (const auto& statistic : statistics) { | ||
| 45 | const char* const name{statistic.name}; | ||
| 46 | if (name == "Binary Size"sv || name == "Code size"sv || name == "Instruction Count"sv) { | ||
| 47 | stage_stats.code_size = GetUint64(statistic); | ||
| 48 | } else if (name == "Register Count"sv) { | ||
| 49 | stage_stats.register_count = GetUint64(statistic); | ||
| 50 | } else if (name == "SGPRs"sv || name == "numUsedSgprs"sv) { | ||
| 51 | stage_stats.sgpr_count = GetUint64(statistic); | ||
| 52 | } else if (name == "VGPRs"sv || name == "numUsedVgprs"sv) { | ||
| 53 | stage_stats.vgpr_count = GetUint64(statistic); | ||
| 54 | } else if (name == "Branches"sv) { | ||
| 55 | stage_stats.branches_count = GetUint64(statistic); | ||
| 56 | } else if (name == "Basic Block Count"sv) { | ||
| 57 | stage_stats.basic_block_count = GetUint64(statistic); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | std::lock_guard lock{mutex}; | ||
| 61 | collected_stats.push_back(stage_stats); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | void PipelineStatistics::Report() const { | ||
| 66 | double num{}; | ||
| 67 | Stats total; | ||
| 68 | { | ||
| 69 | std::lock_guard lock{mutex}; | ||
| 70 | for (const Stats& stats : collected_stats) { | ||
| 71 | total.code_size += stats.code_size; | ||
| 72 | total.register_count += stats.register_count; | ||
| 73 | total.sgpr_count += stats.sgpr_count; | ||
| 74 | total.vgpr_count += stats.vgpr_count; | ||
| 75 | total.branches_count += stats.branches_count; | ||
| 76 | total.basic_block_count += stats.basic_block_count; | ||
| 77 | } | ||
| 78 | num = static_cast<double>(collected_stats.size()); | ||
| 79 | } | ||
| 80 | std::string report; | ||
| 81 | const auto add = [&](const char* fmt, u64 value) { | ||
| 82 | if (value > 0) { | ||
| 83 | report += fmt::format(fmt::runtime(fmt), static_cast<double>(value) / num); | ||
| 84 | } | ||
| 85 | }; | ||
| 86 | add("Code size: {:9.03f}\n", total.code_size); | ||
| 87 | add("Register count: {:9.03f}\n", total.register_count); | ||
| 88 | add("SGPRs: {:9.03f}\n", total.sgpr_count); | ||
| 89 | add("VGPRs: {:9.03f}\n", total.vgpr_count); | ||
| 90 | add("Branches count: {:9.03f}\n", total.branches_count); | ||
| 91 | add("Basic blocks: {:9.03f}\n", total.basic_block_count); | ||
| 92 | |||
| 93 | LOG_INFO(Render_Vulkan, | ||
| 94 | "\nAverage pipeline statistics\n" | ||
| 95 | "==========================================\n" | ||
| 96 | "{}\n", | ||
| 97 | report); | ||
| 98 | } | ||
| 99 | |||
| 100 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.h b/src/video_core/renderer_vulkan/pipeline_statistics.h new file mode 100644 index 000000000..b61840107 --- /dev/null +++ b/src/video_core/renderer_vulkan/pipeline_statistics.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <mutex> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 12 | |||
| 13 | namespace Vulkan { | ||
| 14 | |||
| 15 | class Device; | ||
| 16 | |||
| 17 | class PipelineStatistics { | ||
| 18 | public: | ||
| 19 | explicit PipelineStatistics(const Device& device_); | ||
| 20 | |||
| 21 | void Collect(VkPipeline pipeline); | ||
| 22 | |||
| 23 | void Report() const; | ||
| 24 | |||
| 25 | private: | ||
| 26 | struct Stats { | ||
| 27 | u64 code_size{}; | ||
| 28 | u64 register_count{}; | ||
| 29 | u64 sgpr_count{}; | ||
| 30 | u64 vgpr_count{}; | ||
| 31 | u64 branches_count{}; | ||
| 32 | u64 basic_block_count{}; | ||
| 33 | }; | ||
| 34 | |||
| 35 | const Device& device; | ||
| 36 | mutable std::mutex mutex; | ||
| 37 | std::vector<Stats> collected_stats; | ||
| 38 | }; | ||
| 39 | |||
| 40 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 70b84c7a6..44faf626a 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <boost/container/small_vector.hpp> | 8 | #include <boost/container/small_vector.hpp> |
| 9 | 9 | ||
| 10 | #include "video_core/renderer_vulkan/pipeline_helper.h" | 10 | #include "video_core/renderer_vulkan/pipeline_helper.h" |
| 11 | #include "video_core/renderer_vulkan/pipeline_statistics.h" | ||
| 11 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 12 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 12 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | 13 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" |
| 13 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 14 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| @@ -26,6 +27,7 @@ using Tegra::Texture::TexturePair; | |||
| 26 | ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, | 27 | ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, |
| 27 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 28 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 28 | Common::ThreadWorker* thread_worker, | 29 | Common::ThreadWorker* thread_worker, |
| 30 | PipelineStatistics* pipeline_statistics, | ||
| 29 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, | 31 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, |
| 30 | vk::ShaderModule spv_module_) | 32 | vk::ShaderModule spv_module_) |
| 31 | : device{device_}, update_descriptor_queue{update_descriptor_queue_}, info{info_}, | 33 | : device{device_}, update_descriptor_queue{update_descriptor_queue_}, info{info_}, |
| @@ -36,7 +38,7 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 36 | std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), | 38 | std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), |
| 37 | uniform_buffer_sizes.begin()); | 39 | uniform_buffer_sizes.begin()); |
| 38 | 40 | ||
| 39 | auto func{[this, &descriptor_pool, shader_notify] { | 41 | auto func{[this, &descriptor_pool, shader_notify, pipeline_statistics] { |
| 40 | DescriptorLayoutBuilder builder{device}; | 42 | DescriptorLayoutBuilder builder{device}; |
| 41 | builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); | 43 | builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); |
| 42 | 44 | ||
| @@ -50,10 +52,14 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 50 | .pNext = nullptr, | 52 | .pNext = nullptr, |
| 51 | .requiredSubgroupSize = GuestWarpSize, | 53 | .requiredSubgroupSize = GuestWarpSize, |
| 52 | }; | 54 | }; |
| 55 | VkPipelineCreateFlags flags{}; | ||
| 56 | if (device.IsKhrPipelineEexecutablePropertiesEnabled()) { | ||
| 57 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | ||
| 58 | } | ||
| 53 | pipeline = device.GetLogical().CreateComputePipeline({ | 59 | pipeline = device.GetLogical().CreateComputePipeline({ |
| 54 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | 60 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, |
| 55 | .pNext = nullptr, | 61 | .pNext = nullptr, |
| 56 | .flags = 0, | 62 | .flags = flags, |
| 57 | .stage{ | 63 | .stage{ |
| 58 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 64 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| 59 | .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr, | 65 | .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr, |
| @@ -67,6 +73,9 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 67 | .basePipelineHandle = 0, | 73 | .basePipelineHandle = 0, |
| 68 | .basePipelineIndex = 0, | 74 | .basePipelineIndex = 0, |
| 69 | }); | 75 | }); |
| 76 | if (pipeline_statistics) { | ||
| 77 | pipeline_statistics->Collect(*pipeline); | ||
| 78 | } | ||
| 70 | std::lock_guard lock{build_mutex}; | 79 | std::lock_guard lock{build_mutex}; |
| 71 | is_built = true; | 80 | is_built = true; |
| 72 | build_condvar.notify_one(); | 81 | build_condvar.notify_one(); |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 52fec04d3..8c4b0a301 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h | |||
| @@ -25,6 +25,7 @@ class ShaderNotify; | |||
| 25 | namespace Vulkan { | 25 | namespace Vulkan { |
| 26 | 26 | ||
| 27 | class Device; | 27 | class Device; |
| 28 | class PipelineStatistics; | ||
| 28 | class VKScheduler; | 29 | class VKScheduler; |
| 29 | 30 | ||
| 30 | class ComputePipeline { | 31 | class ComputePipeline { |
| @@ -32,6 +33,7 @@ public: | |||
| 32 | explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, | 33 | explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, |
| 33 | VKUpdateDescriptorQueue& update_descriptor_queue, | 34 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 34 | Common::ThreadWorker* thread_worker, | 35 | Common::ThreadWorker* thread_worker, |
| 36 | PipelineStatistics* pipeline_statistics, | ||
| 35 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info, | 37 | VideoCore::ShaderNotify* shader_notify, const Shader::Info& info, |
| 36 | vk::ShaderModule spv_module); | 38 | vk::ShaderModule spv_module); |
| 37 | 39 | ||
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 18482e1d0..7c0f91007 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/bit_field.h" | 11 | #include "common/bit_field.h" |
| 12 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 12 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 13 | #include "video_core/renderer_vulkan/pipeline_helper.h" | 13 | #include "video_core/renderer_vulkan/pipeline_helper.h" |
| 14 | #include "video_core/renderer_vulkan/pipeline_statistics.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 15 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 15 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" | 16 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" |
| 16 | #include "video_core/renderer_vulkan/vk_render_pass_cache.h" | 17 | #include "video_core/renderer_vulkan/vk_render_pass_cache.h" |
| @@ -217,8 +218,8 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 217 | VKScheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, | 218 | VKScheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, |
| 218 | VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, | 219 | VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, |
| 219 | VKUpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, | 220 | VKUpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, |
| 220 | RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key_, | 221 | PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, |
| 221 | std::array<vk::ShaderModule, NUM_STAGES> stages, | 222 | const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 222 | const std::array<const Shader::Info*, NUM_STAGES>& infos) | 223 | const std::array<const Shader::Info*, NUM_STAGES>& infos) |
| 223 | : key{key_}, maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, device{device_}, | 224 | : key{key_}, maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, device{device_}, |
| 224 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, scheduler{scheduler_}, | 225 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, scheduler{scheduler_}, |
| @@ -235,7 +236,7 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 235 | enabled_uniform_buffer_masks[stage] = info->constant_buffer_mask; | 236 | enabled_uniform_buffer_masks[stage] = info->constant_buffer_mask; |
| 236 | std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); | 237 | std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); |
| 237 | } | 238 | } |
| 238 | auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool] { | 239 | auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics] { |
| 239 | DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; | 240 | DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; |
| 240 | uses_push_descriptor = builder.CanUsePushDescriptor(); | 241 | uses_push_descriptor = builder.CanUsePushDescriptor(); |
| 241 | descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor); | 242 | descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor); |
| @@ -250,6 +251,9 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 250 | const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state))}; | 251 | const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state))}; |
| 251 | Validate(); | 252 | Validate(); |
| 252 | MakePipeline(render_pass); | 253 | MakePipeline(render_pass); |
| 254 | if (pipeline_statistics) { | ||
| 255 | pipeline_statistics->Collect(*pipeline); | ||
| 256 | } | ||
| 253 | 257 | ||
| 254 | std::lock_guard lock{build_mutex}; | 258 | std::lock_guard lock{build_mutex}; |
| 255 | is_built = true; | 259 | is_built = true; |
| @@ -782,10 +786,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 782 | } | 786 | } |
| 783 | */ | 787 | */ |
| 784 | } | 788 | } |
| 789 | VkPipelineCreateFlags flags{}; | ||
| 790 | if (device.IsKhrPipelineEexecutablePropertiesEnabled()) { | ||
| 791 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | ||
| 792 | } | ||
| 785 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | 793 | pipeline = device.GetLogical().CreateGraphicsPipeline({ |
| 786 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | 794 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
| 787 | .pNext = nullptr, | 795 | .pNext = nullptr, |
| 788 | .flags = 0, | 796 | .flags = flags, |
| 789 | .stageCount = static_cast<u32>(shader_stages.size()), | 797 | .stageCount = static_cast<u32>(shader_stages.size()), |
| 790 | .pStages = shader_stages.data(), | 798 | .pStages = shader_stages.data(), |
| 791 | .pVertexInputState = &vertex_input_ci, | 799 | .pVertexInputState = &vertex_input_ci, |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 2bd48d697..1c780e944 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -60,6 +60,7 @@ struct hash<Vulkan::GraphicsPipelineCacheKey> { | |||
| 60 | namespace Vulkan { | 60 | namespace Vulkan { |
| 61 | 61 | ||
| 62 | class Device; | 62 | class Device; |
| 63 | class PipelineStatistics; | ||
| 63 | class RenderPassCache; | 64 | class RenderPassCache; |
| 64 | class VKScheduler; | 65 | class VKScheduler; |
| 65 | class VKUpdateDescriptorQueue; | 66 | class VKUpdateDescriptorQueue; |
| @@ -73,8 +74,9 @@ public: | |||
| 73 | VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, | 74 | VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, |
| 74 | VideoCore::ShaderNotify* shader_notify, const Device& device, | 75 | VideoCore::ShaderNotify* shader_notify, const Device& device, |
| 75 | DescriptorPool& descriptor_pool, VKUpdateDescriptorQueue& update_descriptor_queue, | 76 | DescriptorPool& descriptor_pool, VKUpdateDescriptorQueue& update_descriptor_queue, |
| 76 | Common::ThreadWorker* worker_thread, RenderPassCache& render_pass_cache, | 77 | Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics, |
| 77 | const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages, | 78 | RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key, |
| 79 | std::array<vk::ShaderModule, NUM_STAGES> stages, | ||
| 78 | const std::array<const Shader::Info*, NUM_STAGES>& infos); | 80 | const std::array<const Shader::Info*, NUM_STAGES>& infos); |
| 79 | 81 | ||
| 80 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; | 82 | GraphicsPipeline& operator=(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 57b163247..a37ca1fdf 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 29 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 30 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 30 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 31 | #include "video_core/renderer_vulkan/pipeline_helper.h" | 31 | #include "video_core/renderer_vulkan/pipeline_helper.h" |
| 32 | #include "video_core/renderer_vulkan/pipeline_statistics.h" | ||
| 32 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | 33 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" |
| 33 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 34 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 34 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 35 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| @@ -389,15 +390,19 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 389 | size_t total{}; | 390 | size_t total{}; |
| 390 | size_t built{}; | 391 | size_t built{}; |
| 391 | bool has_loaded{}; | 392 | bool has_loaded{}; |
| 393 | std::unique_ptr<PipelineStatistics> statistics; | ||
| 392 | } state; | 394 | } state; |
| 393 | 395 | ||
| 396 | if (device.IsKhrPipelineEexecutablePropertiesEnabled()) { | ||
| 397 | state.statistics = std::make_unique<PipelineStatistics>(device); | ||
| 398 | } | ||
| 394 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { | 399 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { |
| 395 | ComputePipelineCacheKey key; | 400 | ComputePipelineCacheKey key; |
| 396 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 401 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 397 | 402 | ||
| 398 | workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable { | 403 | workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable { |
| 399 | ShaderPools pools; | 404 | ShaderPools pools; |
| 400 | auto pipeline{CreateComputePipeline(pools, key, env, false)}; | 405 | auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)}; |
| 401 | std::lock_guard lock{state.mutex}; | 406 | std::lock_guard lock{state.mutex}; |
| 402 | if (pipeline) { | 407 | if (pipeline) { |
| 403 | compute_cache.emplace(key, std::move(pipeline)); | 408 | compute_cache.emplace(key, std::move(pipeline)); |
| @@ -425,7 +430,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 425 | for (auto& env : envs) { | 430 | for (auto& env : envs) { |
| 426 | env_ptrs.push_back(&env); | 431 | env_ptrs.push_back(&env); |
| 427 | } | 432 | } |
| 428 | auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), false)}; | 433 | auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), |
| 434 | state.statistics.get(), false)}; | ||
| 429 | 435 | ||
| 430 | std::lock_guard lock{state.mutex}; | 436 | std::lock_guard lock{state.mutex}; |
| 431 | graphics_cache.emplace(key, std::move(pipeline)); | 437 | graphics_cache.emplace(key, std::move(pipeline)); |
| @@ -445,6 +451,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 445 | lock.unlock(); | 451 | lock.unlock(); |
| 446 | 452 | ||
| 447 | workers.WaitForRequests(); | 453 | workers.WaitForRequests(); |
| 454 | |||
| 455 | if (state.statistics) { | ||
| 456 | state.statistics->Report(); | ||
| 457 | } | ||
| 448 | } | 458 | } |
| 449 | 459 | ||
| 450 | GraphicsPipeline* PipelineCache::CurrentGraphicsPipelineSlowPath() { | 460 | GraphicsPipeline* PipelineCache::CurrentGraphicsPipelineSlowPath() { |
| @@ -486,7 +496,8 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const | |||
| 486 | 496 | ||
| 487 | std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | 497 | std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( |
| 488 | ShaderPools& pools, const GraphicsPipelineCacheKey& key, | 498 | ShaderPools& pools, const GraphicsPipelineCacheKey& key, |
| 489 | std::span<Shader::Environment* const> envs, bool build_in_parallel) try { | 499 | std::span<Shader::Environment* const> envs, PipelineStatistics* statistics, |
| 500 | bool build_in_parallel) try { | ||
| 490 | LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); | 501 | LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); |
| 491 | size_t env_index{0}; | 502 | size_t env_index{0}; |
| 492 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 503 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| @@ -540,7 +551,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 540 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 551 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 541 | return std::make_unique<GraphicsPipeline>( | 552 | return std::make_unique<GraphicsPipeline>( |
| 542 | maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, &shader_notify, device, | 553 | maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, &shader_notify, device, |
| 543 | descriptor_pool, update_descriptor_queue, thread_worker, render_pass_cache, key, | 554 | descriptor_pool, update_descriptor_queue, thread_worker, statistics, render_pass_cache, key, |
| 544 | std::move(modules), infos); | 555 | std::move(modules), infos); |
| 545 | 556 | ||
| 546 | } catch (const Shader::Exception& exception) { | 557 | } catch (const Shader::Exception& exception) { |
| @@ -553,7 +564,8 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() { | |||
| 553 | GetGraphicsEnvironments(environments, graphics_key.unique_hashes); | 564 | GetGraphicsEnvironments(environments, graphics_key.unique_hashes); |
| 554 | 565 | ||
| 555 | main_pools.ReleaseContents(); | 566 | main_pools.ReleaseContents(); |
| 556 | auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), true)}; | 567 | auto pipeline{ |
| 568 | CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), nullptr, true)}; | ||
| 557 | if (!pipeline || pipeline_cache_filename.empty()) { | 569 | if (!pipeline || pipeline_cache_filename.empty()) { |
| 558 | return pipeline; | 570 | return pipeline; |
| 559 | } | 571 | } |
| @@ -578,7 +590,7 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 578 | env.SetCachedSize(shader->size_bytes); | 590 | env.SetCachedSize(shader->size_bytes); |
| 579 | 591 | ||
| 580 | main_pools.ReleaseContents(); | 592 | main_pools.ReleaseContents(); |
| 581 | auto pipeline{CreateComputePipeline(main_pools, key, env, true)}; | 593 | auto pipeline{CreateComputePipeline(main_pools, key, env, nullptr, true)}; |
| 582 | if (!pipeline || pipeline_cache_filename.empty()) { | 594 | if (!pipeline || pipeline_cache_filename.empty()) { |
| 583 | return pipeline; | 595 | return pipeline; |
| 584 | } | 596 | } |
| @@ -591,7 +603,7 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 591 | 603 | ||
| 592 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | 604 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( |
| 593 | ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, | 605 | ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, |
| 594 | bool build_in_parallel) try { | 606 | PipelineStatistics* statistics, bool build_in_parallel) try { |
| 595 | LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); | 607 | LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); |
| 596 | 608 | ||
| 597 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; | 609 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; |
| @@ -605,8 +617,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 605 | } | 617 | } |
| 606 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 618 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 607 | return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue, | 619 | return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue, |
| 608 | thread_worker, &shader_notify, program.info, | 620 | thread_worker, statistics, &shader_notify, |
| 609 | std::move(spv_module)); | 621 | program.info, std::move(spv_module)); |
| 610 | 622 | ||
| 611 | } catch (const Shader::Exception& exception) { | 623 | } catch (const Shader::Exception& exception) { |
| 612 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); | 624 | 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 efe5a7ed8..4c135b5dd 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -80,8 +80,9 @@ struct hash<Vulkan::ComputePipelineCacheKey> { | |||
| 80 | namespace Vulkan { | 80 | namespace Vulkan { |
| 81 | 81 | ||
| 82 | class ComputePipeline; | 82 | class ComputePipeline; |
| 83 | class Device; | ||
| 84 | class DescriptorPool; | 83 | class DescriptorPool; |
| 84 | class Device; | ||
| 85 | class PipelineStatistics; | ||
| 85 | class RasterizerVulkan; | 86 | class RasterizerVulkan; |
| 86 | class RenderPassCache; | 87 | class RenderPassCache; |
| 87 | class VKScheduler; | 88 | class VKScheduler; |
| @@ -128,7 +129,8 @@ private: | |||
| 128 | 129 | ||
| 129 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( | 130 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( |
| 130 | ShaderPools& pools, const GraphicsPipelineCacheKey& key, | 131 | ShaderPools& pools, const GraphicsPipelineCacheKey& key, |
| 131 | std::span<Shader::Environment* const> envs, bool build_in_parallel); | 132 | std::span<Shader::Environment* const> envs, PipelineStatistics* statistics, |
| 133 | bool build_in_parallel); | ||
| 132 | 134 | ||
| 133 | std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineCacheKey& key, | 135 | std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineCacheKey& key, |
| 134 | const ShaderInfo* shader); | 136 | const ShaderInfo* shader); |
| @@ -136,6 +138,7 @@ private: | |||
| 136 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderPools& pools, | 138 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderPools& pools, |
| 137 | const ComputePipelineCacheKey& key, | 139 | const ComputePipelineCacheKey& key, |
| 138 | Shader::Environment& env, | 140 | Shader::Environment& env, |
| 141 | PipelineStatistics* statistics, | ||
| 139 | bool build_in_parallel); | 142 | bool build_in_parallel); |
| 140 | 143 | ||
| 141 | const Device& device; | 144 | const Device& device; |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 44afdc1cd..8e56a89e1 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -526,6 +526,17 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 526 | SetNext(next, workgroup_layout); | 526 | SetNext(next, workgroup_layout); |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR executable_properties; | ||
| 530 | if (khr_pipeline_executable_properties) { | ||
| 531 | LOG_INFO(Render_Vulkan, "Enabling shader feedback, expect slower shader build times"); | ||
| 532 | executable_properties = { | ||
| 533 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR, | ||
| 534 | .pNext = nullptr, | ||
| 535 | .pipelineExecutableInfo = VK_TRUE, | ||
| 536 | }; | ||
| 537 | SetNext(next, executable_properties); | ||
| 538 | } | ||
| 539 | |||
| 529 | if (!ext_depth_range_unrestricted) { | 540 | if (!ext_depth_range_unrestricted) { |
| 530 | LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted"); | 541 | LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted"); |
| 531 | } | 542 | } |
| @@ -824,6 +835,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 824 | 835 | ||
| 825 | bool has_khr_shader_float16_int8{}; | 836 | bool has_khr_shader_float16_int8{}; |
| 826 | bool has_khr_workgroup_memory_explicit_layout{}; | 837 | bool has_khr_workgroup_memory_explicit_layout{}; |
| 838 | bool has_khr_pipeline_executable_properties{}; | ||
| 827 | bool has_ext_subgroup_size_control{}; | 839 | bool has_ext_subgroup_size_control{}; |
| 828 | bool has_ext_transform_feedback{}; | 840 | bool has_ext_transform_feedback{}; |
| 829 | bool has_ext_custom_border_color{}; | 841 | bool has_ext_custom_border_color{}; |
| @@ -878,6 +890,10 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 878 | test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, | 890 | test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, |
| 879 | true); | 891 | true); |
| 880 | } | 892 | } |
| 893 | if (Settings::values.renderer_shader_feedback) { | ||
| 894 | test(has_khr_pipeline_executable_properties, | ||
| 895 | VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME, false); | ||
| 896 | } | ||
| 881 | } | 897 | } |
| 882 | VkPhysicalDeviceFeatures2KHR features{}; | 898 | VkPhysicalDeviceFeatures2KHR features{}; |
| 883 | features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; | 899 | features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; |
| @@ -1033,6 +1049,19 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1033 | khr_workgroup_memory_explicit_layout = true; | 1049 | khr_workgroup_memory_explicit_layout = true; |
| 1034 | } | 1050 | } |
| 1035 | } | 1051 | } |
| 1052 | if (has_khr_pipeline_executable_properties) { | ||
| 1053 | VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR executable_properties; | ||
| 1054 | executable_properties.sType = | ||
| 1055 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR; | ||
| 1056 | executable_properties.pNext = nullptr; | ||
| 1057 | features.pNext = &executable_properties; | ||
| 1058 | physical.GetFeatures2KHR(features); | ||
| 1059 | |||
| 1060 | if (executable_properties.pipelineExecutableInfo) { | ||
| 1061 | extensions.push_back(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); | ||
| 1062 | khr_pipeline_executable_properties = true; | ||
| 1063 | } | ||
| 1064 | } | ||
| 1036 | if (khr_push_descriptor) { | 1065 | if (khr_push_descriptor) { |
| 1037 | VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor; | 1066 | VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor; |
| 1038 | push_descriptor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR; | 1067 | push_descriptor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR; |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index df394e384..c19f40746 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -214,6 +214,11 @@ public: | |||
| 214 | return khr_push_descriptor; | 214 | return khr_push_descriptor; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | /// Returns true if VK_KHR_pipeline_executable_properties is enabled. | ||
| 218 | bool IsKhrPipelineEexecutablePropertiesEnabled() const { | ||
| 219 | return khr_pipeline_executable_properties; | ||
| 220 | } | ||
| 221 | |||
| 217 | /// Returns true if the device supports VK_KHR_workgroup_memory_explicit_layout. | 222 | /// Returns true if the device supports VK_KHR_workgroup_memory_explicit_layout. |
| 218 | bool IsKhrWorkgroupMemoryExplicitLayoutSupported() const { | 223 | bool IsKhrWorkgroupMemoryExplicitLayoutSupported() const { |
| 219 | return khr_workgroup_memory_explicit_layout; | 224 | return khr_workgroup_memory_explicit_layout; |
| @@ -378,6 +383,7 @@ private: | |||
| 378 | bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4. | 383 | bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4. |
| 379 | bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts. | 384 | bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts. |
| 380 | bool khr_push_descriptor{}; ///< Support for VK_KHR_push_descritor. | 385 | bool khr_push_descriptor{}; ///< Support for VK_KHR_push_descritor. |
| 386 | bool khr_pipeline_executable_properties{}; ///< Support for executable properties. | ||
| 381 | bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8. | 387 | bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8. |
| 382 | bool ext_sampler_filter_minmax{}; ///< Support for VK_EXT_sampler_filter_minmax. | 388 | bool ext_sampler_filter_minmax{}; ///< Support for VK_EXT_sampler_filter_minmax. |
| 383 | bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted. | 389 | bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted. |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 70898004a..a9faa4807 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -181,6 +181,8 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 181 | X(vkGetMemoryWin32HandleKHR); | 181 | X(vkGetMemoryWin32HandleKHR); |
| 182 | #endif | 182 | #endif |
| 183 | X(vkGetQueryPoolResults); | 183 | X(vkGetQueryPoolResults); |
| 184 | X(vkGetPipelineExecutablePropertiesKHR); | ||
| 185 | X(vkGetPipelineExecutableStatisticsKHR); | ||
| 184 | X(vkGetSemaphoreCounterValueKHR); | 186 | X(vkGetSemaphoreCounterValueKHR); |
| 185 | X(vkMapMemory); | 187 | X(vkMapMemory); |
| 186 | X(vkQueueSubmit); | 188 | X(vkQueueSubmit); |
| @@ -809,6 +811,42 @@ VkMemoryRequirements Device::GetImageMemoryRequirements(VkImage image) const noe | |||
| 809 | return requirements; | 811 | return requirements; |
| 810 | } | 812 | } |
| 811 | 813 | ||
| 814 | std::vector<VkPipelineExecutablePropertiesKHR> Device::GetPipelineExecutablePropertiesKHR( | ||
| 815 | VkPipeline pipeline) const { | ||
| 816 | const VkPipelineInfoKHR info{ | ||
| 817 | .sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, | ||
| 818 | .pNext = nullptr, | ||
| 819 | .pipeline = pipeline, | ||
| 820 | }; | ||
| 821 | u32 num{}; | ||
| 822 | dld->vkGetPipelineExecutablePropertiesKHR(handle, &info, &num, nullptr); | ||
| 823 | std::vector<VkPipelineExecutablePropertiesKHR> properties(num); | ||
| 824 | for (auto& property : properties) { | ||
| 825 | property.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR; | ||
| 826 | } | ||
| 827 | Check(dld->vkGetPipelineExecutablePropertiesKHR(handle, &info, &num, properties.data())); | ||
| 828 | return properties; | ||
| 829 | } | ||
| 830 | |||
| 831 | std::vector<VkPipelineExecutableStatisticKHR> Device::GetPipelineExecutableStatisticsKHR( | ||
| 832 | VkPipeline pipeline, u32 executable_index) const { | ||
| 833 | const VkPipelineExecutableInfoKHR executable_info{ | ||
| 834 | .sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, | ||
| 835 | .pNext = nullptr, | ||
| 836 | .pipeline = pipeline, | ||
| 837 | .executableIndex = executable_index, | ||
| 838 | }; | ||
| 839 | u32 num{}; | ||
| 840 | dld->vkGetPipelineExecutableStatisticsKHR(handle, &executable_info, &num, nullptr); | ||
| 841 | std::vector<VkPipelineExecutableStatisticKHR> statistics(num); | ||
| 842 | for (auto& statistic : statistics) { | ||
| 843 | statistic.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR; | ||
| 844 | } | ||
| 845 | Check(dld->vkGetPipelineExecutableStatisticsKHR(handle, &executable_info, &num, | ||
| 846 | statistics.data())); | ||
| 847 | return statistics; | ||
| 848 | } | ||
| 849 | |||
| 812 | void Device::UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes, | 850 | void Device::UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes, |
| 813 | Span<VkCopyDescriptorSet> copies) const noexcept { | 851 | Span<VkCopyDescriptorSet> copies) const noexcept { |
| 814 | dld->vkUpdateDescriptorSets(handle, writes.size(), writes.data(), copies.size(), copies.data()); | 852 | dld->vkUpdateDescriptorSets(handle, writes.size(), writes.data(), copies.size(), copies.data()); |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index d76bb4324..b7ae01c6c 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -295,6 +295,8 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 295 | #ifdef _WIN32 | 295 | #ifdef _WIN32 |
| 296 | PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{}; | 296 | PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{}; |
| 297 | #endif | 297 | #endif |
| 298 | PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{}; | ||
| 299 | PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{}; | ||
| 298 | PFN_vkGetQueryPoolResults vkGetQueryPoolResults{}; | 300 | PFN_vkGetQueryPoolResults vkGetQueryPoolResults{}; |
| 299 | PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR{}; | 301 | PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR{}; |
| 300 | PFN_vkMapMemory vkMapMemory{}; | 302 | PFN_vkMapMemory vkMapMemory{}; |
| @@ -879,6 +881,12 @@ public: | |||
| 879 | 881 | ||
| 880 | VkMemoryRequirements GetImageMemoryRequirements(VkImage image) const noexcept; | 882 | VkMemoryRequirements GetImageMemoryRequirements(VkImage image) const noexcept; |
| 881 | 883 | ||
| 884 | std::vector<VkPipelineExecutablePropertiesKHR> GetPipelineExecutablePropertiesKHR( | ||
| 885 | VkPipeline pipeline) const; | ||
| 886 | |||
| 887 | std::vector<VkPipelineExecutableStatisticKHR> GetPipelineExecutableStatisticsKHR( | ||
| 888 | VkPipeline pipeline, u32 executable_index) const; | ||
| 889 | |||
| 882 | void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes, | 890 | void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes, |
| 883 | Span<VkCopyDescriptorSet> copies) const noexcept; | 891 | Span<VkCopyDescriptorSet> copies) const noexcept; |
| 884 | 892 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index ecd5dfac1..f3b8787f5 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -825,6 +825,7 @@ void Config::ReadRendererValues() { | |||
| 825 | if (global) { | 825 | if (global) { |
| 826 | ReadBasicSetting(Settings::values.fps_cap); | 826 | ReadBasicSetting(Settings::values.fps_cap); |
| 827 | ReadBasicSetting(Settings::values.renderer_debug); | 827 | ReadBasicSetting(Settings::values.renderer_debug); |
| 828 | ReadBasicSetting(Settings::values.renderer_shader_feedback); | ||
| 828 | ReadBasicSetting(Settings::values.enable_nsight_aftermath); | 829 | ReadBasicSetting(Settings::values.enable_nsight_aftermath); |
| 829 | ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks); | 830 | ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks); |
| 830 | } | 831 | } |
| @@ -1363,6 +1364,7 @@ void Config::SaveRendererValues() { | |||
| 1363 | if (global) { | 1364 | if (global) { |
| 1364 | WriteBasicSetting(Settings::values.fps_cap); | 1365 | WriteBasicSetting(Settings::values.fps_cap); |
| 1365 | WriteBasicSetting(Settings::values.renderer_debug); | 1366 | WriteBasicSetting(Settings::values.renderer_debug); |
| 1367 | WriteBasicSetting(Settings::values.renderer_shader_feedback); | ||
| 1366 | WriteBasicSetting(Settings::values.enable_nsight_aftermath); | 1368 | WriteBasicSetting(Settings::values.enable_nsight_aftermath); |
| 1367 | WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks); | 1369 | WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks); |
| 1368 | } | 1370 | } |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index f7e29dbd7..c0b240c1e 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -43,6 +43,8 @@ void ConfigureDebug::SetConfiguration() { | |||
| 43 | ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue()); | 43 | ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue()); |
| 44 | ui->enable_graphics_debugging->setEnabled(runtime_lock); | 44 | ui->enable_graphics_debugging->setEnabled(runtime_lock); |
| 45 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); | 45 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); |
| 46 | ui->enable_shader_feedback->setEnabled(runtime_lock); | ||
| 47 | ui->enable_shader_feedback->setChecked(Settings::values.renderer_shader_feedback.GetValue()); | ||
| 46 | ui->enable_cpu_debugging->setEnabled(runtime_lock); | 48 | ui->enable_cpu_debugging->setEnabled(runtime_lock); |
| 47 | ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue()); | 49 | ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue()); |
| 48 | ui->enable_nsight_aftermath->setEnabled(runtime_lock); | 50 | ui->enable_nsight_aftermath->setEnabled(runtime_lock); |
| @@ -65,6 +67,7 @@ void ConfigureDebug::ApplyConfiguration() { | |||
| 65 | Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); | 67 | Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); |
| 66 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); | 68 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); |
| 67 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); | 69 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); |
| 70 | Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked(); | ||
| 68 | Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); | 71 | Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); |
| 69 | Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked(); | 72 | Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked(); |
| 70 | Settings::values.disable_shader_loop_safety_checks = | 73 | Settings::values.disable_shader_loop_safety_checks = |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index c8baf2921..3fe9ff7de 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -111,8 +111,8 @@ | |||
| 111 | <property name="title"> | 111 | <property name="title"> |
| 112 | <string>Graphics</string> | 112 | <string>Graphics</string> |
| 113 | </property> | 113 | </property> |
| 114 | <layout class="QVBoxLayout" name="verticalLayout_6"> | 114 | <layout class="QGridLayout" name="gridLayout_3"> |
| 115 | <item> | 115 | <item row="0" column="0"> |
| 116 | <widget class="QCheckBox" name="enable_graphics_debugging"> | 116 | <widget class="QCheckBox" name="enable_graphics_debugging"> |
| 117 | <property name="enabled"> | 117 | <property name="enabled"> |
| 118 | <bool>true</bool> | 118 | <bool>true</bool> |
| @@ -125,7 +125,7 @@ | |||
| 125 | </property> | 125 | </property> |
| 126 | </widget> | 126 | </widget> |
| 127 | </item> | 127 | </item> |
| 128 | <item> | 128 | <item row="2" column="0"> |
| 129 | <widget class="QCheckBox" name="enable_nsight_aftermath"> | 129 | <widget class="QCheckBox" name="enable_nsight_aftermath"> |
| 130 | <property name="toolTip"> | 130 | <property name="toolTip"> |
| 131 | <string>When checked, it enables Nsight Aftermath crash dumps</string> | 131 | <string>When checked, it enables Nsight Aftermath crash dumps</string> |
| @@ -135,7 +135,7 @@ | |||
| 135 | </property> | 135 | </property> |
| 136 | </widget> | 136 | </widget> |
| 137 | </item> | 137 | </item> |
| 138 | <item> | 138 | <item row="0" column="1"> |
| 139 | <widget class="QCheckBox" name="disable_macro_jit"> | 139 | <widget class="QCheckBox" name="disable_macro_jit"> |
| 140 | <property name="enabled"> | 140 | <property name="enabled"> |
| 141 | <bool>true</bool> | 141 | <bool>true</bool> |
| @@ -148,7 +148,17 @@ | |||
| 148 | </property> | 148 | </property> |
| 149 | </widget> | 149 | </widget> |
| 150 | </item> | 150 | </item> |
| 151 | <item> | 151 | <item row="1" column="0"> |
| 152 | <widget class="QCheckBox" name="enable_shader_feedback"> | ||
| 153 | <property name="toolTip"> | ||
| 154 | <string>When checked, yuzu will log statistics about the compiled pipeline cache</string> | ||
| 155 | </property> | ||
| 156 | <property name="text"> | ||
| 157 | <string>Enable Shader Feedback</string> | ||
| 158 | </property> | ||
| 159 | </widget> | ||
| 160 | </item> | ||
| 161 | <item row="1" column="1"> | ||
| 152 | <widget class="QCheckBox" name="disable_loop_safety_checks"> | 162 | <widget class="QCheckBox" name="disable_loop_safety_checks"> |
| 153 | <property name="toolTip"> | 163 | <property name="toolTip"> |
| 154 | <string>When checked, it executes shaders without loop logic changes</string> | 164 | <string>When checked, it executes shaders without loop logic changes</string> |
| @@ -276,11 +286,14 @@ | |||
| 276 | <tabstop>open_log_button</tabstop> | 286 | <tabstop>open_log_button</tabstop> |
| 277 | <tabstop>homebrew_args_edit</tabstop> | 287 | <tabstop>homebrew_args_edit</tabstop> |
| 278 | <tabstop>enable_graphics_debugging</tabstop> | 288 | <tabstop>enable_graphics_debugging</tabstop> |
| 289 | <tabstop>enable_shader_feedback</tabstop> | ||
| 279 | <tabstop>enable_nsight_aftermath</tabstop> | 290 | <tabstop>enable_nsight_aftermath</tabstop> |
| 280 | <tabstop>disable_macro_jit</tabstop> | 291 | <tabstop>disable_macro_jit</tabstop> |
| 281 | <tabstop>disable_loop_safety_checks</tabstop> | 292 | <tabstop>disable_loop_safety_checks</tabstop> |
| 293 | <tabstop>fs_access_log</tabstop> | ||
| 282 | <tabstop>reporting_services</tabstop> | 294 | <tabstop>reporting_services</tabstop> |
| 283 | <tabstop>quest_flag</tabstop> | 295 | <tabstop>quest_flag</tabstop> |
| 296 | <tabstop>enable_cpu_debugging</tabstop> | ||
| 284 | <tabstop>use_debug_asserts</tabstop> | 297 | <tabstop>use_debug_asserts</tabstop> |
| 285 | <tabstop>use_auto_stub</tabstop> | 298 | <tabstop>use_auto_stub</tabstop> |
| 286 | </tabstops> | 299 | </tabstops> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 5af1ee6a8..064ecaafa 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -444,6 +444,7 @@ void Config::ReadValues() { | |||
| 444 | // Renderer | 444 | // Renderer |
| 445 | ReadSetting("Renderer", Settings::values.renderer_backend); | 445 | ReadSetting("Renderer", Settings::values.renderer_backend); |
| 446 | ReadSetting("Renderer", Settings::values.renderer_debug); | 446 | ReadSetting("Renderer", Settings::values.renderer_debug); |
| 447 | ReadSetting("Renderer", Settings::values.renderer_shader_feedback); | ||
| 447 | ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); | 448 | ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); |
| 448 | ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); | 449 | ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); |
| 449 | ReadSetting("Renderer", Settings::values.vulkan_device); | 450 | ReadSetting("Renderer", Settings::values.vulkan_device); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 17123304d..e02eceb99 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -221,6 +221,10 @@ backend = | |||
| 221 | # 0 (default): Disabled, 1: Enabled | 221 | # 0 (default): Disabled, 1: Enabled |
| 222 | debug = | 222 | debug = |
| 223 | 223 | ||
| 224 | # Enable shader feedback. | ||
| 225 | # 0 (default): Disabled, 1: Enabled | ||
| 226 | renderer_shader_feedback = | ||
| 227 | |||
| 224 | # Enable Nsight Aftermath crash dumps | 228 | # Enable Nsight Aftermath crash dumps |
| 225 | # 0 (default): Disabled, 1: Enabled | 229 | # 0 (default): Disabled, 1: Enabled |
| 226 | nsight_aftermath = | 230 | nsight_aftermath = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index ea3e0ada4..f643a4b0b 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -16,8 +16,8 @@ | |||
| 16 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 16 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 17 | #include "yuzu_cmd/yuzu_icon.h" | 17 | #include "yuzu_cmd/yuzu_icon.h" |
| 18 | 18 | ||
| 19 | EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_) | 19 | EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) |
| 20 | : input_subsystem{input_subsystem_} { | 20 | : input_subsystem{input_subsystem_}, system{system_} { |
| 21 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { | 21 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { |
| 22 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | 22 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); |
| 23 | exit(1); | 23 | exit(1); |
| @@ -218,7 +218,7 @@ void EmuWindow_SDL2::WaitEvent() { | |||
| 218 | 218 | ||
| 219 | const u32 current_time = SDL_GetTicks(); | 219 | const u32 current_time = SDL_GetTicks(); |
| 220 | if (current_time > last_time + 2000) { | 220 | if (current_time > last_time + 2000) { |
| 221 | const auto results = Core::System::GetInstance().GetAndResetPerfStats(); | 221 | const auto results = system.GetAndResetPerfStats(); |
| 222 | const auto title = | 222 | const auto title = |
| 223 | fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, | 223 | fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, |
| 224 | Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, | 224 | Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 1b9ab5b93..aa0d52ae4 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h | |||
| @@ -24,7 +24,7 @@ enum class MouseButton; | |||
| 24 | 24 | ||
| 25 | class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { | 25 | class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { |
| 26 | public: | 26 | public: |
| 27 | explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem); | 27 | explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem, Core::System& system_); |
| 28 | ~EmuWindow_SDL2(); | 28 | ~EmuWindow_SDL2(); |
| 29 | 29 | ||
| 30 | /// Whether the window is still open, and a close request hasn't yet been sent | 30 | /// Whether the window is still open, and a close request hasn't yet been sent |
| @@ -87,4 +87,7 @@ protected: | |||
| 87 | 87 | ||
| 88 | /// Input subsystem to use with this window. | 88 | /// Input subsystem to use with this window. |
| 89 | InputCommon::InputSubsystem* input_subsystem; | 89 | InputCommon::InputSubsystem* input_subsystem; |
| 90 | |||
| 91 | /// yuzu core instance | ||
| 92 | Core::System& system; | ||
| 90 | }; | 93 | }; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index eadb41790..5b98c255b 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | |||
| @@ -76,8 +76,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { | |||
| 76 | return unsupported_ext.empty(); | 76 | return unsupported_ext.empty(); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen) | 79 | EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, |
| 80 | : EmuWindow_SDL2{input_subsystem} { | 80 | Core::System& system_, bool fullscreen) |
| 81 | : EmuWindow_SDL2{input_subsystem, system_} { | ||
| 81 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); | 82 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); |
| 82 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); | 83 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); |
| 83 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); | 84 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h index 9e694d985..d7f2c83d8 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h | |||
| @@ -8,13 +8,18 @@ | |||
| 8 | #include "core/frontend/emu_window.h" | 8 | #include "core/frontend/emu_window.h" |
| 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 10 | 10 | ||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 11 | namespace InputCommon { | 15 | namespace InputCommon { |
| 12 | class InputSubsystem; | 16 | class InputSubsystem; |
| 13 | } | 17 | } |
| 14 | 18 | ||
| 15 | class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { | 19 | class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { |
| 16 | public: | 20 | public: |
| 17 | explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen); | 21 | explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, Core::System& system_, |
| 22 | bool fullscreen); | ||
| 18 | ~EmuWindow_SDL2_GL(); | 23 | ~EmuWindow_SDL2_GL(); |
| 19 | 24 | ||
| 20 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; | 25 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index d1473dbab..cdda375d8 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -24,8 +24,9 @@ | |||
| 24 | #include <SDL.h> | 24 | #include <SDL.h> |
| 25 | #include <SDL_syswm.h> | 25 | #include <SDL_syswm.h> |
| 26 | 26 | ||
| 27 | EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, bool fullscreen) | 27 | EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, |
| 28 | : EmuWindow_SDL2{input_subsystem} { | 28 | Core::System& system_, bool fullscreen) |
| 29 | : EmuWindow_SDL2{input_subsystem, system_} { | ||
| 29 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, | 30 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, |
| 30 | Common::g_scm_branch, Common::g_scm_desc); | 31 | Common::g_scm_branch, Common::g_scm_desc); |
| 31 | render_window = | 32 | render_window = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h index de53844f0..3ea521b2a 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h | |||
| @@ -19,7 +19,8 @@ class InputSubsystem; | |||
| 19 | 19 | ||
| 20 | class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { | 20 | class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { |
| 21 | public: | 21 | public: |
| 22 | explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, bool fullscreen); | 22 | explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, Core::System& system, |
| 23 | bool fullscreen); | ||
| 23 | ~EmuWindow_SDL2_VK() override; | 24 | ~EmuWindow_SDL2_VK() override; |
| 24 | 25 | ||
| 25 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; | 26 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 35ce23696..c10093820 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -172,10 +172,10 @@ int main(int argc, char** argv) { | |||
| 172 | std::unique_ptr<EmuWindow_SDL2> emu_window; | 172 | std::unique_ptr<EmuWindow_SDL2> emu_window; |
| 173 | switch (Settings::values.renderer_backend.GetValue()) { | 173 | switch (Settings::values.renderer_backend.GetValue()) { |
| 174 | case Settings::RendererBackend::OpenGL: | 174 | case Settings::RendererBackend::OpenGL: |
| 175 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(&input_subsystem, fullscreen); | 175 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(&input_subsystem, system, fullscreen); |
| 176 | break; | 176 | break; |
| 177 | case Settings::RendererBackend::Vulkan: | 177 | case Settings::RendererBackend::Vulkan: |
| 178 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem, fullscreen); | 178 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem, system, fullscreen); |
| 179 | break; | 179 | break; |
| 180 | } | 180 | } |
| 181 | 181 | ||