Fix bad framebuffer bind in Parappa The Rapper

This commit is contained in:
Henrik Rydgård 2024-05-29 12:23:54 +02:00
parent e5662f63d5
commit 87ead3f492
4 changed files with 32 additions and 6 deletions

View File

@ -154,9 +154,9 @@ struct VKRStep {
VKRRenderPassStoreAction colorStore;
VKRRenderPassStoreAction depthStore;
VKRRenderPassStoreAction stencilStore;
u8 clearStencil;
uint32_t clearColor;
float clearDepth;
u8 clearStencil;
int numDraws;
// Downloads and textures from this pass.
int numReads;
@ -173,20 +173,20 @@ struct VKRStep {
VKRFramebuffer *dst;
VkRect2D srcRect;
VkOffset2D dstPos;
int aspectMask;
VkImageAspectFlags aspectMask;
} copy;
struct {
VKRFramebuffer *src;
VKRFramebuffer *dst;
VkRect2D srcRect;
VkRect2D dstRect;
int aspectMask;
VkImageAspectFlags aspectMask;
VkFilter filter;
} blit;
struct {
int aspectMask;
VKRFramebuffer *src;
VkRect2D srcRect;
VkImageAspectFlags aspectMask;
bool delayed;
} readback;
struct {

View File

@ -900,6 +900,11 @@ void VulkanRenderManager::EndCurRenderStep() {
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth, VKRRenderPassLoadAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
_dbg_assert_(insideFrame_);
#ifdef _DEBUG
SanityCheckPassesOnAdd();
#endif
// Eliminate dupes (bind of the framebuffer we already are rendering to), instantly convert to a clear if possible.
if (!steps_.empty() && steps_.back()->stepType == VKRStepType::RENDER && steps_.back()->render.framebuffer == fb) {
u32 clearMask = 0;
@ -1233,6 +1238,10 @@ void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearSten
}
void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, VKRFramebuffer *dst, VkOffset2D dstPos, VkImageAspectFlags aspectMask, const char *tag) {
#ifdef _DEBUG
SanityCheckPassesOnAdd();
#endif
_dbg_assert_msg_(srcRect.offset.x >= 0, "srcrect offset x (%d) < 0", srcRect.offset.x);
_dbg_assert_msg_(srcRect.offset.y >= 0, "srcrect offset y (%d) < 0", srcRect.offset.y);
_dbg_assert_msg_(srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x (%d) + extent (%d) > width (%d)", srcRect.offset.x, srcRect.extent.width, (uint32_t)src->width);
@ -1297,6 +1306,10 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
}
void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, VKRFramebuffer *dst, VkRect2D dstRect, VkImageAspectFlags aspectMask, VkFilter filter, const char *tag) {
#ifdef _DEBUG
SanityCheckPassesOnAdd();
#endif
_dbg_assert_msg_(srcRect.offset.x >= 0, "srcrect offset x (%d) < 0", srcRect.offset.x);
_dbg_assert_msg_(srcRect.offset.y >= 0, "srcrect offset y (%d) < 0", srcRect.offset.y);
_dbg_assert_msg_(srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x (%d) + extent (%d) > width (%d)", srcRect.offset.x, srcRect.extent.width, (uint32_t)src->width);
@ -1849,3 +1862,14 @@ void VKRPipelineLayout::FlushDescSets(VulkanContext *vulkan, int frame, QueuePro
profile->descriptorsWritten += writeCount;
profile->descriptorsDeduped += dedupCount;
}
void VulkanRenderManager::SanityCheckPassesOnAdd() {
#if _DEBUG
// Check that we don't have any previous passes that write to the backbuffer, that must ALWAYS be the last one.
for (int i = 0; i < steps_.size(); i++) {
if (steps_[i]->stepType == VKRStepType::RENDER) {
_dbg_assert_(steps_[i]->render.framebuffer != nullptr);
}
}
#endif
}

View File

@ -554,6 +554,8 @@ private:
void ResetDescriptorLists(int frame);
void FlushDescriptors(int frame);
void SanityCheckPassesOnAdd();
FrameDataShared frameDataShared_;
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES];

View File

@ -3272,8 +3272,8 @@ void FramebufferManagerCommon::RebindFramebuffer(const char *tag) {
if (currentRenderVfb_ && currentRenderVfb_->fbo) {
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, tag);
} else {
// Should this even happen? It could while debugging, but maybe we can just skip binding at all.
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "RebindFramebuffer_Bad");
// This can happen (like it does in Parappa) when a frame starts with copies instead of rendering.
// Let's do nothing and assume it'll take care of itself.
}
}