mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-19 21:52:45 +00:00
Correct an issue where reformat didn't work if no renderpass was active due to the use of clear.
Also instantly convert to a clear when binding the framebuffer in cases when we know it's the optimal thing. The QueueRunner would have later merged anyway hopefully, but I like the simplicity of this.
This commit is contained in:
parent
7d10a0c609
commit
4aec10d04f
@ -265,8 +265,14 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb,
|
||||
// to exactly reproduce in 4444 and 8888 formats.
|
||||
|
||||
if (old == GE_FORMAT_565) {
|
||||
// Previously started a render pass here to clear, but better to just, well, explicitly clear.
|
||||
draw_->Clear(Draw::FBChannel::FB_COLOR_BIT | Draw::FBChannel::FB_STENCIL_BIT, 0, 0.0f, 0);
|
||||
// We have to bind here instead of clear, since it can be that no framebuffer is bound.
|
||||
// The backend can sometimes directly optimize it to a clear.
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "ReformatFramebuffer");
|
||||
// draw_->Clear(Draw::FBChannel::FB_COLOR_BIT | Draw::FBChannel::FB_STENCIL_BIT, 0, 0.0f, 0);
|
||||
|
||||
// Need to dirty anything that has command buffer dynamic state, in case we started a new pass above.
|
||||
// Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager.
|
||||
gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,11 +456,25 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() {
|
||||
|
||||
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
|
||||
assert(insideFrame_);
|
||||
// Eliminate dupes.
|
||||
// Eliminate dupes, instantly convert to a clear if possible.
|
||||
if (!steps_.empty() && steps_.back()->stepType == VKRStepType::RENDER && steps_.back()->render.framebuffer == fb) {
|
||||
if (color != VKRRenderPassAction::CLEAR && depth != VKRRenderPassAction::CLEAR && stencil != VKRRenderPassAction::CLEAR) {
|
||||
// We don't move to a new step, this bind was unnecessary and we can safely skip it.
|
||||
// Not sure how much this is still happening but probably worth checking for nevertheless.
|
||||
u32 clearMask = 0;
|
||||
if (color == VKRRenderPassAction::CLEAR) {
|
||||
clearMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
if (depth == VKRRenderPassAction::CLEAR) {
|
||||
clearMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
if (stencil == VKRRenderPassAction::CLEAR) {
|
||||
clearMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
|
||||
// If we need a clear and the previous step has commands already, it's best to just add a clear and keep going.
|
||||
// If there's no clear needed, let's also do that.
|
||||
//
|
||||
// However, if we do need a clear and there are no commands in the previous pass,
|
||||
// we want the queuerunner to have the opportunity to merge, so we'll go ahead and make a new renderpass.
|
||||
if (clearMask == 0 || !steps_.back()->commands.empty()) {
|
||||
curRenderStep_ = steps_.back();
|
||||
curStepHasViewport_ = false;
|
||||
curStepHasScissor_ = false;
|
||||
@ -473,6 +487,14 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (clearMask != 0) {
|
||||
VkRenderData data{ VKRRenderCommand::CLEAR };
|
||||
data.clear.clearColor = clearColor;
|
||||
data.clear.clearZ = clearDepth;
|
||||
data.clear.clearStencil = clearStencil;
|
||||
data.clear.clearMask = clearMask;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user