mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-29 23:06:23 -05:00
renderer_vulkan: Query device names from the backend
This commit is contained in:
parent
7104e01bb3
commit
bc1b4b85b0
4 changed files with 79 additions and 35 deletions
|
@ -39,6 +39,7 @@ using UniqueFence = UniqueHandle<vk::Fence>;
|
||||||
using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>;
|
using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>;
|
||||||
using UniqueImage = UniqueHandle<vk::Image>;
|
using UniqueImage = UniqueHandle<vk::Image>;
|
||||||
using UniqueImageView = UniqueHandle<vk::ImageView>;
|
using UniqueImageView = UniqueHandle<vk::ImageView>;
|
||||||
|
using UniqueInstance = UniqueHandle<vk::Instance>;
|
||||||
using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>;
|
using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>;
|
||||||
using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>;
|
using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>;
|
||||||
using UniquePipeline = UniqueHandle<vk::Pipeline>;
|
using UniquePipeline = UniqueHandle<vk::Pipeline>;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/dynamic_library.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/telemetry.h"
|
#include "common/telemetry.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
@ -53,6 +54,45 @@ VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity_,
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common::DynamicLibrary OpenVulkanLibrary() {
|
||||||
|
Common::DynamicLibrary library;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// Check if a path to a specific Vulkan library has been specified.
|
||||||
|
char* libvulkan_env = getenv("LIBVULKAN_PATH");
|
||||||
|
if (!libvulkan_env || !library.Open(libvulkan_env)) {
|
||||||
|
// Use the libvulkan.dylib from the application bundle.
|
||||||
|
std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib";
|
||||||
|
library.Open(filename.c_str());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1);
|
||||||
|
if (!library.Open(filename.c_str())) {
|
||||||
|
// Android devices may not have libvulkan.so.1, only libvulkan.so.
|
||||||
|
filename = Common::DynamicLibrary::GetVersionedFilename("vulkan");
|
||||||
|
library.Open(filename.c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return library;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqueInstance CreateInstance(Common::DynamicLibrary& library, vk::DispatchLoaderDynamic& dld) {
|
||||||
|
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
|
||||||
|
if (!library.GetSymbol("vkGetInstanceProcAddr", &vkGetInstanceProcAddr)) {
|
||||||
|
return UniqueInstance{};
|
||||||
|
}
|
||||||
|
dld.init(vkGetInstanceProcAddr);
|
||||||
|
|
||||||
|
const vk::ApplicationInfo application_info("yuzu", VK_MAKE_VERSION(0, 1, 0), "yuzu",
|
||||||
|
VK_MAKE_VERSION(0, 1, 0), VK_API_VERSION_1_1);
|
||||||
|
const vk::InstanceCreateInfo instance_ci({}, &application_info, 0, nullptr, 0, nullptr);
|
||||||
|
vk::Instance unsafe_instance;
|
||||||
|
if (vk::createInstance(&instance_ci, nullptr, &unsafe_instance, dld) != vk::Result::eSuccess) {
|
||||||
|
return UniqueInstance{};
|
||||||
|
}
|
||||||
|
dld.init(unsafe_instance, vkGetInstanceProcAddr);
|
||||||
|
return UniqueInstance(unsafe_instance, {nullptr, dld});
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetReadableVersion(u32 version) {
|
std::string GetReadableVersion(u32 version) {
|
||||||
return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
|
return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
|
||||||
VK_VERSION_PATCH(version));
|
VK_VERSION_PATCH(version));
|
||||||
|
@ -276,4 +316,33 @@ void RendererVulkan::Report() const {
|
||||||
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> RendererVulkan::EnumerateDevices() {
|
||||||
|
Common::DynamicLibrary library = OpenVulkanLibrary();
|
||||||
|
if (!library.IsOpen()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
vk::DispatchLoaderDynamic dld;
|
||||||
|
UniqueInstance instance = CreateInstance(library, dld);
|
||||||
|
if (!instance) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 num_devices;
|
||||||
|
if (instance->enumeratePhysicalDevices(&num_devices, nullptr, dld) != vk::Result::eSuccess) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<vk::PhysicalDevice> devices(num_devices);
|
||||||
|
if (instance->enumeratePhysicalDevices(&num_devices, devices.data(), dld) !=
|
||||||
|
vk::Result::eSuccess) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> names;
|
||||||
|
names.reserve(num_devices);
|
||||||
|
for (auto& device : devices) {
|
||||||
|
names.push_back(device.getProperties(dld).deviceName);
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
@ -44,6 +45,8 @@ public:
|
||||||
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
||||||
bool TryPresent(int timeout_ms) override;
|
bool TryPresent(int timeout_ms) override;
|
||||||
|
|
||||||
|
static std::vector<std::string> EnumerateDevices();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
|
std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
|
||||||
const vk::DispatchLoaderDynamic& dldi);
|
const vk::DispatchLoaderDynamic& dldi);
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "ui_configure_graphics.h"
|
#include "ui_configure_graphics.h"
|
||||||
#include "yuzu/configuration/configure_graphics.h"
|
#include "yuzu/configuration/configure_graphics.h"
|
||||||
|
#ifdef HAS_VULKAN
|
||||||
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
enum class Resolution : int {
|
enum class Resolution : int {
|
||||||
|
@ -165,41 +168,9 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
|
||||||
|
|
||||||
void ConfigureGraphics::RetrieveVulkanDevices() {
|
void ConfigureGraphics::RetrieveVulkanDevices() {
|
||||||
#ifdef HAS_VULKAN
|
#ifdef HAS_VULKAN
|
||||||
QVulkanInstance instance;
|
vulkan_devices.clear();
|
||||||
instance.setApiVersion(QVersionNumber(1, 1, 0));
|
for (auto& name : Vulkan::RendererVulkan::EnumerateDevices()) {
|
||||||
if (!instance.create()) {
|
vulkan_devices.push_back(QString::fromStdString(name));
|
||||||
LOG_INFO(Frontend, "Vulkan 1.1 not available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto vkEnumeratePhysicalDevices{reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
|
|
||||||
instance.getInstanceProcAddr("vkEnumeratePhysicalDevices"))};
|
|
||||||
if (vkEnumeratePhysicalDevices == nullptr) {
|
|
||||||
LOG_INFO(Frontend, "Failed to get pointer to vkEnumeratePhysicalDevices");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
u32 physical_device_count;
|
|
||||||
if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count, nullptr) !=
|
|
||||||
VK_SUCCESS) {
|
|
||||||
LOG_INFO(Frontend, "Failed to get physical devices count");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::vector<VkPhysicalDevice> physical_devices(physical_device_count);
|
|
||||||
if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count,
|
|
||||||
physical_devices.data()) != VK_SUCCESS) {
|
|
||||||
LOG_INFO(Frontend, "Failed to get physical devices");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto vkGetPhysicalDeviceProperties{reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
|
|
||||||
instance.getInstanceProcAddr("vkGetPhysicalDeviceProperties"))};
|
|
||||||
if (vkGetPhysicalDeviceProperties == nullptr) {
|
|
||||||
LOG_INFO(Frontend, "Failed to get pointer to vkGetPhysicalDeviceProperties");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const auto physical_device : physical_devices) {
|
|
||||||
VkPhysicalDeviceProperties properties;
|
|
||||||
vkGetPhysicalDeviceProperties(physical_device, &properties);
|
|
||||||
vulkan_devices.push_back(QString::fromUtf8(properties.deviceName));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue