summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan/pipeline_statistics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_vulkan/pipeline_statistics.cpp')
-rw-r--r--src/video_core/renderer_vulkan/pipeline_statistics.cpp100
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