Add subpass limit quirk to fix Adreno driver bug

Older Adreno proprietary drivers (5xx and below) will segfault while destroying the renderpass and associated objects if more than 64 subpasses are within a renderpass due to internal driver implementation details. This commit introduces checks to automatically break up a renderpass when that limit is hit.
This commit is contained in:
PixelyIon 2022-03-28 14:41:37 +05:30
parent 65d5a3bce5
commit e294fa8c91
6 changed files with 13 additions and 5 deletions

View File

@ -1,3 +1,3 @@
<component name="DependencyValidationManager">
<scope name="ShaderCompiler" pattern="file[skyline.app]:libraries/shader-compiler//*" />
<scope name="ShaderCompiler" pattern="file[skyline.app.main]:shader-compiler//*" />
</component>

View File

@ -12,15 +12,18 @@ namespace skyline::gpu::interconnect {
}
bool CommandExecutor::CreateRenderPass(vk::Rect2D renderArea) {
if (renderPass && renderPass->renderArea != renderArea) {
if (renderPass && (renderPass->renderArea != renderArea || subpassCount > gpu.traits.quirks.maxSubpassCount)) {
nodes.emplace_back(std::in_place_type_t<node::RenderPassEndNode>());
renderPass = nullptr;
subpassCount = 0;
}
bool newRenderPass{renderPass == nullptr};
if (newRenderPass)
// We need to create a render pass if one doesn't already exist or the current one isn't compatible
renderPass = &std::get<node::RenderPassNode>(nodes.emplace_back(std::in_place_type_t<node::RenderPassNode>(), renderArea));
else
subpassCount++;
return newRenderPass;
}
@ -119,6 +122,7 @@ namespace skyline::gpu::interconnect {
if (renderPass) {
nodes.emplace_back(std::in_place_type_t<node::RenderPassEndNode>());
renderPass = nullptr;
subpassCount = 0;
}
{

View File

@ -18,6 +18,7 @@ namespace skyline::gpu::interconnect {
CommandScheduler::ActiveCommandBuffer activeCommandBuffer;
boost::container::stable_vector<node::NodeVariant> nodes;
node::RenderPassNode *renderPass{};
size_t subpassCount{}; //!< The number of subpasses in the current render pass
std::unordered_set<Texture *> syncTextures; //!< All textures that need to be synced prior to and after execution
using SharedBufferDelegate = std::shared_ptr<Buffer::BufferDelegate>;

View File

@ -529,7 +529,7 @@ namespace skyline::gpu {
}
if (gpu.traits.quirks.vkImageMutableFormatCostly && pFormat->vkFormat != format->vkFormat)
Logger::Warn("Creating a view of a texture with a different format without mutable format");
Logger::Warn("Creating a view of a texture with a different format without mutable format: {} - {}", vk::to_string(pFormat->vkFormat), vk::to_string(format->vkFormat));
auto view{std::make_shared<TextureView>(shared_from_this(), type, range, pFormat, mapping)};
views.push_back(view);

View File

@ -133,6 +133,8 @@ namespace skyline::gpu {
needsIndividualTextureBindingWrites = true;
vkImageMutableFormatCostly = true; // Disables UBWC
brokenDescriptorAliasing = true;
if (deviceProperties.driverVersion < VK_MAKE_VERSION(512, 600, 0))
maxSubpassCount = 64; // Driver will segfault while destroying the renderpass and associated objects if this is exceeded on all 5xx and below drivers
break;
}
@ -148,8 +150,8 @@ namespace skyline::gpu {
std::string TraitManager::QuirkManager::Summary() {
return fmt::format(
"\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}",
needsIndividualTextureBindingWrites, vkImageMutableFormatCostly
"\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Broken Descriptor Aliasing: {}\n* Max Subpass Count: {}",
needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, brokenDescriptorAliasing, maxSubpassCount
);
}

View File

@ -42,6 +42,7 @@ namespace skyline::gpu {
bool needsIndividualTextureBindingWrites{}; //!< [Adreno Proprietary] A bug that requires descriptor set writes for VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER to be done individually with descriptorCount = 1 rather than batched
bool vkImageMutableFormatCostly{}; //!< [Adreno Proprietary/Freedreno] An indication that VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is costly and should not be enabled unless absolutely necessary (Disables UBWC on Adreno GPUs)
bool brokenDescriptorAliasing{}; //!< [Adreno Proprietary] A bug that causes alised descriptor sets to be incorrectly interpreted by the shader compiler leading to it buggering up LLVM function argument types and crashing
u32 maxSubpassCount{std::numeric_limits<u32>::max()}; //!< The maximum amount of subpasses within a renderpass, this is limited to 64 on older Adreno proprietary drivers
QuirkManager() = default;