Add quirk for relaxed render pass compatibility

As we require a relaxed version of the Vulkan render pass compatibility clause for caching multi-subpass render passes, we now utilize a quirk to determine if this is supported which it is on Nvidia/Adreno while AMD/Mali where it isn't supported we force single-subpass render passes.
This commit is contained in:
PixelyIon 2022-04-24 16:18:36 +05:30
parent 44615c8dd2
commit 94e6f3cfa0
5 changed files with 20 additions and 6 deletions

View File

@ -51,7 +51,13 @@ namespace skyline::gpu::interconnect {
cycle->AttachObject(dependency); cycle->AttachObject(dependency);
} }
void CommandExecutor::AddSubpass(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment) { void CommandExecutor::AddSubpass(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment, bool exclusiveSubpass) {
if (exclusiveSubpass && renderPass) {
nodes.emplace_back(std::in_place_type_t<node::RenderPassEndNode>());
renderPass = nullptr;
subpassCount = 0;
}
bool newRenderPass{CreateRenderPass(renderArea)}; bool newRenderPass{CreateRenderPass(renderArea)};
renderPass->AddSubpass(inputAttachments, colorAttachments, depthStencilAttachment ? &*depthStencilAttachment : nullptr); renderPass->AddSubpass(inputAttachments, colorAttachments, depthStencilAttachment ? &*depthStencilAttachment : nullptr);
if (newRenderPass) if (newRenderPass)

View File

@ -57,9 +57,10 @@ namespace skyline::gpu::interconnect {
/** /**
* @brief Adds a command that needs to be executed inside a subpass configured with certain attachments * @brief Adds a command that needs to be executed inside a subpass configured with certain attachments
* @param exclusiveSubpass If this subpass should be the only subpass in a render pass
* @note Any supplied texture should be attached prior and not undergo any persistent layout transitions till execution * @note Any supplied texture should be attached prior and not undergo any persistent layout transitions till execution
*/ */
void AddSubpass(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span<TextureView *> inputAttachments = {}, span<TextureView *> colorAttachments = {}, TextureView *depthStencilAttachment = {}); void AddSubpass(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span<TextureView *> inputAttachments = {}, span<TextureView *> colorAttachments = {}, TextureView *depthStencilAttachment = {}, bool exclusiveSubpass = false);
/** /**
* @brief Adds a subpass that clears the entirety of the specified attachment with a color value, it may utilize VK_ATTACHMENT_LOAD_OP_CLEAR for a more efficient clear when possible * @brief Adds a subpass that clears the entirety of the specified attachment with a color value, it may utilize VK_ATTACHMENT_LOAD_OP_CLEAR for a more efficient clear when possible

View File

@ -2897,7 +2897,7 @@ namespace skyline::gpu::interconnect {
cycle->AttachObject(drawStorage); cycle->AttachObject(drawStorage);
}, vk::Rect2D{ }, vk::Rect2D{
.extent = activeColorRenderTargets.empty() ? depthRenderTarget.guest.dimensions : activeColorRenderTargets.front()->texture->dimensions, .extent = activeColorRenderTargets.empty() ? depthRenderTarget.guest.dimensions : activeColorRenderTargets.front()->texture->dimensions,
}, {}, activeColorRenderTargets, depthRenderTargetView); }, {}, activeColorRenderTargets, depthRenderTargetView, !gpu.traits.quirks.relaxedRenderPassCompatibility);
} }
void DrawVertex(u32 vertexCount, u32 firstVertex) { void DrawVertex(u32 vertexCount, u32 firstVertex) {

View File

@ -143,6 +143,7 @@ namespace skyline::gpu {
needsIndividualTextureBindingWrites = true; needsIndividualTextureBindingWrites = true;
vkImageMutableFormatCostly = true; // Disables UBWC vkImageMutableFormatCostly = true; // Disables UBWC
brokenDescriptorAliasing = true; brokenDescriptorAliasing = true;
relaxedRenderPassCompatibility = true; // Adreno drivers support relaxed render pass compatibility rules
if (deviceProperties.driverVersion < VK_MAKE_VERSION(512, 600, 0)) 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 maxSubpassCount = 64; // Driver will segfault while destroying the renderpass and associated objects if this is exceeded on all 5xx and below drivers
@ -160,6 +161,11 @@ namespace skyline::gpu {
break; break;
} }
case vk::DriverId::eNvidiaProprietary: {
relaxedRenderPassCompatibility = true;
break;
}
case vk::DriverId::eAmdProprietary: { case vk::DriverId::eAmdProprietary: {
maxGlobalPriority = vk::QueueGlobalPriorityEXT::eHigh; maxGlobalPriority = vk::QueueGlobalPriorityEXT::eHigh;
break; break;
@ -172,8 +178,8 @@ namespace skyline::gpu {
std::string TraitManager::QuirkManager::Summary() { std::string TraitManager::QuirkManager::Summary() {
return fmt::format( return fmt::format(
"\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Broken Descriptor Aliasing: {}\n* Max Subpass Count: {}\n* Max Global Queue Priority: {}", "\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Broken Descriptor Aliasing: {}\n* Relaxed Render Pass Compatibility: {}\n* Max Subpass Count: {}\n* Max Global Queue Priority: {}",
needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, brokenDescriptorAliasing, maxSubpassCount, vk::to_string(maxGlobalPriority) needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, brokenDescriptorAliasing, relaxedRenderPassCompatibility, maxSubpassCount, vk::to_string(maxGlobalPriority)
); );
} }

View File

@ -46,9 +46,10 @@ 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 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 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 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
bool relaxedRenderPassCompatibility{}; //!< [Adreno Proprietary/Freedreno] A relaxed version of Vulkan specification's render pass compatibility clause which allows for caching pipeline objects for multi-subpass renderpasses, this is intentionally disabled by default as it requires testing prior to enabling
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 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
vk::QueueGlobalPriorityEXT maximumGlobalPriority{vk::QueueGlobalPriorityEXT::eMedium}; //!< The highest allowed global priority of the queue, drivers will not allow higher priorities to be set on queues vk::QueueGlobalPriorityEXT maxGlobalPriority{vk::QueueGlobalPriorityEXT::eMedium}; //!< The highest allowed global priority of the queue, drivers will not allow higher priorities to be set on queues
QuirkManager() = default; QuirkManager() = default;