Browse Source
renderer_vulkan: Add setting to log pipeline statistics
renderer_vulkan: Add setting to log pipeline statistics
Use VK_KHR_pipeline_executable_properties when enabled and available to log statistics about the pipeline cache in a game. For example, this is on Turing GPUs when generating a pipeline cache from Super Smash Bros. Ultimate: Average pipeline statistics ========================================== Code size: 6433.167 Register count: 32.939 More advanced results could be presented, at the moment it's just an average of all 3D and compute pipelines.nce_cpp
19 changed files with 307 additions and 24 deletions
-
1src/common/settings.h
-
2src/video_core/CMakeLists.txt
-
100src/video_core/renderer_vulkan/pipeline_statistics.cpp
-
40src/video_core/renderer_vulkan/pipeline_statistics.h
-
13src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
-
2src/video_core/renderer_vulkan/vk_compute_pipeline.h
-
16src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
-
6src/video_core/renderer_vulkan/vk_graphics_pipeline.h
-
30src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
-
7src/video_core/renderer_vulkan/vk_pipeline_cache.h
-
29src/video_core/vulkan_common/vulkan_device.cpp
-
6src/video_core/vulkan_common/vulkan_device.h
-
38src/video_core/vulkan_common/vulkan_wrapper.cpp
-
8src/video_core/vulkan_common/vulkan_wrapper.h
-
2src/yuzu/configuration/config.cpp
-
3src/yuzu/configuration/configure_debug.cpp
-
23src/yuzu/configuration/configure_debug.ui
-
1src/yuzu_cmd/config.cpp
-
4src/yuzu_cmd/default_ini.h
@ -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
|
||||
@ -0,0 +1,40 @@ |
|||||
|
// Copyright 2021 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <mutex> |
||||
|
#include <vector> |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
class Device; |
||||
|
|
||||
|
class PipelineStatistics { |
||||
|
public: |
||||
|
explicit PipelineStatistics(const Device& device_); |
||||
|
|
||||
|
void Collect(VkPipeline pipeline); |
||||
|
|
||||
|
void Report() const; |
||||
|
|
||||
|
private: |
||||
|
struct Stats { |
||||
|
u64 code_size{}; |
||||
|
u64 register_count{}; |
||||
|
u64 sgpr_count{}; |
||||
|
u64 vgpr_count{}; |
||||
|
u64 branches_count{}; |
||||
|
u64 basic_block_count{}; |
||||
|
}; |
||||
|
|
||||
|
const Device& device; |
||||
|
mutable std::mutex mutex; |
||||
|
std::vector<Stats> collected_stats; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Vulkan |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue