From 8b5ac56d66ba207f65bb5e281163dc409927b534 Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 19 Jul 2024 14:38:05 -0700 Subject: [PATCH] OpenGL Renderer: More FBO rework. --- desmume/src/OGLRender.cpp | 257 ++++++++++++++++++++-------------- desmume/src/OGLRender.h | 25 ++-- desmume/src/OGLRender_3_2.cpp | 116 ++++++++++----- 3 files changed, 247 insertions(+), 151 deletions(-) diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 830e8d580..014ae426c 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -2835,12 +2835,15 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() // Set up FBOs glGenFramebuffersEXT(1, &OGLRef.fboClearImageID); glGenFramebuffersEXT(1, &OGLRef.fboRenderID); + glGenFramebuffersEXT(1, &OGLRef.fboRenderMutableID); glGenFramebuffersEXT(1, &OGLRef.fboColorOutMainID); glGenFramebuffersEXT(1, &OGLRef.fboColorOutWorkingID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboColorOutMainID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE) { @@ -2871,8 +2874,8 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboClearImageID); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIFogAttrID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_CI_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_CI_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIFogAttrID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); @@ -2888,6 +2891,26 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderMutableID); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_WORKING_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); + + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) + { + INFO("OpenGL: Failed to create FBOs!\n"); + this->DestroyFBOs(); + + return OGLERROR_FBO_CREATE_ERROR; + } + + // Assign the default read/draw buffers. + glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, OGL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); @@ -2909,6 +2932,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboRenderMutableID; INFO("OpenGL: Successfully created FBOs.\n"); return OGLERROR_NOERR; @@ -2926,8 +2950,9 @@ void OpenGLRenderer_1_2::DestroyFBOs() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); - glDeleteFramebuffers(1, &OGLRef.fboColorOutMainID); - glDeleteFramebuffers(1, &OGLRef.fboColorOutWorkingID); + glDeleteFramebuffersEXT(1, &OGLRef.fboRenderMutableID); + glDeleteFramebuffersEXT(1, &OGLRef.fboColorOutMainID); + glDeleteFramebuffersEXT(1, &OGLRef.fboColorOutWorkingID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIDepthStencilID); @@ -2975,6 +3000,8 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO(GLsizei numSamples) // Set up multisampled rendering FBO glGenFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); + glGenFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderMutableID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, OGL_COLOROUT_ATTACHMENT_ID, GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, OGL_POLYID_ATTACHMENT_ID, GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); @@ -2994,6 +3021,25 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO(GLsizei numSamples) glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderMutableID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, OGL_COLOROUT_ATTACHMENT_ID, GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, OGL_POLYID_ATTACHMENT_ID, GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, OGL_WORKING_ATTACHMENT_ID, GL_RENDERBUFFER_EXT, OGLRef.rboMSGWorkingID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); + + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) + { + INFO("OpenGL: Failed to create multisampled FBO!\n"); + this->DestroyMultisampledFBO(); + + return OGLERROR_FBO_CREATE_ERROR; + } + + glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); INFO("OpenGL: Successfully created multisampled FBO.\n"); @@ -3011,6 +3057,7 @@ void OpenGLRenderer_1_2::DestroyMultisampledFBO() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); + glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderMutableID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGWorkingID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); @@ -3111,14 +3158,14 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms() std::stringstream shaderFlags; shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n"; shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n"; - shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; + shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing && this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0) << "\n"; shaderFlags << "\n"; shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n"; shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n"); shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n"); shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n"; - shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; - shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; + shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog && this->_deviceInfo.isFogSupported) ? 1 : 0) << "\n"; + shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0) << "\n"; shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; shaderFlags << "\n"; shaderFlags << "#define ATTACHMENT_WORKING_BUFFER " << GeometryAttachmentWorkingBuffer[programFlags.DrawBuffersMode] << "\n"; @@ -3952,13 +3999,12 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons { // Just downsample the color buffer now so that we have some texture data to sample from in the non-multisample shader. // This is not perfectly pixel accurate, but it's better than nothing. - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboColorOutMainID); glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingMutableFBO); + glUseProgram(OGLRef.programGeometryZeroDstAlphaID); glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight); glDisable(GL_BLEND); @@ -4001,6 +4047,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; this->_geometryProgramFlags.EnableEdgeMark = 0; this->_geometryProgramFlags.EnableFog = 0; + this->_geometryProgramFlags.OpaqueDrawMode = 0; this->_SetupGeometryShaders(this->_geometryProgramFlags); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); @@ -4018,7 +4065,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons // Restore OpenGL states back to normal. this->_geometryProgramFlags = oldGProgramFlags; this->_SetupGeometryShaders(this->_geometryProgramFlags); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -4046,15 +4093,11 @@ void OpenGLRenderer_1_2::_ResolveWorkingBackFacing() } glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboColorOutWorkingID); glReadBuffer(OGL_WORKING_ATTACHMENT_ID); - glDrawBuffer(OGL_WORKING_ATTACHMENT_ID); glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - // Reset framebuffer targets glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); } @@ -4069,7 +4112,7 @@ void OpenGLRenderer_1_2::_ResolveGeometry() } glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderMutableID); if (this->isShaderSupported) { @@ -4091,19 +4134,15 @@ void OpenGLRenderer_1_2::_ResolveGeometry() glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - // Reset framebuffer targets - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); } else { // Blit the color buffer - glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - // Reset framebuffer targets - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); } + + // Reset framebuffer targets + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); } Render3DError OpenGLRenderer_1_2::ReadBackPixels() @@ -4372,7 +4411,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading; this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0; this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0; - this->_geometryProgramFlags.OpaqueDrawMode = (this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0; + this->_geometryProgramFlags.OpaqueDrawMode = 1; this->_SetupGeometryShaders(this->_geometryProgramFlags); @@ -4415,14 +4454,24 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co // Even with no polygons to draw, we always need to set these 3 flags so that // glDrawBuffers() can reference the correct set of FBO attachments using // OGLGeometryFlags.DrawBuffersMode. - this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; - this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; + this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0; + this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0; this->_geometryProgramFlags.OpaqueDrawMode = 1; } if (this->isFBOSupported) { - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; + if (this->_enableMultisampledRendering) + { + OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboMSIntermediateRenderMutableID; + } + else + { + OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboRenderMutableID; + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); if (this->isShaderSupported) @@ -4481,8 +4530,17 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry() if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount) { + // We are now rendering the transparent polys. this->_geometryProgramFlags.OpaqueDrawMode = 0; + // Geometry flags have changed, so we need to update shader uniforms and also + // update draw buffers based on the flags. + this->_SetupGeometryShaders(this->_geometryProgramFlags); + if (this->isFBOSupported && this->isShaderSupported) + { + glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + } + if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending) { if (this->_clippedPolyOpaqueCount == 0) @@ -4508,12 +4566,6 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry() glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); glStencilMask(0xFF); - - this->_SetupGeometryShaders(this->_geometryProgramFlags); - if (this->isFBOSupported && this->isShaderSupported) - { - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); - } } if (this->_clippedPolyOpaqueCount == 0) @@ -4556,6 +4608,11 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer() OGLRenderRef &OGLRef = *this->ref; // Set up the postprocessing states + if (this->isFBOSupported) + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboColorOutMainID); + } + glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight); glDisable(GL_DEPTH_TEST); @@ -4616,7 +4673,6 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer() glUseProgram(OGLRef.programEdgeMarkID); glUniform1i(OGLRef.uniformStateClearPolyID, this->_pendingRenderStates.clearPolyID); glUniform1f(OGLRef.uniformStateClearDepth, this->_pendingRenderStates.clearDepth); - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -4641,12 +4697,6 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer() } OGLFogShaderID shaderID = this->_fogProgramMap[this->_fogProgramKey.key]; - - if (this->isFBOSupported) - { - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); - } - glUseProgram(shaderID.program); glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, this->_pendingRenderStates.enableFogAlphaOnly); @@ -4664,11 +4714,6 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer() glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA); glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); - - if (this->isFBOSupported) - { - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); - } } if (this->isVAOSupported) @@ -4708,7 +4753,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf this->UploadClearImage(colorBuffer, depthBuffer, fogBuffer, opaquePolyID); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboClearImageID); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderMutableID); // It might seem wasteful to be doing a separate glClear(GL_STENCIL_BUFFER_BIT) instead // of simply blitting the stencil buffer with everything else. @@ -4737,77 +4782,67 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf if (this->_enableFog && this->_deviceInfo.isFogSupported) { - glReadBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); + glReadBuffer(OGL_CI_FOGATTRIBUTES_ATTACHMENT_ID); glDrawBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); } // Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO. - glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glReadBuffer(OGL_CI_COLOROUT_ATTACHMENT_ID); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); } else { glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); } - if (this->isMultisampledFBOSupported) + if (this->_enableMultisampledRendering) { - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; - if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID) + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderMutableID); + + // See above comment for why we need to get clear the stencil buffer separately. + glClearStencil(opaquePolyID); + glClear(GL_STENCIL_BUFFER_BIT); + + if (this->isShaderSupported) { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - - // See above comment for why we need to get clear the stencil buffer separately. - glClearStencil(opaquePolyID); - glClear(GL_STENCIL_BUFFER_BIT); + if (this->_emulateDepthLEqualPolygonFacing && this->_isDepthLEqualPolygonFacingSupported) + { + glDrawBuffer(OGL_WORKING_ATTACHMENT_ID); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } - if (this->isShaderSupported) + if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) { - if (this->_emulateDepthLEqualPolygonFacing && this->_isDepthLEqualPolygonFacingSupported) - { - glDrawBuffer(OGL_WORKING_ATTACHMENT_ID); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - } - - if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) - { - glDrawBuffer(OGL_POLYID_ATTACHMENT_ID); - glClearColor((GLfloat)opaquePolyID/63.0f, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - } - - if (this->_enableFog && this->_deviceInfo.isFogSupported) - { - glReadBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); - glDrawBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); - glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - // Blit the color and depth buffers. Do this last so that color attachment 0 is set to the read FBO. - glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); - glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffer(OGL_POLYID_ATTACHMENT_ID); + glClearColor((GLfloat)opaquePolyID/63.0f, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); } - else + + if (this->_enableFog && this->_deviceInfo.isFogSupported) { - // Blit the color and depth buffers. - glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); + glReadBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); + glDrawBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); + glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); } + + // Blit the color and depth buffers. Do this last so that color attachment 0 is set to the read FBO. + glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } + else + { + // Blit the color and depth buffers. + glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); } } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); + return OGLERROR_NOERR; } @@ -4815,14 +4850,10 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const Color4u8 &clearColor666 { OGLRenderRef &OGLRef = *this->ref; - if (this->isFBOSupported) - { - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - } - if (this->isShaderSupported && this->isFBOSupported) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingMutableFBO); + glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glClearColor(divide6bitBy63_LUT[clearColor6665.r], divide6bitBy63_LUT[clearColor6665.g], divide6bitBy63_LUT[clearColor6665.b], divide5bitBy31_LUT[clearColor6665.a]); glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF); @@ -4850,7 +4881,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const Color4u8 &clearColor666 glClear(GL_COLOR_BUFFER_BIT); } - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); this->_needsZeroDstAlphaPass = (clearColor6665.a == 0); } else @@ -5646,7 +5677,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading; this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0; this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0; - this->_geometryProgramFlags.OpaqueDrawMode = (this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0; + this->_geometryProgramFlags.OpaqueDrawMode = 1; this->_SetupGeometryShaders(this->_geometryProgramFlags); @@ -5671,14 +5702,24 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co // Even with no polygons to draw, we always need to set these 3 flags so that // glDrawBuffers() can reference the correct set of FBO attachments using // OGLGeometryFlags.DrawBuffersMode. - this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; - this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; + this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0; + this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0; this->_geometryProgramFlags.OpaqueDrawMode = 1; } if (this->isFBOSupported) { - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; + if (this->_enableMultisampledRendering) + { + OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboMSIntermediateRenderMutableID; + } + else + { + OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboRenderMutableID; + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 167ce044c..21baf8c11 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -368,15 +368,21 @@ EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT) // Assign the FBO attachments for the main geometry render #if defined(GL_VERSION_3_0) || defined(GL_ES_VERSION_3_0) - #define OGL_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0 - #define OGL_WORKING_ATTACHMENT_ID GL_COLOR_ATTACHMENT3 - #define OGL_POLYID_ATTACHMENT_ID GL_COLOR_ATTACHMENT1 - #define OGL_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT2 + #define OGL_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0 + #define OGL_WORKING_ATTACHMENT_ID GL_COLOR_ATTACHMENT1 + #define OGL_POLYID_ATTACHMENT_ID GL_COLOR_ATTACHMENT2 + #define OGL_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT3 + + #define OGL_CI_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0 + #define OGL_CI_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT1 #else - #define OGL_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0_EXT - #define OGL_WORKING_ATTACHMENT_ID GL_COLOR_ATTACHMENT3_EXT - #define OGL_POLYID_ATTACHMENT_ID GL_COLOR_ATTACHMENT1_EXT - #define OGL_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT2_EXT + #define OGL_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0_EXT + #define OGL_WORKING_ATTACHMENT_ID GL_COLOR_ATTACHMENT1_EXT + #define OGL_POLYID_ATTACHMENT_ID GL_COLOR_ATTACHMENT2_EXT + #define OGL_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT3_EXT + + #define OGL_CI_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0_EXT + #define OGL_CI_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT1_EXT #endif enum OpenGLVariantID @@ -628,10 +634,13 @@ struct OGLRenderRef GLuint fboClearImageID; GLuint fboRenderID; + GLuint fboRenderMutableID; GLuint fboColorOutMainID; GLuint fboColorOutWorkingID; GLuint fboMSIntermediateRenderID; + GLuint fboMSIntermediateRenderMutableID; GLuint selectedRenderingFBO; + GLuint selectedRenderingMutableFBO; // Shader states GLuint vertexGeometryShaderID; diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 1c4c32790..dec8699d2 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -924,12 +924,14 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() // Set up FBOs glGenFramebuffers(1, &OGLRef.fboClearImageID); glGenFramebuffers(1, &OGLRef.fboRenderID); + glGenFramebuffers(1, &OGLRef.fboRenderMutableID); glGenFramebuffers(1, &OGLRef.fboColorOutMainID); glGenFramebuffers(1, &OGLRef.fboColorOutWorkingID); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboColorOutMainID); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { @@ -960,8 +962,8 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboClearImageID); - glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIFogAttrID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_CI_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_CI_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texCIFogAttrID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) @@ -976,6 +978,25 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderMutableID); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + INFO("OpenGL: Failed to create FBOs!\n"); + this->DestroyFBOs(); + + return OGLERROR_FBO_CREATE_ERROR; + } + + // Assign the default read/draw buffers. + glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); @@ -996,6 +1017,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboRenderMutableID; INFO("OpenGL: Successfully created FBOs.\n"); return OGLERROR_NOERR; @@ -1013,6 +1035,7 @@ void OpenGLRenderer_3_2::DestroyFBOs() glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboClearImageID); glDeleteFramebuffers(1, &OGLRef.fboRenderID); + glDeleteFramebuffers(1, &OGLRef.fboRenderMutableID); glDeleteFramebuffers(1, &OGLRef.fboColorOutMainID); glDeleteFramebuffers(1, &OGLRef.fboColorOutWorkingID); glDeleteTextures(1, &OGLRef.texCIColorID); @@ -1084,8 +1107,37 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples) // Set up multisampled rendering FBO glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); + glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderMutableID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); +#ifdef GL_VERSION_3_2 + if (this->willUsePerSampleZeroDstPass) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID, 0); + } + else +#endif + { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGColorID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGWorkingID); + } + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGPolyID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n"); + this->DestroyMultisampledFBO(); + + return OGLERROR_FBO_CREATE_ERROR; + } + + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderMutableID); + #ifdef GL_VERSION_3_2 if (this->willUsePerSampleZeroDstPass) { @@ -1128,6 +1180,7 @@ void OpenGLRenderer_3_2::DestroyMultisampledFBO() glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); + glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderMutableID); glDeleteTextures(1, &OGLRef.texMSGColorID); glDeleteTextures(1, &OGLRef.texMSGWorkingID); glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID); @@ -2061,13 +2114,12 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons { // Just downsample the color buffer now so that we have some texture data to sample from in the non-multisample shader. // This is not perfectly pixel accurate, but it's better than nothing. - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboColorOutMainID); glBlitFramebuffer(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); } + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingMutableFBO); + glUseProgram((isRunningMSAAWithPerSampleShading) ? OGLRef.programMSGeometryZeroDstAlphaID : OGLRef.programGeometryZeroDstAlphaID); glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight); glDisable(GL_BLEND); @@ -2089,6 +2141,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; this->_geometryProgramFlags.EnableEdgeMark = 0; this->_geometryProgramFlags.EnableFog = 0; + this->_geometryProgramFlags.OpaqueDrawMode = 0; this->_SetupGeometryShaders(this->_geometryProgramFlags); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); @@ -2106,7 +2159,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons // Restore OpenGL states back to normal. this->_geometryProgramFlags = oldGProgramFlags; this->_SetupGeometryShaders(this->_geometryProgramFlags); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -2134,18 +2187,13 @@ void OpenGLRenderer_3_2::_ResolveWorkingBackFacing() } glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboColorOutWorkingID); glReadBuffer(OGL_WORKING_ATTACHMENT_ID); - glDrawBuffer(OGL_WORKING_ATTACHMENT_ID); glBlitFramebuffer(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - // Reset framebuffer targets glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); } void OpenGLRenderer_3_2::_ResolveGeometry() @@ -2158,7 +2206,7 @@ void OpenGLRenderer_3_2::_ResolveGeometry() } glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderMutableID); if (this->_enableEdgeMark) { @@ -2181,7 +2229,6 @@ void OpenGLRenderer_3_2::_ResolveGeometry() // Reset framebuffer targets glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); } Render3DError OpenGLRenderer_3_2::ReadBackPixels() @@ -2464,7 +2511,17 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co this->_geometryProgramFlags.OpaqueDrawMode = 1; } - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; + if (this->_enableMultisampledRendering) + { + OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboMSIntermediateRenderMutableID; + } + else + { + OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + OGLRef.selectedRenderingMutableFBO = OGLRef.fboRenderMutableID; + } + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -2487,6 +2544,7 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer() OGLRenderRef &OGLRef = *this->ref; // Set up the postprocessing states + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboColorOutMainID); glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight); glDisable(GL_DEPTH_TEST); @@ -2524,7 +2582,6 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer() else { glUseProgram(OGLRef.programEdgeMarkID); - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -2545,7 +2602,6 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer() } OGLFogShaderID shaderID = this->_fogProgramMap[this->_fogProgramKey.key]; - glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glUseProgram(shaderID.program); glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -2576,8 +2632,7 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf this->UploadClearImage(colorBuffer, depthBuffer, fogBuffer, opaquePolyID); glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboClearImageID); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderMutableID); if (this->_emulateDepthLEqualPolygonFacing) { @@ -2595,25 +2650,20 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf if (this->_enableFog) { // Blit the fog buffer - glReadBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); + glReadBuffer(OGL_CI_FOGATTRIBUTES_ATTACHMENT_ID); glDrawBuffer(OGL_FOGATTRIBUTES_ATTACHMENT_ID); glBlitFramebuffer(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); } // Blit the color and depth/stencil buffers. Do this last so that color attachment 0 is set to the read FBO. - glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); + glReadBuffer(OGL_CI_COLOROUT_ATTACHMENT_ID); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glBlitFramebuffer(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); - - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; - if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID) + if (this->_enableMultisampledRendering) { glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboRenderID); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderMutableID); if (this->_emulateDepthLEqualPolygonFacing) { @@ -2638,20 +2688,16 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID); glBlitFramebuffer(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); } + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); + return OGLERROR_NOERR; } Render3DError OpenGLRenderer_3_2::ClearUsingValues(const Color4u8 &clearColor6665, const FragmentAttributes &clearAttributes) { OGLRenderRef &OGLRef = *this->ref; - OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(4, GeometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); const GLfloat oglColor[4] = {divide6bitBy63_LUT[clearColor6665.r], divide6bitBy63_LUT[clearColor6665.g], divide6bitBy63_LUT[clearColor6665.b], divide5bitBy31_LUT[clearColor6665.a]}; glClearBufferfv(GL_COLOR, 0, oglColor);