renderer_vulkan: Proper telemetry reporting

This commit is contained in:
GPUCode
2022-11-20 13:54:14 +02:00
parent 278198f5f5
commit c8e9b465e2
5 changed files with 163 additions and 29 deletions

View File

@ -21,7 +21,7 @@ class MemorySystem;
namespace GPU {
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
constexpr u64 frame_ticks = /*4481136ull*/2240568ull;
constexpr u64 frame_ticks = 4481136ull;
// Refresh rate defined by ratio of ARM11 frequency to ARM11 ticks per frame
// (268,111,856) / (4,481,136) = 59.83122493939037Hz

View File

@ -180,21 +180,61 @@ static std::array<float, 3 * 2> MakeOrthographicMatrix(float width, float height
return matrix;
}
namespace {
std::string GetReadableVersion(u32 version) {
return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
VK_VERSION_PATCH(version));
}
std::string GetDriverVersion(const Instance& instance) {
// Extracted from
// https://github.com/SaschaWillems/vulkan.gpuinfo.org/blob/5dddea46ea1120b0df14eef8f15ff8e318e35462/functions.php#L308-L314
const u32 version = instance.GetDriverVersion();
if (instance.GetDriverID() == vk::DriverId::eNvidiaProprietary) {
const u32 major = (version >> 22) & 0x3ff;
const u32 minor = (version >> 14) & 0x0ff;
const u32 secondary = (version >> 6) & 0x0ff;
const u32 tertiary = version & 0x003f;
return fmt::format("{}.{}.{}.{}", major, minor, secondary, tertiary);
}
if (instance.GetDriverID() == vk::DriverId::eIntelProprietaryWindows) {
const u32 major = version >> 14;
const u32 minor = version & 0x3fff;
return fmt::format("{}.{}", major, minor);
}
return GetReadableVersion(version);
}
std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_extensions) {
std::sort(available_extensions.begin(), available_extensions.end());
static constexpr std::size_t AverageExtensionSize = 64;
std::string separated_extensions;
separated_extensions.reserve(available_extensions.size() * AverageExtensionSize);
const auto end = std::end(available_extensions);
for (auto extension = std::begin(available_extensions); extension != end; ++extension) {
if (const bool is_last = extension + 1 == end; is_last) {
separated_extensions += *extension;
} else {
separated_extensions += fmt::format("{},", *extension);
}
}
return separated_extensions;
}
} // Anonymous namespace
RendererVulkan::RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window)
: RendererBase{window, secondary_window}, instance{window, Settings::values.physical_device},
: RendererBase{window, secondary_window}, telemetry_session{Core::System::GetInstance().TelemetrySession()},
instance{window, Settings::values.physical_device},
scheduler{instance, renderpass_cache, *this},
renderpass_cache{instance, scheduler}, desc_manager{instance, scheduler},
runtime{instance, scheduler, renderpass_cache, desc_manager},
swapchain{instance, scheduler, renderpass_cache},
vertex_buffer{instance, scheduler, VERTEX_BUFFER_SIZE, vk::BufferUsageFlagBits::eVertexBuffer, {}},
rasterizer{render_window, instance, scheduler, desc_manager, runtime, renderpass_cache} {
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
constexpr auto user_system = Common::Telemetry::FieldType::UserSystem;
telemetry_session.AddField(user_system, "GPU_Vendor", "NVIDIA");
telemetry_session.AddField(user_system, "GPU_Model", "GTX 1650");
telemetry_session.AddField(user_system, "GPU_Vulkan_Version", "Vulkan 1.1");
Report();
window.mailbox = nullptr;
}
@ -983,4 +1023,27 @@ void RendererVulkan::FlushBuffers() {
runtime.FlushBuffers();
}
void RendererVulkan::Report() const {
const std::string vendor_name{instance.GetVendorName()};
const std::string model_name{instance.GetModelName()};
const std::string driver_version = GetDriverVersion(instance);
const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
const std::string api_version = GetReadableVersion(instance.ApiVersion());
const std::string extensions = BuildCommaSeparatedExtensions(instance.GetAvailableExtensions());
LOG_INFO(Render_Vulkan, "Driver: {}", driver_name);
LOG_INFO(Render_Vulkan, "Device: {}", model_name);
LOG_INFO(Render_Vulkan, "Vulkan: {}", api_version);
static constexpr auto field = Common::Telemetry::FieldType::UserSystem;
telemetry_session.AddField(field, "GPU_Vendor", vendor_name);
telemetry_session.AddField(field, "GPU_Model", model_name);
telemetry_session.AddField(field, "GPU_Vulkan_Driver", driver_name);
telemetry_session.AddField(field, "GPU_Vulkan_Version", api_version);
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
}
} // namespace Vulkan

View File

@ -17,6 +17,10 @@
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
namespace Core {
class TelemetrySession;
}
namespace Layout {
struct FramebufferLayout;
}
@ -102,7 +106,11 @@ private:
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
ScreenInfo& screen_info, bool right_eye);
void Report() const;
private:
Core::TelemetrySession& telemetry_session;
Instance instance;
Scheduler scheduler;
RenderpassCache renderpass_cache;

View File

@ -42,6 +42,16 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
}
}
std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
const std::vector extensions = physical.enumerateDeviceExtensionProperties();
std::vector<std::string> supported_extensions;
supported_extensions.reserve(extensions.size());
for (const auto& extension : extensions) {
supported_extensions.emplace_back(extension.extensionName.data());
}
return supported_extensions;
}
Instance::Instance(bool validation, bool dump_command_buffers) {
// Fetch instance independant function pointers
auto vkGetInstanceProcAddr =
@ -156,10 +166,10 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index) {
}
physical_device = physical_devices[physical_device_index];
device_properties = physical_device.getProperties();
properties = physical_device.getProperties();
LOG_INFO(Render_Vulkan, "Creating logical device for physical device: {}",
device_properties.deviceName);
properties.deviceName);
CreateDevice();
CreateFormatTable();
@ -261,7 +271,7 @@ void Instance::CreateFormatTable() {
}
bool Instance::CreateDevice() {
auto feature_chain =
const vk::StructureChain feature_chain =
physical_device.getFeatures2<vk::PhysicalDeviceFeatures2,
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT,
vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR,
@ -269,14 +279,14 @@ bool Instance::CreateDevice() {
// Not having geometry shaders will cause issues with accelerated rendering.
const vk::PhysicalDeviceFeatures available = feature_chain.get().features;
device_features = available;
features = available;
if (!available.geometryShader) {
LOG_WARNING(Render_Vulkan,
"Geometry shaders not availabe! Accelerated rendering not possible!");
}
auto extension_list = physical_device.enumerateDeviceExtensionProperties();
if (extension_list.empty()) {
available_extensions = GetSupportedExtensions(physical_device);
if (available_extensions.empty()) {
LOG_CRITICAL(Render_Vulkan, "No extensions supported by device.");
return false;
}
@ -285,18 +295,18 @@ bool Instance::CreateDevice() {
std::array<const char*, 10> enabled_extensions;
u32 enabled_extension_count = 0;
auto AddExtension = [&](std::string_view name) -> bool {
auto AddExtension = [&](std::string_view extension) -> bool {
auto result =
std::find_if(extension_list.begin(), extension_list.end(),
[&](const auto& prop) { return name.compare(prop.extensionName.data()) == 0; });
std::find_if(available_extensions.begin(), available_extensions.end(),
[&](const std::string& name) { return name == extension; });
if (result != extension_list.end()) {
LOG_INFO(Render_Vulkan, "Enabling extension: {}", name);
enabled_extensions[enabled_extension_count++] = name.data();
if (result != available_extensions.end()) {
LOG_INFO(Render_Vulkan, "Enabling extension: {}", extension);
enabled_extensions[enabled_extension_count++] = extension.data();
return true;
}
LOG_WARNING(Render_Vulkan, "Extension {} unavailable.", name);
LOG_WARNING(Render_Vulkan, "Extension {} unavailable.", extension);
return false;
};
@ -412,4 +422,15 @@ void Instance::CreateAllocator() {
}
}
void Instance::CollectTelemetryParameters() {
const vk::StructureChain property_chain =
physical_device.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceDriverProperties>();
const vk::PhysicalDeviceDriverProperties driver =
property_chain.get<vk::PhysicalDeviceDriverProperties>();
driver_id = driver.driverID;
vendor_name = driver.driverName.data();
}
} // namespace Vulkan

View File

@ -87,7 +87,7 @@ public:
/// Returns true if logic operations need shader emulation
bool NeedsLogicOpEmulation() const {
return !device_features.logicOp;
return !features.logicOp;
}
/// Returns true when VK_KHR_timeline_semaphore is supported
@ -112,22 +112,52 @@ public:
/// Returns the vendor ID of the physical device
u32 GetVendorID() const {
return device_properties.vendorID;
return properties.vendorID;
}
/// Returns the device ID of the physical device
u32 GetDeviceID() const {
return device_properties.deviceID;
return properties.deviceID;
}
/// Returns the driver ID.
vk::DriverId GetDriverID() const {
return driver_id;
}
/// Returns the current driver version provided in Vulkan-formatted version numbers.
u32 GetDriverVersion() const {
return properties.driverVersion;
}
/// Returns the current Vulkan API version provided in Vulkan-formatted version numbers.
u32 ApiVersion() const {
return properties.apiVersion;
}
/// Returns the vendor name reported from Vulkan.
std::string_view GetVendorName() const {
return vendor_name;
}
/// Returns the list of available extensions.
const std::vector<std::string>& GetAvailableExtensions() const {
return available_extensions;
}
/// Returns the device name.
std::string_view GetModelName() const {
return properties.deviceName;
}
/// Returns the pipeline cache unique identifier
const auto GetPipelineCacheUUID() const {
return device_properties.pipelineCacheUUID;
return properties.pipelineCacheUUID;
}
/// Returns the minimum required alignment for uniforms
vk::DeviceSize UniformMinAlignment() const {
return device_properties.limits.minUniformBufferOffsetAlignment;
return properties.limits.minUniformBufferOffsetAlignment;
}
private:
@ -143,19 +173,31 @@ private:
/// Creates the VMA allocator handle
void CreateAllocator();
/// Collects telemetry information from the device.
void CollectTelemetryParameters();
/// Collects information about attached tools.
void CollectToolingInfo();
/// Collects information about the device's local memory.
void CollectPhysicalMemoryInfo();
private:
static vk::DynamicLoader dl;
vk::Device device;
vk::PhysicalDevice physical_device;
vk::Instance instance;
vk::SurfaceKHR surface;
vk::PhysicalDeviceProperties device_properties;
vk::PhysicalDeviceFeatures device_features;
vk::PhysicalDeviceProperties properties;
vk::PhysicalDeviceFeatures features;
vk::DriverIdKHR driver_id;
std::string vendor_name;
VmaAllocator allocator;
vk::Queue present_queue;
vk::Queue graphics_queue;
std::vector<vk::PhysicalDevice> physical_devices;
std::array<FormatTraits, VideoCore::PIXEL_FORMAT_COUNT> format_table;
std::vector<std::string> available_extensions;
u32 present_queue_family_index = 0;
u32 graphics_queue_family_index = 0;
bool timeline_semaphores = false;