diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index bc5580d6..97ec9e16 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -152,7 +152,7 @@ namespace skyline::gpu { throw exception("Cannot find Vulkan device extension: \"{}\"", requiredExtension.data()); } - auto deviceProperties2{physicalDevice.getProperties2()}; + auto deviceProperties2{physicalDevice.getProperties2()}; traits = TraitManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2); 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 ? " <--" : ""); auto properties{deviceProperties2.get().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), + vk::to_string(deviceProperties2.get().driverID), 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, traits.Summary()); + queueString, extensionString, traits.Summary(), traits.quirks.Summary()); } return vk::raii::Device(physicalDevice, vk::DeviceCreateInfo{ diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index cb55de36..593efa6d 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -942,18 +942,27 @@ namespace skyline::gpu::interconnect { } if (!program.info.texture_descriptors.empty()) { - descriptorSetWrites.push_back(vk::WriteDescriptorSet{ - .dstBinding = bindingIndex, - .descriptorCount = static_cast(program.info.texture_descriptors.size()), - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .pImageInfo = imageInfo.data() + imageInfo.size(), - }); + if (!gpu.traits.quirks.needsTextureBindingPadding) + descriptorSetWrites.push_back(vk::WriteDescriptorSet{ + .dstBinding = bindingIndex, + .descriptorCount = static_cast(program.info.texture_descriptors.size()), + .descriptorType = vk::DescriptorType::eCombinedImageSampler, + .pImageInfo = imageInfo.data() + imageInfo.size(), + }); 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{ .binding = bindingIndex++, .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = 1, + .descriptorCount = gpu.traits.quirks.needsTextureBindingPadding ? 1U : 2U, .stageFlags = pipelineStage.vkStage, }); diff --git a/app/src/main/cpp/skyline/gpu/trait_manager.cpp b/app/src/main/cpp/skyline/gpu/trait_manager.cpp index 940ca6e0..bef8b109 100644 --- a/app/src/main/cpp/skyline/gpu/trait_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/trait_manager.cpp @@ -5,7 +5,7 @@ #include "trait_manager.h" namespace skyline::gpu { - TraitManager::TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector &deviceExtensions, std::vector> &enabledExtensions, const DeviceProperties2 &deviceProperties2) { + TraitManager::TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector &deviceExtensions, std::vector> &enabledExtensions, const DeviceProperties2 &deviceProperties2) : quirks(deviceProperties2.get().properties, deviceProperties2.get()) { 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 @@ -48,11 +48,13 @@ namespace skyline::gpu { #undef EXT_SET_V } - #define FEAT_SET(structName, feature, property) \ - if (deviceFeatures2.get().feature) { \ - property = true; \ - enabledFeatures2.get().feature = true; \ - } + #define FEAT_SET(structName, feature, property) \ + do { \ + if (deviceFeatures2.get().feature) { \ + property = true; \ + enabledFeatures2.get().feature = true; \ + } \ + } while(false); FEAT_SET(vk::PhysicalDeviceFeatures2, features.logicOp, supportsLogicOp) FEAT_SET(vk::PhysicalDeviceFeatures2, features.multiViewport, supportsMultipleViewports) @@ -96,10 +98,9 @@ namespace skyline::gpu { else enabledFeatures2.unlink(); - if (supportsUniformBufferStandardLayout) { FEAT_SET(vk::PhysicalDeviceUniformBufferStandardLayoutFeatures, uniformBufferStandardLayout, supportsUniformBufferStandardLayout) - }else { + } else { enabledFeatures2.unlink(); 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) { // Create an instance without validation layers in order to get pointers to the functions we need to patch from the driver vk::ApplicationInfo applicationInfo{ diff --git a/app/src/main/cpp/skyline/gpu/trait_manager.h b/app/src/main/cpp/skyline/gpu/trait_manager.h index a652d166..ce952e68 100644 --- a/app/src/main/cpp/skyline/gpu/trait_manager.h +++ b/app/src/main/cpp/skyline/gpu/trait_manager.h @@ -35,9 +35,25 @@ 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 + /** + * @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; - using DeviceProperties2 = vk::StructureChain; + using DeviceProperties2 = vk::StructureChain; using DeviceFeatures2 = vk::StructureChain;