diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/renderer_vulkan/pipeline_statistics.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
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 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <string_view> + +#include <fmt/format.h> + +#include "common/common_types.h" +#include "common/logging/log.h" +#include "video_core/renderer_vulkan/pipeline_statistics.h" +#include "video_core/vulkan_common/vulkan_device.h" +#include "video_core/vulkan_common/vulkan_wrapper.h" + +namespace Vulkan { + +using namespace std::string_view_literals; + +static u64 GetUint64(const VkPipelineExecutableStatisticKHR& statistic) { + switch (statistic.format) { + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR: + return static_cast<u64>(statistic.value.i64); + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR: + return statistic.value.u64; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR: + return static_cast<u64>(statistic.value.f64); + default: + return 0; + } +} + +PipelineStatistics::PipelineStatistics(const Device& device_) : device{device_} {} + +void PipelineStatistics::Collect(VkPipeline pipeline) { + const auto& dev{device.GetLogical()}; + const std::vector properties{dev.GetPipelineExecutablePropertiesKHR(pipeline)}; + const u32 num_executables{static_cast<u32>(properties.size())}; + for (u32 executable = 0; executable < num_executables; ++executable) { + const auto statistics{dev.GetPipelineExecutableStatisticsKHR(pipeline, executable)}; + if (statistics.empty()) { + continue; + } + Stats stage_stats; + for (const auto& statistic : statistics) { + const char* const name{statistic.name}; + if (name == "Binary Size"sv || name == "Code size"sv || name == "Instruction Count"sv) { + stage_stats.code_size = GetUint64(statistic); + } else if (name == "Register Count"sv) { + stage_stats.register_count = GetUint64(statistic); + } else if (name == "SGPRs"sv || name == "numUsedSgprs"sv) { + stage_stats.sgpr_count = GetUint64(statistic); + } else if (name == "VGPRs"sv || name == "numUsedVgprs"sv) { + stage_stats.vgpr_count = GetUint64(statistic); + } else if (name == "Branches"sv) { + stage_stats.branches_count = GetUint64(statistic); + } else if (name == "Basic Block Count"sv) { + stage_stats.basic_block_count = GetUint64(statistic); + } + } + std::lock_guard lock{mutex}; + collected_stats.push_back(stage_stats); + } +} + +void PipelineStatistics::Report() const { + double num{}; + Stats total; + { + std::lock_guard lock{mutex}; + for (const Stats& stats : collected_stats) { + total.code_size += stats.code_size; + total.register_count += stats.register_count; + total.sgpr_count += stats.sgpr_count; + total.vgpr_count += stats.vgpr_count; + total.branches_count += stats.branches_count; + total.basic_block_count += stats.basic_block_count; + } + num = static_cast<double>(collected_stats.size()); + } + std::string report; + const auto add = [&](const char* fmt, u64 value) { + if (value > 0) { + report += fmt::format(fmt::runtime(fmt), static_cast<double>(value) / num); + } + }; + add("Code size: {:9.03f}\n", total.code_size); + add("Register count: {:9.03f}\n", total.register_count); + add("SGPRs: {:9.03f}\n", total.sgpr_count); + add("VGPRs: {:9.03f}\n", total.vgpr_count); + add("Branches count: {:9.03f}\n", total.branches_count); + add("Basic blocks: {:9.03f}\n", total.basic_block_count); + + LOG_INFO(Render_Vulkan, + "\nAverage pipeline statistics\n" + "==========================================\n" + "{}\n", + report); +} + +} // namespace Vulkan |