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