From 40ba5226c6e1f01334d8bbd3ba3b194c98007b19 Mon Sep 17 00:00:00 2001
From: GPUCode <47210458+GPUCode@users.noreply.github.com>
Date: Thu, 12 Oct 2023 01:11:43 +0300
Subject: [PATCH] vk_instance: Perform vulkan logging as early as possible
 (#7058)

---
 .../renderer_vulkan/renderer_vulkan.cpp       | 66 ++-----------------
 .../renderer_vulkan/renderer_vulkan.h         |  5 +-
 .../renderer_vulkan/vk_instance.cpp           | 53 +++++++++++++--
 src/video_core/renderer_vulkan/vk_instance.h  | 12 +++-
 4 files changed, 64 insertions(+), 72 deletions(-)

diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 51932a8b6..7c82b8bcc 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -11,7 +11,6 @@
 #include "core/hw/gpu.h"
 #include "core/hw/hw.h"
 #include "core/hw/lcd.h"
-#include "core/telemetry_session.h"
 #include "video_core/renderer_vulkan/renderer_vulkan.h"
 #include "video_core/renderer_vulkan/vk_shader_util.h"
 
@@ -26,9 +25,6 @@ MICROPROFILE_DEFINE(Vulkan_RenderFrame, "Vulkan", "Render Frame", MP_RGB(128, 12
 
 namespace Vulkan {
 
-/**
- * Vertex structure that the drawn screen rectangles are composed of.
- */
 struct ScreenRectVertex {
     ScreenRectVertex() = default;
     ScreenRectVertex(float x, float y, float u, float v)
@@ -49,46 +45,16 @@ constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(u32 width, u32 height) {
     // clang-format on
 }
 
-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);
-}
-
-constexpr std::array<vk::DescriptorSetLayoutBinding, 1> PRESENT_BINDINGS = {{
+constexpr static std::array<vk::DescriptorSetLayoutBinding, 1> PRESENT_BINDINGS = {{
     {0, vk::DescriptorType::eCombinedImageSampler, 3, vk::ShaderStageFlagBits::eFragment},
 }};
 
-} // Anonymous namespace
-
 RendererVulkan::RendererVulkan(Core::System& system, Frontend::EmuWindow& window,
                                Frontend::EmuWindow* secondary_window)
     : RendererBase{system, window, secondary_window}, memory{system.Memory()},
-      telemetry_session{system.TelemetrySession()},
-      instance{window, Settings::values.physical_device.GetValue()}, scheduler{instance,
-                                                                               renderpass_cache},
-      renderpass_cache{instance, scheduler}, pool{instance}, main_window{window, instance,
-                                                                         scheduler},
+      instance{system.TelemetrySession(), window, Settings::values.physical_device.GetValue()},
+      scheduler{instance, renderpass_cache}, renderpass_cache{instance, scheduler}, pool{instance},
+      main_window{window, instance, scheduler},
       vertex_buffer{instance, scheduler, vk::BufferUsageFlagBits::eVertexBuffer,
                     VERTEX_BUFFER_SIZE},
       rasterizer{memory,
@@ -101,7 +67,6 @@ RendererVulkan::RendererVulkan(Core::System& system, Frontend::EmuWindow& window
                  renderpass_cache,
                  main_window.ImageCount()},
       present_set_provider{instance, pool, PRESENT_BINDINGS} {
-    ReportDriver();
     CompileShaders();
     BuildLayouts();
     BuildPipelines();
@@ -1086,27 +1051,4 @@ void RendererVulkan::RenderScreenshot() {
     settings.screenshot_complete_callback();
 }
 
-void RendererVulkan::ReportDriver() 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 =
-        fmt::format("{}", fmt::join(instance.GetAvailableExtensions(), ", "));
-
-    LOG_INFO(Render_Vulkan, "VK_DRIVER: {}", driver_name);
-    LOG_INFO(Render_Vulkan, "VK_DEVICE: {}", model_name);
-    LOG_INFO(Render_Vulkan, "VK_VERSION: {}", 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 165e11e4c..103941a9e 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -21,8 +21,7 @@
 
 namespace Core {
 class System;
-class TelemetrySession;
-} // namespace Core
+}
 
 namespace Memory {
 class MemorySystem;
@@ -82,7 +81,6 @@ public:
     void Sync() override;
 
 private:
-    void ReportDriver() const;
     void ReloadPipeline();
     void CompileShaders();
     void BuildLayouts();
@@ -111,7 +109,6 @@ private:
 
 private:
     Memory::MemorySystem& memory;
-    Core::TelemetrySession& telemetry_session;
 
     Instance instance;
     Scheduler scheduler;
diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp
index 01debd898..f03ca3ba9 100644
--- a/src/video_core/renderer_vulkan/vk_instance.cpp
+++ b/src/video_core/renderer_vulkan/vk_instance.cpp
@@ -8,6 +8,7 @@
 #include "common/assert.h"
 #include "common/settings.h"
 #include "core/frontend/emu_window.h"
+#include "core/telemetry_session.h"
 #include "video_core/custom_textures/custom_format.h"
 #include "video_core/renderer_vulkan/vk_instance.h"
 #include "video_core/renderer_vulkan/vk_platform.h"
@@ -21,6 +22,7 @@
 namespace Vulkan {
 
 namespace {
+
 vk::Format MakeFormat(VideoCore::PixelFormat format) {
     switch (format) {
     case VideoCore::PixelFormat::RGBA8:
@@ -125,6 +127,12 @@ std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
     }
     return supported_extensions;
 }
+
+std::string GetReadableVersion(u32 version) {
+    return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
+                       VK_VERSION_PATCH(version));
+}
+
 } // Anonymous namespace
 
 Instance::Instance(bool enable_validation, bool dump_command_buffers)
@@ -133,7 +141,8 @@ Instance::Instance(bool enable_validation, bool dump_command_buffers)
                                                       enable_validation, dump_command_buffers)},
       physical_devices{instance->enumeratePhysicalDevices()} {}
 
-Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
+Instance::Instance(Core::TelemetrySession& telemetry, Frontend::EmuWindow& window,
+                   u32 physical_device_index)
     : library{OpenLibrary(&window)}, instance{CreateInstance(
                                          *library, window.GetWindowInfo().type,
                                          Settings::values.renderer_debug.GetValue(),
@@ -146,9 +155,10 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
                physical_device_index, num_physical_devices);
 
     physical_device = physical_devices[physical_device_index];
+    available_extensions = GetSupportedExtensions(physical_device);
     properties = physical_device.getProperties();
 
-    CollectTelemetryParameters();
+    CollectTelemetryParameters(telemetry);
     CreateDevice();
     CollectToolingInfo();
     CreateFormatTable();
@@ -180,6 +190,25 @@ const FormatTraits& Instance::GetTraits(Pica::PipelineRegs::VertexAttributeForma
     return attrib_table[index * 4 + count - 1];
 }
 
+std::string Instance::GetDriverVersionName() {
+    // Extracted from
+    // https://github.com/SaschaWillems/vulkan.gpuinfo.org/blob/5dddea46ea1120b0df14eef8f15ff8e318e35462/functions.php#L308-L314
+    const u32 version = properties.driverVersion;
+    if (driver_id == 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 (driver_id == vk::DriverId::eIntelProprietaryWindows) {
+        const u32 major = version >> 14;
+        const u32 minor = version & 0x3fff;
+        return fmt::format("{}.{}", major, minor);
+    }
+    return GetReadableVersion(version);
+}
+
 FormatTraits Instance::DetermineTraits(VideoCore::PixelFormat pixel_format, vk::Format format) {
     const vk::ImageAspectFlags format_aspect = MakeAspect(VideoCore::GetFormatType(pixel_format));
     const vk::FormatProperties format_properties = physical_device.getFormatProperties(format);
@@ -380,7 +409,6 @@ bool Instance::CreateDevice() {
                                        vk::PhysicalDevicePortabilitySubsetPropertiesKHR>();
 
     features = feature_chain.get().features;
-    available_extensions = GetSupportedExtensions(physical_device);
     if (available_extensions.empty()) {
         LOG_CRITICAL(Render_Vulkan, "No extensions supported by device.");
         return false;
@@ -598,7 +626,7 @@ void Instance::CreateAllocator() {
     }
 }
 
-void Instance::CollectTelemetryParameters() {
+void Instance::CollectTelemetryParameters(Core::TelemetrySession& telemetry) {
     const vk::StructureChain property_chain =
         physical_device
             .getProperties2<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceDriverProperties>();
@@ -607,6 +635,23 @@ void Instance::CollectTelemetryParameters() {
 
     driver_id = driver.driverID;
     vendor_name = driver.driverName.data();
+
+    const std::string model_name{GetModelName()};
+    const std::string driver_version = GetDriverVersionName();
+    const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
+    const std::string api_version = GetReadableVersion(properties.apiVersion);
+    const std::string extensions = fmt::format("{}", fmt::join(available_extensions, ", "));
+
+    LOG_INFO(Render_Vulkan, "VK_DRIVER: {}", driver_name);
+    LOG_INFO(Render_Vulkan, "VK_DEVICE: {}", model_name);
+    LOG_INFO(Render_Vulkan, "VK_VERSION: {}", api_version);
+
+    static constexpr auto field = Common::Telemetry::FieldType::UserSystem;
+    telemetry.AddField(field, "GPU_Vendor", vendor_name);
+    telemetry.AddField(field, "GPU_Model", model_name);
+    telemetry.AddField(field, "GPU_Vulkan_Driver", driver_name);
+    telemetry.AddField(field, "GPU_Vulkan_Version", api_version);
+    telemetry.AddField(field, "GPU_Vulkan_Extensions", extensions);
 }
 
 void Instance::CollectToolingInfo() {
diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h
index 4d7d7f55e..07cface6f 100644
--- a/src/video_core/renderer_vulkan/vk_instance.h
+++ b/src/video_core/renderer_vulkan/vk_instance.h
@@ -10,6 +10,10 @@
 #include "video_core/regs_pipeline.h"
 #include "video_core/renderer_vulkan/vk_platform.h"
 
+namespace Core {
+class TelemetrySession;
+}
+
 namespace Frontend {
 class EmuWindow;
 }
@@ -37,7 +41,8 @@ struct FormatTraits {
 class Instance {
 public:
     explicit Instance(bool validation = false, bool dump_command_buffers = false);
-    explicit Instance(Frontend::EmuWindow& window, u32 physical_device_index);
+    explicit Instance(Core::TelemetrySession& telemetry, Frontend::EmuWindow& window,
+                      u32 physical_device_index);
     ~Instance();
 
     /// Returns the FormatTraits struct for the provided pixel format
@@ -48,6 +53,9 @@ public:
     const FormatTraits& GetTraits(Pica::PipelineRegs::VertexAttributeFormat format,
                                   u32 count) const;
 
+    /// Returns a formatted string for the driver version
+    std::string GetDriverVersionName();
+
     /// Returns the Vulkan instance
     vk::Instance GetInstance() const {
         return *instance;
@@ -263,7 +271,7 @@ private:
     void CreateAllocator();
 
     /// Collects telemetry information from the device.
-    void CollectTelemetryParameters();
+    void CollectTelemetryParameters(Core::TelemetrySession& telemetry);
     void CollectToolingInfo();
 
     /// Sets MoltenVK configuration to the desired state.