mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-10 11:11:40 +00:00
feat(bindless): Implement backend changes in lsfg-vk-ui
This commit is contained in:
parent
cee1b7b714
commit
fd0746c049
6 changed files with 103 additions and 58 deletions
|
|
@ -25,3 +25,5 @@ Checks:
|
|||
- -portability-avoid-pragma-once
|
||||
# Qt requires use of raw pointers in many places
|
||||
- -cppcoreguidelines-owning-memory
|
||||
# Qt seems to break some ranges algorithms in GCC
|
||||
- -modernize-use-ranges
|
||||
|
|
|
|||
|
|
@ -30,12 +30,11 @@ set_target_properties(lsfg-vk-ui PROPERTIES
|
|||
target_compile_options(lsfg-vk-ui PRIVATE # QT-codegen warnings
|
||||
-Wno-ctad-maybe-unsupported
|
||||
-Wno-unsafe-buffer-usage-in-libc-call
|
||||
-Wno-global-constructors
|
||||
-Wno-unsafe-buffer-usage)
|
||||
-Wno-unsafe-buffer-usage
|
||||
-Wno-global-constructors)
|
||||
|
||||
target_link_libraries(lsfg-vk-ui
|
||||
PRIVATE lsfg-vk-common
|
||||
PRIVATE lsfg-vk-backend
|
||||
PRIVATE Qt6::Quick)
|
||||
|
||||
install(TARGETS lsfg-vk-ui
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ using namespace lsfgvk;
|
|||
using namespace lsfgvk::ui;
|
||||
|
||||
Backend::Backend() {
|
||||
// load configuration
|
||||
// Load existing configuration
|
||||
ls::ConfigFile config{};
|
||||
|
||||
auto path = ls::findConfigurationFile();
|
||||
|
|
@ -27,7 +27,8 @@ Backend::Backend() {
|
|||
try {
|
||||
config = ls::ConfigFile(path);
|
||||
} catch (const std::exception&) {
|
||||
std::cerr << "the configuration file is invalid, it has been backed up to '.old'\n";
|
||||
std::cerr << "The existing configuration file is invalid, "
|
||||
<< "it has been backed up to '.old'\n";
|
||||
std::filesystem::rename(path, path.string() + ".old");
|
||||
}
|
||||
}
|
||||
|
|
@ -35,17 +36,17 @@ Backend::Backend() {
|
|||
this->m_global = config.global();
|
||||
this->m_profiles = config.profiles();
|
||||
|
||||
// create gpu list
|
||||
this->m_gpu_list = ui::getAvailableGPUs();
|
||||
// Create gpu list
|
||||
this->m_gpu_list = ui::queryGPUs();
|
||||
|
||||
// create profile list model
|
||||
// Create profile list model
|
||||
QStringList profiles;
|
||||
for (const auto& profile : this->m_profiles)
|
||||
profiles.append(QString::fromStdString(profile.name));
|
||||
|
||||
this->m_profile_list_model = new QStringListModel(profiles, this);
|
||||
|
||||
// create active_in list models
|
||||
// Create active_in list models
|
||||
this->m_active_in_list_models.reserve(this->m_profiles.size());
|
||||
for (const auto& profile : this->m_profiles) {
|
||||
QStringList active_in;
|
||||
|
|
@ -55,11 +56,11 @@ Backend::Backend() {
|
|||
this->m_active_in_list_models.push_back(new QStringListModel(active_in, this));
|
||||
}
|
||||
|
||||
// try to select first profile
|
||||
// Try to select first profile
|
||||
if (!this->m_profiles.empty())
|
||||
this->m_profile_index = 0;
|
||||
|
||||
// spawn saving thread
|
||||
// Spawn saving thread
|
||||
std::thread([this, path]() {
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
|
@ -74,10 +75,10 @@ Backend::Backend() {
|
|||
try {
|
||||
std::filesystem::create_directories(path.parent_path());
|
||||
if (!std::filesystem::exists(path.parent_path()))
|
||||
throw ls::error("unable to create configuration directory");
|
||||
throw ls::error("Unable to create configuration directory");
|
||||
config.write(path);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "unable to write configuration:\n- " << e.what() << "\n";
|
||||
std::cerr << "Unable to write configuration:\n- " << e.what() << "\n";
|
||||
}
|
||||
}
|
||||
}).detach();
|
||||
|
|
|
|||
|
|
@ -9,14 +9,18 @@
|
|||
#include "lsfg-vk-common/configuration/config.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define getters public
|
||||
#define setters public
|
||||
|
||||
namespace lsfgvk::ui {
|
||||
|
||||
/// Class tying ui and configuration together
|
||||
/// Class tying UI and Configuration together
|
||||
class Backend : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
|||
|
|
@ -5,63 +5,100 @@
|
|||
#include <QString>
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "lsfg-vk-backend/lsfgvk.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||
#define VULKAN_HPP_NO_DEFAULT_DISPATCHER 1
|
||||
#define VULKAN_HPP_NO_CONSTRUCTORS 1
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
using namespace lsfgvk;
|
||||
using namespace lsfgvk::ui;
|
||||
|
||||
QStringList ui::getAvailableGPUs() {
|
||||
// list of found GPUs and their optional PCI IDs
|
||||
std::vector<std::pair<std::string, std::optional<std::string>>> gpus{};
|
||||
QStringList ui::queryGPUs() {
|
||||
// Create a Vulkan instance
|
||||
vk::detail::DispatchLoaderDynamic dld;
|
||||
dld.init();
|
||||
|
||||
// create a backend to query all GPUs
|
||||
try {
|
||||
const backend::DevicePicker picker{[&gpus](
|
||||
const std::string& deviceName,
|
||||
std::pair<const std::string&, const std::string&>,
|
||||
const std::optional<std::string>& pci
|
||||
) {
|
||||
gpus.emplace_back(deviceName, pci);
|
||||
return false; // always fail
|
||||
}};
|
||||
const vk::ApplicationInfo appInfo{
|
||||
.pApplicationName = "lsfg-vk-ui",
|
||||
.applicationVersion = vk::makeVersion(2, 0, 0),
|
||||
.pEngineName = "lsfg-vk-ui",
|
||||
.engineVersion = vk::makeVersion(2, 0, 0),
|
||||
.apiVersion = vk::ApiVersion12 // Required by lsfg-vk anyways
|
||||
};
|
||||
const vk::InstanceCreateInfo instanceInfo{
|
||||
.pApplicationInfo = &appInfo
|
||||
};
|
||||
const vk::UniqueInstance instance{vk::createInstanceUnique(instanceInfo, nullptr, dld)};
|
||||
dld.init(*instance);
|
||||
|
||||
const backend::Instance instance{picker, "/non/existent/path", false};
|
||||
throw std::runtime_error("???");
|
||||
} catch (const backend::error&) { // NOLINT (empty catch)
|
||||
// expected
|
||||
// Query physical devices
|
||||
std::vector<std::string> devicesByName{};
|
||||
std::vector<std::string> devicesByBusId{};
|
||||
|
||||
for (const auto& physdev : instance->enumeratePhysicalDevices(dld)) {
|
||||
// Check for VK_EXT_pci_bus_info
|
||||
bool supportsPCIEXT{false};
|
||||
for (const auto& ext : physdev.enumerateDeviceExtensionProperties(nullptr, dld)) {
|
||||
if (std::string(ext.extensionName) != vk::EXTPciBusInfoExtensionName)
|
||||
continue;
|
||||
|
||||
supportsPCIEXT = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fetch properties
|
||||
vk::PhysicalDevicePCIBusInfoPropertiesEXT busInfo{};
|
||||
vk::PhysicalDeviceProperties2 info{
|
||||
.pNext = supportsPCIEXT ? &busInfo : nullptr
|
||||
};
|
||||
physdev.getProperties2(&info, dld);
|
||||
|
||||
auto& props{info.properties};
|
||||
|
||||
// Append device name
|
||||
props.deviceName.back() = '\0'; // Ensure null-termination
|
||||
devicesByName.emplace_back(props.deviceName);
|
||||
|
||||
// Append PCI bus ID
|
||||
if (!supportsPCIEXT)
|
||||
continue;
|
||||
|
||||
std::ostringstream pciss;
|
||||
pciss << std::hex << std::setfill('0')
|
||||
<< std::setw(4) << busInfo.pciDomain << ":"
|
||||
<< std::setw(2) << busInfo.pciBus << ":"
|
||||
<< std::setw(2) << busInfo.pciDevice << "."
|
||||
<< std::setw(1) << busInfo.pciFunction;
|
||||
devicesByBusId.emplace_back(pciss.str());
|
||||
}
|
||||
|
||||
// NOLINTBEGIN (ranges) [GCC has some issues with ranges]
|
||||
// first remove 1:1 duplicates
|
||||
std::sort(gpus.begin(), gpus.end());
|
||||
gpus.erase(std::unique(gpus.begin(), gpus.end()), gpus.end());
|
||||
// NOLINTEND
|
||||
// Count duplicate names
|
||||
std::unordered_map<std::string, size_t> repeats{};
|
||||
for (const auto& name : devicesByName)
|
||||
repeats[name]++;
|
||||
|
||||
// build the frontend list
|
||||
// Build the frontend list
|
||||
QStringList list{"Default"};
|
||||
for (const auto& gpu : gpus) {
|
||||
// check if GPU is in list more than once
|
||||
auto count = std::count_if(gpus.begin(), gpus.end(),
|
||||
[&gpu](const auto& other) {
|
||||
return other.first == gpu.first;
|
||||
}
|
||||
);
|
||||
for (size_t i = 0; i < devicesByName.size(); i++) {
|
||||
const auto& name{devicesByName.at(i)};
|
||||
|
||||
// add pci id to distinguish, otherwise add just the name
|
||||
// Decide whether to show PCI bus ID or device name
|
||||
QString entry;
|
||||
if (count > 1 && gpu.second.has_value())
|
||||
entry = QString::fromStdString(*gpu.second);
|
||||
if (repeats[name] > 1)
|
||||
entry = QString::fromStdString(devicesByBusId.at(i));
|
||||
else
|
||||
entry = QString::fromStdString(gpu.first);
|
||||
entry = QString::fromStdString(name);
|
||||
|
||||
// ensure no duplicates (flatpak does funny things)
|
||||
// Append to list if not already present (flatpak does funny things)
|
||||
if (list.contains(entry))
|
||||
continue;
|
||||
list.append(entry);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
namespace lsfgvk::ui {
|
||||
|
||||
/// get the list of available GPUs, automatically
|
||||
/// switching to PCI IDs if there are duplicates
|
||||
/// @return list of available GPUs
|
||||
QStringList getAvailableGPUs();
|
||||
///
|
||||
/// Query all GPUs available on the system.
|
||||
///
|
||||
/// @return List of available GPUs
|
||||
///
|
||||
QStringList queryGPUs();
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue