diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index b489c111a5..4e5b65e094 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -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 { diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 472f2e240f..902381f752 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -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 +} diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index ea452de49f..247d978800 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -554,6 +554,8 @@ private: void ResetDescriptorLists(int frame); void FlushDescriptors(int frame); + void SanityCheckPassesOnAdd(); + FrameDataShared frameDataShared_; FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index df309de01f..70022b3bb3 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -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. } }