Rename QuirkManager to TraitManager

Quirk terminology was deemed to be inappropriate for describing the features/extensions of a device. It has been replaced with traits which is far more fitting but quirks will be used as a terminology for errata in devices.
This commit is contained in:
PixelyIon 2022-01-22 20:15:28 +05:30
parent 0b2ce6a8f3
commit ddb2ba8a1b
7 changed files with 58 additions and 58 deletions

View File

@ -157,7 +157,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/trait_manager.cpp
${source_DIR}/skyline/gpu/memory_manager.cpp
${source_DIR}/skyline/gpu/texture_manager.cpp
${source_DIR}/skyline/gpu/buffer_manager.cpp

View File

@ -122,7 +122,7 @@ namespace skyline::gpu {
static vk::raii::Device CreateDevice(const vk::raii::Context &context,
const vk::raii::PhysicalDevice &physicalDevice,
decltype(vk::DeviceQueueCreateInfo::queueCount) &vkQueueFamilyIndex,
QuirkManager &quirks) {
TraitManager &traits) {
auto deviceFeatures2{physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, vk::PhysicalDeviceShaderFloat16Int8Features, vk::PhysicalDeviceShaderAtomicInt64Features, vk::PhysicalDeviceUniformBufferStandardLayoutFeatures>()};
decltype(deviceFeatures2) enabledFeatures2{}; // We only want to enable features we required due to potential overhead from unused features
@ -154,8 +154,8 @@ namespace skyline::gpu {
auto deviceProperties2{physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>()};
quirks = QuirkManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2);
quirks.ApplyDriverPatches(context);
traits = TraitManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2);
traits.ApplyDriverPatches(context);
std::vector<const char *> pEnabledExtensions;
pEnabledExtensions.reserve(enabledExtensions.size());
@ -191,11 +191,11 @@ namespace skyline::gpu {
queueString += util::Format("\n* {}x{}{}{}{}{}: TSB{} MIG({}x{}x{}){}", queueFamily.queueCount, queueFamily.queueFlags & vk::QueueFlagBits::eGraphics ? 'G' : '-', queueFamily.queueFlags & vk::QueueFlagBits::eCompute ? 'C' : '-', queueFamily.queueFlags & vk::QueueFlagBits::eTransfer ? 'T' : '-', queueFamily.queueFlags & vk::QueueFlagBits::eSparseBinding ? 'S' : '-', queueFamily.queueFlags & vk::QueueFlagBits::eProtected ? 'P' : '-', queueFamily.timestampValidBits, queueFamily.minImageTransferGranularity.width, queueFamily.minImageTransferGranularity.height, queueFamily.minImageTransferGranularity.depth, familyIndex++ == vkQueueFamilyIndex ? " <--" : "");
auto properties{deviceProperties2.get<vk::PhysicalDeviceProperties2>().properties};
Logger::Info("Vulkan Device:\nName: {}\nType: {}\nVulkan Version: {}.{}.{}\nDriver Version: {}.{}.{}\nQueues:{}\nExtensions:{}\nQuirks:{}",
Logger::Info("Vulkan Device:\nName: {}\nType: {}\nVulkan Version: {}.{}.{}\nDriver Version: {}.{}.{}\nQueues:{}\nExtensions:{}\nTraits:{}",
properties.deviceName, vk::to_string(properties.deviceType),
VK_API_VERSION_MAJOR(properties.apiVersion), VK_API_VERSION_MINOR(properties.apiVersion), VK_API_VERSION_PATCH(properties.apiVersion),
VK_API_VERSION_MAJOR(properties.driverVersion), VK_API_VERSION_MINOR(properties.driverVersion), VK_API_VERSION_PATCH(properties.driverVersion),
queueString, extensionString, quirks.Summary());
queueString, extensionString, traits.Summary());
}
return vk::raii::Device(physicalDevice, vk::DeviceCreateInfo{
@ -211,7 +211,7 @@ namespace skyline::gpu {
: vkInstance(CreateInstance(state, vkContext)),
vkDebugReportCallback(CreateDebugReportCallback(vkInstance)),
vkPhysicalDevice(CreatePhysicalDevice(vkInstance)),
vkDevice(CreateDevice(vkContext, vkPhysicalDevice, vkQueueFamilyIndex, quirks)),
vkDevice(CreateDevice(vkContext, vkPhysicalDevice, vkQueueFamilyIndex, traits)),
vkQueue(vkDevice, vkQueueFamilyIndex, 0),
memory(*this),
scheduler(*this),

View File

@ -3,7 +3,7 @@
#pragma once
#include "gpu/quirk_manager.h"
#include "gpu/trait_manager.h"
#include "gpu/memory_manager.h"
#include "gpu/command_scheduler.h"
#include "gpu/presentation_engine.h"
@ -25,7 +25,7 @@ namespace skyline::gpu {
vk::raii::DebugReportCallbackEXT vkDebugReportCallback; //!< An RAII Vulkan debug report manager which calls into 'GPU::DebugCallback'
vk::raii::PhysicalDevice vkPhysicalDevice;
u32 vkQueueFamilyIndex{};
QuirkManager quirks;
TraitManager traits;
vk::raii::Device vkDevice;
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

View File

@ -67,7 +67,7 @@ namespace skyline::gpu::interconnect {
for (auto &rtBlendState : independentRtBlendState)
rtBlendState.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
if (!gpu.quirks.supportsLastProvokingVertex)
if (!gpu.traits.supportsLastProvokingVertex)
rasterizerState.unlink<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>();
}
@ -1121,7 +1121,7 @@ namespace skyline::gpu::interconnect {
void SetProvokingVertex(bool isLast) {
if (isLast) {
if (!gpu.quirks.supportsLastProvokingVertex)
if (!gpu.traits.supportsLastProvokingVertex)
Logger::Warn("Cannot set provoking vertex to last without host GPU support");
rasterizerState.get<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>().provokingVertexMode = vk::ProvokingVertexModeEXT::eLastVertex;
} else {
@ -1167,7 +1167,7 @@ namespace skyline::gpu::interconnect {
public:
void SetBlendLogicOpEnable(bool enabled) {
if (!gpu.quirks.supportsLogicOp && enabled) {
if (!gpu.traits.supportsLogicOp && enabled) {
Logger::Warn("Cannot enable framebuffer logical operation without host GPU support");
return;
}
@ -1468,9 +1468,9 @@ namespace skyline::gpu::interconnect {
}
void SetVertexBufferDivisor(u32 index, u32 divisor) {
if (!gpu.quirks.supportsVertexAttributeDivisor)
if (!gpu.traits.supportsVertexAttributeDivisor)
Logger::Warn("Cannot set vertex attribute divisor without host GPU support");
else if (divisor == 0 && !gpu.quirks.supportsVertexAttributeZeroDivisor)
else if (divisor == 0 && !gpu.traits.supportsVertexAttributeZeroDivisor)
Logger::Warn("Cannot set vertex attribute divisor to zero without host GPU support");
vertexBuffers[index].bindingDivisorDescription.divisor = divisor;
}
@ -2007,7 +2007,7 @@ namespace skyline::gpu::interconnect {
auto convertAddressModeWithCheck{[&](TextureSamplerControl::AddressMode mode) {
auto vkMode{ConvertSamplerAddressMode(mode)};
if (vkMode == vk::SamplerAddressMode::eMirrorClampToEdge && !gpu.quirks.supportsSamplerMirrorClampToEdge) [[unlikely]] {
if (vkMode == vk::SamplerAddressMode::eMirrorClampToEdge && !gpu.traits.supportsSamplerMirrorClampToEdge) [[unlikely]] {
Logger::Warn("Cannot use Mirror Clamp To Edge as Sampler Address Mode without host GPU support");
return vk::SamplerAddressMode::eClampToEdge; // We use a normal clamp to edge to approximate it
}
@ -2039,11 +2039,11 @@ namespace skyline::gpu::interconnect {
},
};
if (!gpu.quirks.supportsSamplerReductionMode)
if (!gpu.traits.supportsSamplerReductionMode)
samplerInfo.unlink<vk::SamplerReductionModeCreateInfoEXT>();
vk::BorderColor &borderColor{samplerInfo.get<vk::SamplerCreateInfo>().borderColor};
if (gpu.quirks.supportsCustomBorderColor) {
if (gpu.traits.supportsCustomBorderColor) {
borderColor = ConvertBorderColorWithCustom(samplerControl.borderColorR, samplerControl.borderColorG, samplerControl.borderColorB, samplerControl.borderColorA);
if (borderColor != vk::BorderColor::eFloatCustomEXT)
samplerInfo.unlink<vk::SamplerCustomBorderColorCreateInfoEXT>();
@ -2090,7 +2090,7 @@ namespace skyline::gpu::interconnect {
}
}();
if (indexBuffer.type == vk::IndexType::eUint8EXT && !gpu.quirks.supportsUint8Indices)
if (indexBuffer.type == vk::IndexType::eUint8EXT && !gpu.traits.supportsUint8Indices)
throw exception("Cannot use U8 index buffer without host GPU support");
indexBuffer.view.reset();
@ -2395,7 +2395,7 @@ namespace skyline::gpu::interconnect {
auto storage{std::make_shared<Storage>(std::move(pipelineLayout), std::move(descriptorSet))};
// Submit Draw
executor.AddSubpass([=, &vkDevice = gpu.vkDevice, shaderModules = programState.shaderModules, shaderStages = programState.shaderStages, inputAssemblyState = inputAssemblyState, multiViewport = gpu.quirks.supportsMultipleViewports, viewports = viewports, scissors = scissors, rasterizerState = rasterizerState, multisampleState = multisampleState, depthState = depthState, blendState = blendState, storage = std::move(storage), supportsVertexAttributeDivisor = gpu.quirks.supportsVertexAttributeDivisor, vertexBufferHandles = std::move(vertexBufferHandles), vertexBufferOffsets = std::move(vertexBufferOffsets), pipelineCache = *pipelineCache](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &, vk::RenderPass renderPass, u32 subpassIndex) mutable {
executor.AddSubpass([=, &vkDevice = gpu.vkDevice, shaderModules = programState.shaderModules, shaderStages = programState.shaderStages, inputAssemblyState = inputAssemblyState, multiViewport = gpu.traits.supportsMultipleViewports, viewports = viewports, scissors = scissors, rasterizerState = rasterizerState, multisampleState = multisampleState, depthState = depthState, blendState = blendState, storage = std::move(storage), supportsVertexAttributeDivisor = gpu.traits.supportsVertexAttributeDivisor, vertexBufferHandles = std::move(vertexBufferHandles), vertexBufferOffsets = std::move(vertexBufferOffsets), pipelineCache = *pipelineCache](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &, vk::RenderPass renderPass, u32 subpassIndex) mutable {
vk::StructureChain<vk::PipelineVertexInputStateCreateInfo, vk::PipelineVertexInputDivisorStateCreateInfoEXT> vertexState{
vk::PipelineVertexInputStateCreateInfo{
.pVertexBindingDescriptions = vertexBindingDescriptions.data(),

View File

@ -24,42 +24,42 @@ namespace Shader::Log {
namespace skyline::gpu {
ShaderManager::ShaderManager(const DeviceState &state, GPU &gpu) : gpu(gpu) {
auto &quirks{gpu.quirks};
auto &traits{gpu.traits};
hostTranslateInfo = Shader::HostTranslateInfo{
.support_float16 = quirks.supportsFloat16,
.support_int64 = quirks.supportsInt64,
.support_float16 = traits.supportsFloat16,
.support_int64 = traits.supportsInt64,
.needs_demote_reorder = false,
};
constexpr u32 TegraX1WarpSize{32}; //!< The amount of threads in a warp on the Tegra X1
profile = Shader::Profile{
.supported_spirv = quirks.supportsSpirv14 ? 0x00010400U : 0x00010000U,
.supported_spirv = traits.supportsSpirv14 ? 0x00010400U : 0x00010000U,
.unified_descriptor_binding = true,
.support_descriptor_aliasing = true,
.support_int8 = quirks.supportsInt8,
.support_int16 = quirks.supportsInt16,
.support_int64 = quirks.supportsInt64,
.support_int8 = traits.supportsInt8,
.support_int16 = traits.supportsInt16,
.support_int64 = traits.supportsInt64,
.support_vertex_instance_id = false,
.support_float_controls = quirks.supportsFloatControls,
.support_separate_denorm_behavior = quirks.floatControls.denormBehaviorIndependence == vk::ShaderFloatControlsIndependence::eAll,
.support_separate_rounding_mode = quirks.floatControls.roundingModeIndependence == vk::ShaderFloatControlsIndependence::eAll,
.support_fp16_denorm_preserve = static_cast<bool>(quirks.floatControls.shaderDenormPreserveFloat16),
.support_fp32_denorm_preserve = static_cast<bool>(quirks.floatControls.shaderDenormPreserveFloat32),
.support_fp16_denorm_flush = static_cast<bool>(quirks.floatControls.shaderDenormFlushToZeroFloat16),
.support_fp32_denorm_flush = static_cast<bool>(quirks.floatControls.shaderDenormFlushToZeroFloat32),
.support_fp16_signed_zero_nan_preserve = static_cast<bool>(quirks.floatControls.shaderSignedZeroInfNanPreserveFloat16),
.support_fp32_signed_zero_nan_preserve = static_cast<bool>(quirks.floatControls.shaderSignedZeroInfNanPreserveFloat32),
.support_fp64_signed_zero_nan_preserve = static_cast<bool>(quirks.floatControls.shaderSignedZeroInfNanPreserveFloat64),
.support_float_controls = traits.supportsFloatControls,
.support_separate_denorm_behavior = traits.floatControls.denormBehaviorIndependence == vk::ShaderFloatControlsIndependence::eAll,
.support_separate_rounding_mode = traits.floatControls.roundingModeIndependence == vk::ShaderFloatControlsIndependence::eAll,
.support_fp16_denorm_preserve = static_cast<bool>(traits.floatControls.shaderDenormPreserveFloat16),
.support_fp32_denorm_preserve = static_cast<bool>(traits.floatControls.shaderDenormPreserveFloat32),
.support_fp16_denorm_flush = static_cast<bool>(traits.floatControls.shaderDenormFlushToZeroFloat16),
.support_fp32_denorm_flush = static_cast<bool>(traits.floatControls.shaderDenormFlushToZeroFloat32),
.support_fp16_signed_zero_nan_preserve = static_cast<bool>(traits.floatControls.shaderSignedZeroInfNanPreserveFloat16),
.support_fp32_signed_zero_nan_preserve = static_cast<bool>(traits.floatControls.shaderSignedZeroInfNanPreserveFloat32),
.support_fp64_signed_zero_nan_preserve = static_cast<bool>(traits.floatControls.shaderSignedZeroInfNanPreserveFloat64),
.support_explicit_workgroup_layout = false,
.support_vote = quirks.supportsSubgroupVote,
.support_viewport_index_layer_non_geometry = quirks.supportsShaderViewportIndexLayer,
.support_vote = traits.supportsSubgroupVote,
.support_viewport_index_layer_non_geometry = traits.supportsShaderViewportIndexLayer,
.support_viewport_mask = false,
.support_typeless_image_loads = quirks.supportsImageReadWithoutFormat,
.support_demote_to_helper_invocation = quirks.supportsShaderDemoteToHelper,
.support_int64_atomics = quirks.supportsAtomicInt64,
.support_typeless_image_loads = traits.supportsImageReadWithoutFormat,
.support_demote_to_helper_invocation = traits.supportsShaderDemoteToHelper,
.support_int64_atomics = traits.supportsAtomicInt64,
.support_derivative_control = true,
.support_geometry_shader_passthrough = false,
.warp_size_potentially_larger_than_guest = TegraX1WarpSize < quirks.subgroupSize,
.warp_size_potentially_larger_than_guest = TegraX1WarpSize < traits.subgroupSize,
.lower_left_origin_mode = false,
.need_declared_frag_colors = false,
};

View File

@ -2,10 +2,10 @@
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <adrenotools/bcenabler.h>
#include "quirk_manager.h"
#include "trait_manager.h"
namespace skyline::gpu {
QuirkManager::QuirkManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2) {
TraitManager::TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2) {
bool hasCustomBorderColorExtension{}, hasShaderAtomicInt64{}, hasShaderFloat16Int8Ext{}, hasShaderDemoteToHelper{};
bool supportsUniformBufferStandardLayout{}; // We require VK_KHR_uniform_buffer_standard_layout but assume it is implicitly supported even when not present
@ -114,7 +114,14 @@ namespace skyline::gpu {
subgroupSize = deviceProperties2.get<vk::PhysicalDeviceSubgroupProperties>().subgroupSize;
}
void QuirkManager::ApplyDriverPatches(const vk::raii::Context &context) {
std::string TraitManager::Summary() {
return fmt::format(
"\n* Supports U8 Indices: {}\n* Supports Sampler Mirror Clamp To Edge: {}\n* Supports Sampler Reduction Mode: {}\n* Supports Custom Border Color (Without Format): {}\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}\n* Supports Vertex Attribute Zero Divisor: {}\n* Supports Multiple Viewports: {}\n* Supports Shader Viewport Index: {}\n* Supports SPIR-V 1.4: {}\n* Supports Shader Invocation Demotion: {}\n* Supports 16-bit FP: {}\n* Supports 8-bit Integers: {}\n* Supports 16-bit Integers: {}\n* Supports 64-bit Integers: {}\n* Supports Atomic 64-bit Integers: {}\n* Supports Floating Point Behavior Control: {}\n* Supports Image Read Without Format: {}\n* Supports Subgroup Vote: {}\n* Subgroup Size: {}",
supportsUint8Indices, supportsSamplerMirrorClampToEdge, supportsSamplerReductionMode, supportsCustomBorderColor, supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor, supportsVertexAttributeZeroDivisor, supportsMultipleViewports, supportsShaderViewportIndexLayer, supportsSpirv14, supportsShaderDemoteToHelper, supportsFloat16, supportsInt8, supportsInt16, supportsInt64, supportsAtomicInt64, supportsFloatControls, supportsImageReadWithoutFormat, supportsSubgroupVote, subgroupSize
);
}
void TraitManager::ApplyDriverPatches(const vk::raii::Context &context) {
// Create an instance without validation layers in order to get pointers to the functions we need to patch from the driver
vk::ApplicationInfo applicationInfo{
.apiVersion = VK_API_VERSION_1_0,
@ -128,7 +135,7 @@ namespace skyline::gpu {
auto properties{physicalDevice.getProperties()};
// Apply BCeNabler for Adreno devices
auto type{adrenotools_get_bcn_type( VK_VERSION_MAJOR(properties.driverVersion), VK_VERSION_MINOR(properties.driverVersion), properties.vendorID)};
auto type{adrenotools_get_bcn_type(VK_VERSION_MAJOR(properties.driverVersion), VK_VERSION_MINOR(properties.driverVersion), properties.vendorID)};
if (type == ADRENOTOOLS_BCN_PATCH) {
if (adrenotools_patch_bcn(reinterpret_cast<void *>(physicalDevice.getDispatcher()->vkGetPhysicalDeviceFormatProperties)))
Logger::Info("Applied BCeNabler patch");
@ -138,11 +145,4 @@ namespace skyline::gpu {
Logger::Info("BCeNabler skipped, blob BCN support is present");
}
}
std::string QuirkManager::Summary() {
return fmt::format(
"\n* Supports U8 Indices: {}\n* Supports Sampler Mirror Clamp To Edge: {}\n* Supports Sampler Reduction Mode: {}\n* Supports Custom Border Color (Without Format): {}\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}\n* Supports Vertex Attribute Zero Divisor: {}\n* Supports Multiple Viewports: {}\n* Supports Shader Viewport Index: {}\n* Supports SPIR-V 1.4: {}\n* Supports Shader Invocation Demotion: {}\n* Supports 16-bit FP: {}\n* Supports 8-bit Integers: {}\n* Supports 16-bit Integers: {}\n* Supports 64-bit Integers: {}\n* Supports Atomic 64-bit Integers: {}\n* Supports Floating Point Behavior Control: {}\n* Supports Image Read Without Format: {}\n* Supports Subgroup Vote: {}\n* Subgroup Size: {}",
supportsUint8Indices, supportsSamplerMirrorClampToEdge, supportsSamplerReductionMode, supportsCustomBorderColor, supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor, supportsVertexAttributeZeroDivisor, supportsMultipleViewports, supportsShaderViewportIndexLayer, supportsSpirv14, supportsShaderDemoteToHelper, supportsFloat16, supportsInt8, supportsInt16, supportsInt64, supportsAtomicInt64, supportsFloatControls, supportsImageReadWithoutFormat, supportsSubgroupVote, subgroupSize
);
}
}

View File

@ -8,9 +8,9 @@
namespace skyline::gpu {
/**
* @brief Checks and stores all the quirks of the host GPU discovered at runtime
* @brief Checks and stores all the traits of the host GPU discovered at runtime
*/
class QuirkManager {
class TraitManager {
public:
bool supportsUint8Indices{}; //!< If the device supports using uint8 indices in index buffers (with VK_EXT_index_type_uint8)
bool supportsSamplerMirrorClampToEdge{}; //!< If the device supports a mirrored clamp to edge as a sampler address mode (with VK_KHR_sampler_mirror_clamp_to_edge)
@ -35,13 +35,13 @@ namespace skyline::gpu {
bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote
u32 subgroupSize{}; //!< Size of a subgroup on the host GPU
QuirkManager() = default;
TraitManager() = default;
using DeviceProperties2 = vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>;
using DeviceFeatures2 = vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, vk::PhysicalDeviceShaderFloat16Int8Features, vk::PhysicalDeviceShaderAtomicInt64Features, vk::PhysicalDeviceUniformBufferStandardLayoutFeatures>;
QuirkManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2);
TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2);
/**
* @brief Applies driver specific binary patches to the driver (e.g. BCeNabler)
@ -49,7 +49,7 @@ namespace skyline::gpu {
void ApplyDriverPatches(const vk::raii::Context &context);
/**
* @return A summary of all the GPU quirks as a human-readable string
* @return A summary of all the GPU traits as a human-readable string
*/
std::string Summary();
};