diff --git a/src/display_settings.cpp b/src/display_settings.cpp index fd166334..8c91cccc 100644 --- a/src/display_settings.cpp +++ b/src/display_settings.cpp @@ -1,20 +1,37 @@ #include "display_settings.hpp" +#include "vulkan.hpp" #include #include #include #include #include +#ifndef __APPLE__ +#include +#endif +#include + +#ifdef __APPLE__ DisplaySettings::DisplaySettings(QWidget *parent) : +#else +DisplaySettings::DisplaySettings(QList &&vkDevices, QWidget *parent) : +#endif QWidget(parent), +#ifndef __APPLE__ + m_devices(nullptr), +#endif m_resolutions(nullptr), m_profile(nullptr) { auto layout = new QGridLayout(); +#ifdef __APPLE__ layout->addWidget(buildResolution(), 0, 0); - layout->setColumnStretch(1, 1); +#else + layout->addWidget(buildDevice(std::move(vkDevices)), 0, 0); + layout->addWidget(buildResolution(), 0, 1); +#endif layout->setRowStretch(1, 1); setLayout(layout); @@ -43,6 +60,30 @@ void DisplaySettings::setProfile(Profile *p) } } +#ifndef __APPLE__ +QWidget *DisplaySettings::buildDevice(QList &&vkDevices) +{ + // Setup group box. + auto group = new QGroupBox("Device"); + auto layout = new QVBoxLayout(); + + // Setup device list. + m_devices = new QComboBox(); + + for (auto dev : vkDevices) { + auto data = new DisplayDevice(dev); + + m_devices->addItem(data->name(), QVariant::fromValue(data)); + } + + layout->addWidget(m_devices); + + group->setLayout(layout); + + return group; +} +#endif + QWidget *DisplaySettings::buildResolution() { // Setup group box. @@ -67,3 +108,11 @@ QWidget *DisplaySettings::buildResolution() return group; } + +#ifndef __APPLE__ +DisplayDevice::DisplayDevice(VkPhysicalDevice handle) : + m_handle(handle) +{ + vkFunctions->vkGetPhysicalDeviceProperties(handle, &m_props); +} +#endif diff --git a/src/display_settings.hpp b/src/display_settings.hpp index a7c8792b..8e8256dc 100644 --- a/src/display_settings.hpp +++ b/src/display_settings.hpp @@ -2,19 +2,45 @@ #include "core.h" +#ifndef __APPLE__ +#include +#endif #include class QComboBox; class DisplaySettings final : public QWidget { public: +#ifdef __APPLE__ DisplaySettings(QWidget *parent = nullptr); +#else + DisplaySettings(QList &&vkDevices, QWidget *parent = nullptr); +#endif ~DisplaySettings() override; void setProfile(Profile *p); private: +#ifndef __APPLE__ + QWidget *buildDevice(QList &&vkDevices); +#endif QWidget *buildResolution(); +#ifndef __APPLE__ + QComboBox *m_devices; +#endif QComboBox *m_resolutions; Profile *m_profile; }; + +#ifndef __APPLE__ +class DisplayDevice : public QObject { + Q_OBJECT +public: + DisplayDevice(VkPhysicalDevice handle); + + const char *name() const { return m_props.deviceName; } +private: + VkPhysicalDevice m_handle; + VkPhysicalDeviceProperties m_props; +}; +#endif diff --git a/src/launch_settings.cpp b/src/launch_settings.cpp index 2804d35c..e7697c7a 100644 --- a/src/launch_settings.cpp +++ b/src/launch_settings.cpp @@ -18,7 +18,17 @@ #include #include +#include + +#ifdef __APPLE__ LaunchSettings::LaunchSettings(ProfileList *profiles, GameListModel *games, QWidget *parent) : +#else +LaunchSettings::LaunchSettings( + ProfileList *profiles, + GameListModel *games, + QList &&vkDevices, + QWidget *parent) : +#endif QWidget(parent), m_display(nullptr), m_games(nullptr), @@ -26,7 +36,11 @@ LaunchSettings::LaunchSettings(ProfileList *profiles, GameListModel *games, QWid { auto layout = new QVBoxLayout(); +#ifdef __APPLE__ layout->addWidget(buildSettings(games)); +#else + layout->addWidget(buildSettings(games, std::move(vkDevices))); +#endif layout->addLayout(buildActions(profiles)); setLayout(layout); @@ -36,13 +50,21 @@ LaunchSettings::~LaunchSettings() { } +#ifdef __APPLE__ QWidget *LaunchSettings::buildSettings(GameListModel *games) +#else +QWidget *LaunchSettings::buildSettings(GameListModel *games, QList &&vkDevices) +#endif { // Tab. auto tab = new QTabWidget(); // Display settings. +#ifdef __APPLE__ m_display = new DisplaySettings(); +#else + m_display = new DisplaySettings(std::move(vkDevices)); +#endif tab->addTab(m_display, loadIcon(":/resources/monitor.svg"), "Display"); diff --git a/src/launch_settings.hpp b/src/launch_settings.hpp index 02d17bbb..fceb466d 100644 --- a/src/launch_settings.hpp +++ b/src/launch_settings.hpp @@ -2,6 +2,10 @@ #include "core.h" +#include +#ifndef __APPLE__ +#include +#endif #include class DisplaySettings; @@ -14,13 +18,25 @@ class QTableView; class LaunchSettings final : public QWidget { Q_OBJECT public: +#ifdef __APPLE__ LaunchSettings(ProfileList *profiles, GameListModel *games, QWidget *parent = nullptr); +#else + LaunchSettings( + ProfileList *profiles, + GameListModel *games, + QList &&vkDevices, + QWidget *parent = nullptr); +#endif ~LaunchSettings() override; signals: void saveClicked(Profile *p); void startClicked(); private: +#ifdef __APPLE__ QWidget *buildSettings(GameListModel *games); +#else + QWidget *buildSettings(GameListModel *games, QList &&vkDevices); +#endif QLayout *buildActions(ProfileList *profiles); void requestGamesContextMenu(const QPoint &pos); diff --git a/src/main.cpp b/src/main.cpp index f4adf45d..c3ebb690 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,14 +7,18 @@ #endif #include +#include #include #include #include #ifndef __APPLE__ #include +#include #include #endif +#include + #ifndef _WIN32 #include #endif @@ -92,11 +96,69 @@ int main(int argc, char *argv[]) QMessageBox::critical( nullptr, "Error", - QString("Failed to initialize Vulkan (%1)").arg(vulkan.errorCode())); + QString("Failed to initialize Vulkan (%1).").arg(vulkan.errorCode())); return 1; } vkFunctions = vulkan.functions(); + + // List available devices. + QList vkDevices; + + for (;;) { + // Get device count. + uint32_t count; + auto result = vkFunctions->vkEnumeratePhysicalDevices(vulkan.vkInstance(), &count, nullptr); + + if (result != VK_SUCCESS) { + QMessageBox::critical( + nullptr, + "Error", + QString("Failed to get a number of Vulkan physical device (%1).").arg(result)); + return 1; + } else if (!count) { + QMessageBox::critical( + nullptr, + "Error", + "No any Vulkan physical device available."); + return 1; + } + + // Get devices. + vkDevices.resize(count); + + result = vkFunctions->vkEnumeratePhysicalDevices( + vulkan.vkInstance(), + &count, + vkDevices.data()); + + if (result == VK_INCOMPLETE) { + continue; + } else if (result != VK_SUCCESS) { + QMessageBox::critical( + nullptr, + "Error", + QString("Failed to list Vulkan physical devices (%1).").arg(result)); + return 1; + } + + break; + } + + // Filter out devices without Vulkan 1.3. + erase_if(vkDevices, [](VkPhysicalDevice dev) { + VkPhysicalDeviceProperties props; + vkFunctions->vkGetPhysicalDeviceProperties(dev, &props); + return props.apiVersion < VK_API_VERSION_1_3; + }); + + if (vkDevices.isEmpty()) { + QMessageBox::critical( + nullptr, + "Error", + "No any Vulkan device supports Vulkan 1.3."); + return 1; + } #endif // Check if no any required settings. @@ -112,7 +174,7 @@ int main(int argc, char *argv[]) #ifdef __APPLE__ MainWindow win; #else - MainWindow win(&vulkan); + MainWindow win(&vulkan, std::move(vkDevices)); #endif if (!win.loadProfiles() || !win.loadGames()) { diff --git a/src/main_window.cpp b/src/main_window.cpp index f39fdc5c..8f40c618 100644 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -27,9 +27,6 @@ #include #include #include -#ifndef __APPLE__ -#include -#endif #include #include @@ -40,7 +37,7 @@ #ifdef __APPLE__ MainWindow::MainWindow() : #else -MainWindow::MainWindow(QVulkanInstance *vulkan) : +MainWindow::MainWindow(QVulkanInstance *vulkan, QList &&vkDevices) : #endif m_main(nullptr), m_profiles(nullptr), @@ -101,7 +98,11 @@ MainWindow::MainWindow(QVulkanInstance *vulkan) : // Launch settings. m_profiles = new ProfileList(this); m_games = new GameListModel(this); +#ifdef __APPLE__ m_launch = new LaunchSettings(m_profiles, m_games); +#else + m_launch = new LaunchSettings(m_profiles, m_games, std::move(vkDevices)); +#endif connect(m_launch, &LaunchSettings::saveClicked, this, &MainWindow::saveProfile); connect(m_launch, &LaunchSettings::startClicked, this, &MainWindow::startKernel); diff --git a/src/main_window.hpp b/src/main_window.hpp index 010e6dcb..2211db9f 100644 --- a/src/main_window.hpp +++ b/src/main_window.hpp @@ -2,17 +2,18 @@ #include "core.hpp" +#include #include #include +#ifndef __APPLE__ +#include +#endif class GameListModel; class LaunchSettings; class LogsViewer; class ProfileList; class QStackedWidget; -#ifndef __APPLE__ -class QVulkanInstance; -#endif class Screen; class MainWindow final : public QMainWindow { @@ -20,7 +21,7 @@ class MainWindow final : public QMainWindow { #ifdef __APPLE__ MainWindow(); #else - MainWindow(QVulkanInstance *vulkan); + MainWindow(QVulkanInstance *vulkan, QList &&vkDevices); #endif ~MainWindow() override;