From 8ef225a37d1868f39a380f81a2b816d79622c2cf Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Fri, 12 Nov 2021 01:23:46 +0530 Subject: [PATCH] Introduce `QuirkManager` for runtime GPU quirk tracking We require a way to track certain host GPU features that are optional such as Vulkan extensions, this is what the `QuirkManager` class does as it checks for all quirks and holds them allowing other components to branch based off these quirks. --- app/CMakeLists.txt | 1 + app/src/main/cpp/skyline/gpu.cpp | 15 ++++----- app/src/main/cpp/skyline/gpu.h | 5 ++- .../main/cpp/skyline/gpu/memory_manager.cpp | 1 - .../main/cpp/skyline/gpu/quirk_manager.cpp | 31 +++++++++++++++++++ app/src/main/cpp/skyline/gpu/quirk_manager.h | 21 +++++++++++++ 6 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 app/src/main/cpp/skyline/gpu/quirk_manager.cpp create mode 100644 app/src/main/cpp/skyline/gpu/quirk_manager.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index d744ab3d..03d97dec 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -129,6 +129,7 @@ add_library(skyline SHARED ${source_DIR}/skyline/audio/resampler.cpp ${source_DIR}/skyline/audio/adpcm_decoder.cpp ${source_DIR}/skyline/gpu.cpp + ${source_DIR}/skyline/gpu/quirk_manager.cpp ${source_DIR}/skyline/gpu/memory_manager.cpp ${source_DIR}/skyline/gpu/texture_manager.cpp ${source_DIR}/skyline/gpu/command_scheduler.cpp diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 53a31b36..ed9d38bb 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -119,17 +119,18 @@ namespace skyline::gpu { return std::move(vk::raii::PhysicalDevices(instance).front()); // We just select the first device as we aren't expecting multiple GPUs } - vk::raii::Device GPU::CreateDevice(const vk::raii::PhysicalDevice &physicalDevice, typeof(vk::DeviceQueueCreateInfo::queueCount) &vkQueueFamilyIndex) { - auto properties{physicalDevice.getProperties()}; // We should check for required properties here, if/when we have them + vk::raii::Device GPU::CreateDevice(const vk::raii::PhysicalDevice &physicalDevice, typeof(vk::DeviceQueueCreateInfo::queueCount) &vkQueueFamilyIndex, QuirkManager& quirks) { + auto properties{physicalDevice.getProperties()}; + auto features{physicalDevice.getFeatures2()}; + auto extensions{physicalDevice.enumerateDeviceExtensionProperties()}; - // auto features{physicalDevice.getFeatures()}; // Same as above + quirks = QuirkManager(properties, features, extensions); constexpr std::array requiredDeviceExtensions{ VK_KHR_SWAPCHAIN_EXTENSION_NAME, }; - auto deviceExtensions{physicalDevice.enumerateDeviceExtensionProperties()}; for (const auto &requiredExtension : requiredDeviceExtensions) { - if (!std::any_of(deviceExtensions.begin(), deviceExtensions.end(), [&](const vk::ExtensionProperties &deviceExtension) { + if (!std::any_of(extensions.begin(), extensions.end(), [&](const vk::ExtensionProperties &deviceExtension) { return std::string_view(deviceExtension.extensionName) == std::string_view(requiredExtension); })) throw exception("Cannot find Vulkan device extension: \"{}\"", requiredExtension); @@ -155,7 +156,7 @@ namespace skyline::gpu { if (Logger::configLevel >= Logger::LogLevel::Info) { std::string extensionString; - for (const auto &extension : deviceExtensions) + for (const auto &extension : extensions) extensionString += util::Format("\n* {} (v{}.{}.{})", extension.extensionName, VK_VERSION_MAJOR(extension.specVersion), VK_VERSION_MINOR(extension.specVersion), VK_VERSION_PATCH(extension.specVersion)); std::string queueString; @@ -174,5 +175,5 @@ namespace skyline::gpu { }); } - GPU::GPU(const DeviceState &state) : vkInstance(CreateInstance(state, vkContext)), vkDebugReportCallback(CreateDebugReportCallback(vkInstance)), vkPhysicalDevice(CreatePhysicalDevice(vkInstance)), vkDevice(CreateDevice(vkPhysicalDevice, vkQueueFamilyIndex)), vkQueue(vkDevice, vkQueueFamilyIndex, 0), memory(*this), scheduler(*this), presentation(state, *this), texture(*this) {} + GPU::GPU(const DeviceState &state) : vkInstance(CreateInstance(state, vkContext)), vkDebugReportCallback(CreateDebugReportCallback(vkInstance)), vkPhysicalDevice(CreatePhysicalDevice(vkInstance)), vkDevice(CreateDevice(vkPhysicalDevice, vkQueueFamilyIndex, quirks)), vkQueue(vkDevice, vkQueueFamilyIndex, 0), memory(*this), scheduler(*this), presentation(state, *this), texture(*this) {} } diff --git a/app/src/main/cpp/skyline/gpu.h b/app/src/main/cpp/skyline/gpu.h index 06d45b43..38579672 100644 --- a/app/src/main/cpp/skyline/gpu.h +++ b/app/src/main/cpp/skyline/gpu.h @@ -3,6 +3,7 @@ #pragma once +#include "gpu/quirk_manager.h" #include "gpu/memory_manager.h" #include "gpu/command_scheduler.h" #include "gpu/presentation_engine.h" @@ -22,7 +23,7 @@ namespace skyline::gpu { static vk::raii::PhysicalDevice CreatePhysicalDevice(const vk::raii::Instance &instance); - static vk::raii::Device CreateDevice(const vk::raii::PhysicalDevice &physicalDevice, typeof(vk::DeviceQueueCreateInfo::queueCount)& queueConfiguration); + static vk::raii::Device CreateDevice(const vk::raii::PhysicalDevice &physicalDevice, typeof(vk::DeviceQueueCreateInfo::queueCount)& queueConfiguration, QuirkManager& quirks); public: static constexpr u32 VkApiVersion{VK_API_VERSION_1_1}; //!< The version of core Vulkan that we require @@ -36,6 +37,8 @@ namespace skyline::gpu { std::mutex queueMutex; //!< Synchronizes access to the queue as it is externally synchronized vk::raii::Queue vkQueue; //!< A Vulkan Queue supporting graphics and compute operations + QuirkManager quirks; + memory::MemoryManager memory; CommandScheduler scheduler; PresentationEngine presentation; diff --git a/app/src/main/cpp/skyline/gpu/memory_manager.cpp b/app/src/main/cpp/skyline/gpu/memory_manager.cpp index 46021d0a..40792d38 100644 --- a/app/src/main/cpp/skyline/gpu/memory_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/memory_manager.cpp @@ -68,7 +68,6 @@ namespace skyline::gpu::memory { .vulkanApiVersion = GPU::VkApiVersion, }; ThrowOnFail(vmaCreateAllocator(&allocatorCreateInfo, &vmaAllocator)); - // TODO: Use VK_KHR_dedicated_allocation when available (Should be on Adreno GPUs) } MemoryManager::~MemoryManager() { diff --git a/app/src/main/cpp/skyline/gpu/quirk_manager.cpp b/app/src/main/cpp/skyline/gpu/quirk_manager.cpp new file mode 100644 index 00000000..f19a4966 --- /dev/null +++ b/app/src/main/cpp/skyline/gpu/quirk_manager.cpp @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include "quirk_manager.h" + +namespace skyline { + QuirkManager::QuirkManager(vk::PhysicalDeviceProperties properties, vk::PhysicalDeviceFeatures2 features, const std::vector &extensions) { + for (auto &extension : extensions) { + #define EXT_SET(name, property) \ + case util::Hash(name): \ + if (name == extensionName) \ + property = true; \ + break + + #define EXT_SET_V(name, property, version) \ + case util::Hash(name): \ + if (name == extensionName && extensionVersion >= version) \ + property = true; \ + break + + std::string_view extensionName{extension.extensionName}; + auto extensionVersion{extension.specVersion}; + switch (util::Hash(extensionName)) { + EXT_SET("VK_EXT_provoking_vertex", supportsLastProvokingVertex); + } + + #undef EXT_SET + #undef EXT_SET_V + } + } +} diff --git a/app/src/main/cpp/skyline/gpu/quirk_manager.h b/app/src/main/cpp/skyline/gpu/quirk_manager.h new file mode 100644 index 00000000..d1133b1d --- /dev/null +++ b/app/src/main/cpp/skyline/gpu/quirk_manager.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include + +namespace skyline { + /** + * @brief Checks and stores all the quirks of the host GPU discovered at runtime + */ + class QuirkManager { + public: + bool supportsLastProvokingVertex{}; //!< If the device supports setting the last vertex as the provoking vertex (with VK_EXT_provoking_vertex) + + QuirkManager() = default; + + QuirkManager(vk::PhysicalDeviceProperties properties, vk::PhysicalDeviceFeatures2 features, const std::vector& extensions); + }; +}