mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-29 23:54:16 +01:00
Fix Adreno Texture Sampler Binding Bug
Adreno proprietary drivers suffer from a bug where `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER` requires 2 descriptor slots rather than one, we add a padding slot to fix this issue. `QuirkManager` was introduced to handle per-vendor/per-device errata and allow enabling this on Adreno proprietary drivers specifically as to not affect the performance of other devices.
This commit is contained in:
parent
ddb2ba8a1b
commit
9f7e80cf8f
@ -152,7 +152,7 @@ namespace skyline::gpu {
|
|||||||
throw exception("Cannot find Vulkan device extension: \"{}\"", requiredExtension.data());
|
throw exception("Cannot find Vulkan device extension: \"{}\"", requiredExtension.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto deviceProperties2{physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>()};
|
auto deviceProperties2{physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceDriverProperties, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>()};
|
||||||
|
|
||||||
traits = TraitManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2);
|
traits = TraitManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2);
|
||||||
traits.ApplyDriverPatches(context);
|
traits.ApplyDriverPatches(context);
|
||||||
@ -191,11 +191,12 @@ 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 ? " <--" : "");
|
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};
|
auto properties{deviceProperties2.get<vk::PhysicalDeviceProperties2>().properties};
|
||||||
Logger::Info("Vulkan Device:\nName: {}\nType: {}\nVulkan Version: {}.{}.{}\nDriver Version: {}.{}.{}\nQueues:{}\nExtensions:{}\nTraits:{}",
|
Logger::Info("Vulkan Device:\nName: {}\nType: {}\nDriver ID: {}\nVulkan Version: {}.{}.{}\nDriver Version: {}.{}.{}\nQueues:{}\nExtensions:{}\nTraits:{}\nQuirks:{}",
|
||||||
properties.deviceName, vk::to_string(properties.deviceType),
|
properties.deviceName, vk::to_string(properties.deviceType),
|
||||||
|
vk::to_string(deviceProperties2.get<vk::PhysicalDeviceDriverProperties>().driverID),
|
||||||
VK_API_VERSION_MAJOR(properties.apiVersion), VK_API_VERSION_MINOR(properties.apiVersion), VK_API_VERSION_PATCH(properties.apiVersion),
|
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),
|
VK_API_VERSION_MAJOR(properties.driverVersion), VK_API_VERSION_MINOR(properties.driverVersion), VK_API_VERSION_PATCH(properties.driverVersion),
|
||||||
queueString, extensionString, traits.Summary());
|
queueString, extensionString, traits.Summary(), traits.quirks.Summary());
|
||||||
}
|
}
|
||||||
|
|
||||||
return vk::raii::Device(physicalDevice, vk::DeviceCreateInfo{
|
return vk::raii::Device(physicalDevice, vk::DeviceCreateInfo{
|
||||||
|
@ -942,18 +942,27 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!program.info.texture_descriptors.empty()) {
|
if (!program.info.texture_descriptors.empty()) {
|
||||||
descriptorSetWrites.push_back(vk::WriteDescriptorSet{
|
if (!gpu.traits.quirks.needsTextureBindingPadding)
|
||||||
.dstBinding = bindingIndex,
|
descriptorSetWrites.push_back(vk::WriteDescriptorSet{
|
||||||
.descriptorCount = static_cast<u32>(program.info.texture_descriptors.size()),
|
.dstBinding = bindingIndex,
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
.descriptorCount = static_cast<u32>(program.info.texture_descriptors.size()),
|
||||||
.pImageInfo = imageInfo.data() + imageInfo.size(),
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
});
|
.pImageInfo = imageInfo.data() + imageInfo.size(),
|
||||||
|
});
|
||||||
|
|
||||||
for (auto &texture : program.info.texture_descriptors) {
|
for (auto &texture : program.info.texture_descriptors) {
|
||||||
|
if (gpu.traits.quirks.needsTextureBindingPadding)
|
||||||
|
descriptorSetWrites.push_back(vk::WriteDescriptorSet{
|
||||||
|
.dstBinding = bindingIndex,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.pImageInfo = imageInfo.data() + imageInfo.size(),
|
||||||
|
});
|
||||||
|
|
||||||
layoutBindings.push_back(vk::DescriptorSetLayoutBinding{
|
layoutBindings.push_back(vk::DescriptorSetLayoutBinding{
|
||||||
.binding = bindingIndex++,
|
.binding = bindingIndex++,
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = gpu.traits.quirks.needsTextureBindingPadding ? 1U : 2U,
|
||||||
.stageFlags = pipelineStage.vkStage,
|
.stageFlags = pipelineStage.vkStage,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "trait_manager.h"
|
#include "trait_manager.h"
|
||||||
|
|
||||||
namespace skyline::gpu {
|
namespace skyline::gpu {
|
||||||
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) {
|
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) : quirks(deviceProperties2.get<vk::PhysicalDeviceProperties2>().properties, deviceProperties2.get<vk::PhysicalDeviceDriverProperties>()) {
|
||||||
bool hasCustomBorderColorExtension{}, hasShaderAtomicInt64{}, hasShaderFloat16Int8Ext{}, hasShaderDemoteToHelper{};
|
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
|
bool supportsUniformBufferStandardLayout{}; // We require VK_KHR_uniform_buffer_standard_layout but assume it is implicitly supported even when not present
|
||||||
|
|
||||||
@ -48,11 +48,13 @@ namespace skyline::gpu {
|
|||||||
#undef EXT_SET_V
|
#undef EXT_SET_V
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FEAT_SET(structName, feature, property) \
|
#define FEAT_SET(structName, feature, property) \
|
||||||
if (deviceFeatures2.get<structName>().feature) { \
|
do { \
|
||||||
property = true; \
|
if (deviceFeatures2.get<structName>().feature) { \
|
||||||
enabledFeatures2.get<structName>().feature = true; \
|
property = true; \
|
||||||
}
|
enabledFeatures2.get<structName>().feature = true; \
|
||||||
|
} \
|
||||||
|
} while(false);
|
||||||
|
|
||||||
FEAT_SET(vk::PhysicalDeviceFeatures2, features.logicOp, supportsLogicOp)
|
FEAT_SET(vk::PhysicalDeviceFeatures2, features.logicOp, supportsLogicOp)
|
||||||
FEAT_SET(vk::PhysicalDeviceFeatures2, features.multiViewport, supportsMultipleViewports)
|
FEAT_SET(vk::PhysicalDeviceFeatures2, features.multiViewport, supportsMultipleViewports)
|
||||||
@ -96,10 +98,9 @@ namespace skyline::gpu {
|
|||||||
else
|
else
|
||||||
enabledFeatures2.unlink<vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT>();
|
enabledFeatures2.unlink<vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT>();
|
||||||
|
|
||||||
|
|
||||||
if (supportsUniformBufferStandardLayout) {
|
if (supportsUniformBufferStandardLayout) {
|
||||||
FEAT_SET(vk::PhysicalDeviceUniformBufferStandardLayoutFeatures, uniformBufferStandardLayout, supportsUniformBufferStandardLayout)
|
FEAT_SET(vk::PhysicalDeviceUniformBufferStandardLayoutFeatures, uniformBufferStandardLayout, supportsUniformBufferStandardLayout)
|
||||||
}else {
|
} else {
|
||||||
enabledFeatures2.unlink<vk::PhysicalDeviceUniformBufferStandardLayoutFeatures>();
|
enabledFeatures2.unlink<vk::PhysicalDeviceUniformBufferStandardLayoutFeatures>();
|
||||||
Logger::Warn("Cannot find VK_KHR_uniform_buffer_standard_layout, assuming implicit support");
|
Logger::Warn("Cannot find VK_KHR_uniform_buffer_standard_layout, assuming implicit support");
|
||||||
}
|
}
|
||||||
@ -121,6 +122,25 @@ namespace skyline::gpu {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TraitManager::QuirkManager::QuirkManager(const vk::PhysicalDeviceProperties &deviceProperties, const vk::PhysicalDeviceDriverProperties &driverProperties) {
|
||||||
|
switch (driverProperties.driverID) {
|
||||||
|
case vk::DriverId::eQualcommProprietary: {
|
||||||
|
needsTextureBindingPadding = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TraitManager::QuirkManager::Summary() {
|
||||||
|
return fmt::format(
|
||||||
|
"\n* Needs Texture Binding Padding: {}",
|
||||||
|
needsTextureBindingPadding
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void TraitManager::ApplyDriverPatches(const vk::raii::Context &context) {
|
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
|
// Create an instance without validation layers in order to get pointers to the functions we need to patch from the driver
|
||||||
vk::ApplicationInfo applicationInfo{
|
vk::ApplicationInfo applicationInfo{
|
||||||
|
@ -35,9 +35,25 @@ namespace skyline::gpu {
|
|||||||
bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote
|
bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote
|
||||||
u32 subgroupSize{}; //!< Size of a subgroup on the host GPU
|
u32 subgroupSize{}; //!< Size of a subgroup on the host GPU
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Manages a list of any vendor/device-specific errata in the host GPU
|
||||||
|
*/
|
||||||
|
struct QuirkManager {
|
||||||
|
bool needsTextureBindingPadding{}; //!< [Adreno Proprietary] A bug that requires a padding descriptor slot for VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
|
||||||
|
|
||||||
|
QuirkManager() = default;
|
||||||
|
|
||||||
|
QuirkManager(const vk::PhysicalDeviceProperties& deviceProperties, const vk::PhysicalDeviceDriverProperties& driverProperties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A summary of all the GPU quirks as a human-readable string
|
||||||
|
*/
|
||||||
|
std::string Summary();
|
||||||
|
} quirks;
|
||||||
|
|
||||||
TraitManager() = default;
|
TraitManager() = default;
|
||||||
|
|
||||||
using DeviceProperties2 = vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>;
|
using DeviceProperties2 = vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceDriverProperties, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>;
|
||||||
|
|
||||||
using DeviceFeatures2 = vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, vk::PhysicalDeviceShaderFloat16Int8Features, vk::PhysicalDeviceShaderAtomicInt64Features, vk::PhysicalDeviceUniformBufferStandardLayoutFeatures>;
|
using DeviceFeatures2 = vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, vk::PhysicalDeviceShaderFloat16Int8Features, vk::PhysicalDeviceShaderAtomicInt64Features, vk::PhysicalDeviceUniformBufferStandardLayoutFeatures>;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user