renderer_vulkan: Proper telemetry reporting
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user