gonetz / GLideN64

A new generation, open-source graphics plugin for N64 emulators.
Other
754 stars 175 forks source link

blitParams.drawBuffer being zero-initialized instead of using ObjectHandle::defaultFrameBuffer — breaks rendering to FB #2717

Open rogual opened 1 year ago

rogual commented 1 year ago

I'm trying to get GlideN64 to render its output to a GL framebuffer.

Looking at the code, it seems that this is supported via ObjectHandle::defaultFramebuffer. I'm using the VidExt API to set this by returning my framebuffer's ID from VidExtFuncGLGetDefaultFramebuffer.

However, this causes GlideN64 to fill that framebuffer with black for a few (hundred?) frames, then stop rendering to it altogether.

Investigating, I found that GlideN64 sometimes creates a GraphicsDrawer::BlitOrCopyRectParams without initializing the drawBuffer field, letting it default to 0, which means "blit to the screen".

As far as I can tell, if GlideN64 has a nonzero default framebuffer, it shouldn't ever have a reason to render to the screen without using a framebuffer.

So, I tried making this change:

--- a/src/FrameBuffer.cpp
+++ b/src/FrameBuffer.cpp
@@ -1623,6 +1623,7 @@ void FrameBufferList::renderBuffer()
                        CombinerInfo::get().getTexrectUpscaleCopyProgram();
        }
        blitParams.readBuffer = readBuffer;
+       blitParams.drawBuffer = ObjectHandle::defaultFramebuffer;
        blitParams.invertY = config.frameBufferEmulation.enableOverscan == 0;

        drawer.copyTexturedRect(blitParams);
@@ -1114,6 +1114,7 @@ void FrameBufferList::_renderScreenSizeBuffer()
        blitParams.combiner = downscale ? CombinerInfo::get().getTexrectDownscaleCopyProgram() :
                CombinerInfo::get().getTexrectUpscaleCopyProgram();
        blitParams.readBuffer = pFilteredBuffer->m_FBO;
+       blitParams.drawBuffer = ObjectHandle::defaultFramebuffer;

        drawer.blitOrCopyTexturedRect(blitParams);

@@ -1449,6 +1450,8 @@ void FrameBufferList::OverscanBuffer::draw(u32 _fullHeight, bool _PAL)
        }

        blitParams.readBuffer = m_FBO;
+       blitParams.drawBuffer = ObjectHandle::defaultFramebuffer;        
        blitParams.invertY = false;

        gfxContext.clearColorBuffer(0.0f, 0.0f, 0.0f, 0.0f);

This works! GlideN64 now renders to its default framebuffer.

However, it only works as long as config.frameBufferEmulation is switched off.

Otherwise, the code takes a more complex path that I don't understand yet and the framebuffer is once again not rendered to.

I tried covering all the cases by adding a default-initializer:


--- a/src/GraphicsDrawer.h
+++ b/src/GraphicsDrawer.h
@@ -113,8 +113,8 @@ public:

        struct BlitOrCopyRectParams : public CopyRectParams
        {
-               graphics::ObjectHandle readBuffer;
-               graphics::ObjectHandle drawBuffer;
+               graphics::ObjectHandle readBuffer = graphics::ObjectHandle::defaultFramebuffer;
+               graphics::ObjectHandle drawBuffer = graphics::ObjectHandle::defaultFramebuffer;
                graphics::BlitMaskParam mask;
        };

...but this didn't help. Perhaps there are more places where things are being zero-initialized instead of using defaultFramebuffer?