Vulkan: Ensure depth/stencil load match on Mali.

This commit is contained in:
Unknown W. Brackets 2020-05-25 12:14:03 -07:00
parent c90c29df32
commit 40a0525aea
2 changed files with 28 additions and 2 deletions

View file

@ -171,9 +171,8 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, StencilUp
return false;
if (dstBuffer->fbo) {
// Use keep because some drivers have trouble when stencilAction != depthAction.
// Typically, STENCIL_IS_ZERO means it's already bound, so this bind will be optimized away.
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "Stencil");
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::DONT_CARE }, "Stencil");
} else {
// something is wrong...
}

View file

@ -510,6 +510,23 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
VLOG("Empty render step. Usually happens after uploading pixels..");
}
// Older Mali drivers have issues with depth and stencil don't match load/clear/etc.
// TODO: Determine which versions and do this only where necessary.
u32 lateClearMask = 0;
if (depth != stencil && vulkan_->GetPhysicalDeviceProperties().properties.vendorID == VULKAN_VENDOR_ARM) {
if (stencil == VKRRenderPassAction::DONT_CARE) {
stencil = depth;
} else if (depth == VKRRenderPassAction::DONT_CARE) {
depth = stencil;
} else if (stencil == VKRRenderPassAction::CLEAR) {
depth = stencil;
lateClearMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
} else if (depth == VKRRenderPassAction::CLEAR) {
stencil = depth;
lateClearMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
}
VKRStep *step = new VKRStep{ VKRStepType::RENDER };
step->render.framebuffer = fb;
step->render.color = color;
@ -541,6 +558,16 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
curWidth_ = vulkan_->GetBackbufferWidth();
curHeight_ = vulkan_->GetBackbufferHeight();
}
// See above - we add a clear afterward if only one side for depth/stencil CLEAR/KEEP.
if (lateClearMask != 0) {
VkRenderData data{ VKRRenderCommand::CLEAR };
data.clear.clearColor = clearColor;
data.clear.clearZ = clearDepth;
data.clear.clearStencil = clearStencil;
data.clear.clearMask = lateClearMask;
curRenderStep_->commands.push_back(data);
}
}
bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag) {