From c8e9b465e224c2066bd7c65f790caafb79673218 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Sun, 20 Nov 2022 13:54:14 +0200 Subject: [PATCH] renderer_vulkan: Proper telemetry reporting --- src/core/hw/gpu.h | 2 +- .../renderer_vulkan/renderer_vulkan.cpp | 79 +++++++++++++++++-- .../renderer_vulkan/renderer_vulkan.h | 8 ++ .../renderer_vulkan/vk_instance.cpp | 47 ++++++++--- src/video_core/renderer_vulkan/vk_instance.h | 56 +++++++++++-- 5 files changed, 163 insertions(+), 29 deletions(-) diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index 49d487b4b..b865dcd6e 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h @@ -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 diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 65efe7647..407e72040 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -180,21 +180,61 @@ static std::array 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 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 diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index ff1938015..c4ec93852 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -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; diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 0a1ca3b2b..99897d618 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -42,6 +42,16 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) { } } +std::vector GetSupportedExtensions(vk::PhysicalDevice physical) { + const std::vector extensions = physical.enumerateDeviceExtensionProperties(); + std::vector 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 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(); + const vk::PhysicalDeviceDriverProperties driver = + property_chain.get(); + + driver_id = driver.driverID; + vendor_name = driver.driverName.data(); +} + } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 0959c06cb..12fe8fb9c 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -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& 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 physical_devices; std::array format_table; + std::vector available_extensions; u32 present_queue_family_index = 0; u32 graphics_queue_family_index = 0; bool timeline_semaphores = false;