Handle one more error case in presentation

This commit is contained in:
Henrik Rydgård 2024-10-28 12:43:18 +01:00
parent cf678a1aa6
commit 56a164a14e
5 changed files with 22 additions and 8 deletions

View File

@ -1523,7 +1523,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G
return tex;
}
void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat) {
bool FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat) {
textureCache_->ForgetLastTexture();
shaderManager_->DirtyLastShader();
@ -1531,7 +1531,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int
float v0 = 0.0f, v1 = 1.0f;
Draw::Texture *pixelsTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272);
if (!pixelsTex)
return;
return false;
int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL;
OutputFlags flags = g_Config.iDisplayFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST;
@ -1552,6 +1552,8 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int
DiscardFramebufferCopy();
currentRenderVfb_ = nullptr;
return true;
}
void FramebufferManagerCommon::SetViewport2D(int x, int y, int w, int h) {
@ -1633,8 +1635,14 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) {
if (!vfb) {
if (Memory::IsValidAddress(fbaddr)) {
// The game is displaying something directly from RAM. In GTA, it's decoded video.
DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_);
// This effectively calls presentation_->NotifyPresent();
// If successful, this effectively calls presentation_->NotifyPresent();
if (!DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_)) {
if (useBufferedRendering_) {
// Bind and clear the backbuffer. This should be the first time during the frame that it's bound.
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput_DrawError");
}
presentation_->NotifyPresent();
}
return;
} else {
DEBUG_LOG(Log::FrameBuf, "Found no FBO to display! displayFBPtr = %08x", fbaddr);

View File

@ -356,7 +356,7 @@ public:
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes);
void DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat);
bool DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat);
void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag);

View File

@ -535,6 +535,7 @@ void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) {
shaderManager_->DirtyLastShader();
// after this, render pass is active.
framebufferManager_->CopyDisplayToOutput(reallyDirty);
gstate_c.Dirty(DIRTY_TEXTURE_IMAGE);

View File

@ -9,6 +9,7 @@ public:
GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
~GPUCommonHW();
// This can fail, and if so no render pass is active.
void CopyDisplayToOutput(bool reallyDirty) override;
void DoState(PointerWrap &p) override;
void DeviceLost() override;

View File

@ -1397,7 +1397,9 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
}
Draw::BackendState state = draw->GetCurrentBackendState();
_assert_msg_(!state.valid || state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d tag: %s", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, screenManager()->topScreen()->tag());
if (state.valid) {
_assert_msg_(state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d tag: %s", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, screenManager()->topScreen()->tag());
}
// Need to make sure the UI texture is available, for "darken".
screenManager()->getUIContext()->BeginFrame();
@ -1523,8 +1525,10 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
Draw::BackendState state = draw->GetCurrentBackendState();
// We allow if !state.valid, that means it's not the Vulkan backend.
_assert_msg_(!state.valid || state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d bound: %d", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, (int)framebufferBound);
// State.valid just states whether the passes parameter has a meaningful value.
if (state.valid) {
_assert_msg_(state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d bound: %d", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, (int)framebufferBound);
}
screenManager()->getUIContext()->BeginFrame();