OpenGL Renderer: Lower host GPU requirements for performing on-GPU final framebuffer conversions.
- Framebuffer conversion now occurs purely in shaders, and also performs flipping along with conversion. FBOs and PBOs are no longer required to do this. - If shaders are not available, then framebuffer flipping will occur if FBOs are available. PBOs are no longer required to do this. - Also fix a minor framebuffer attachment bug in the v3.2 renderer.
This commit is contained in:
parent
5deec25409
commit
69f97b056a
|
@ -596,11 +596,12 @@ static const char *FogFragShader_100 = {"\
|
||||||
static const char *FramebufferOutputVtxShader_100 = {"\
|
static const char *FramebufferOutputVtxShader_100 = {"\
|
||||||
attribute vec2 inPosition;\n\
|
attribute vec2 inPosition;\n\
|
||||||
attribute vec2 inTexCoord0;\n\
|
attribute vec2 inTexCoord0;\n\
|
||||||
|
uniform vec2 framebufferSize;\n\
|
||||||
varying vec2 texCoord;\n\
|
varying vec2 texCoord;\n\
|
||||||
\n\
|
\n\
|
||||||
void main()\n\
|
void main()\n\
|
||||||
{\n\
|
{\n\
|
||||||
texCoord = inTexCoord0;\n\
|
texCoord = vec2(inTexCoord0.x, (framebufferSize.y - (framebufferSize.y * inTexCoord0.y)) / framebufferSize.y);\n\
|
||||||
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
|
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
|
||||||
}\n\
|
}\n\
|
||||||
"};
|
"};
|
||||||
|
@ -632,6 +633,8 @@ static const char *FramebufferOutputRGBA8888FragShader_100 = {"\
|
||||||
\n\
|
\n\
|
||||||
void main()\n\
|
void main()\n\
|
||||||
{\n\
|
{\n\
|
||||||
|
// Note that we swap B and R since pixel readbacks are done in BGRA format for fastest\n\
|
||||||
|
// performance. The final color is still in RGBA format.\n\
|
||||||
gl_FragData[0] = texture2D(texInFragColor, texCoord).bgra;\n\
|
gl_FragData[0] = texture2D(texInFragColor, texCoord).bgra;\n\
|
||||||
}\n\
|
}\n\
|
||||||
"};
|
"};
|
||||||
|
@ -1051,8 +1054,8 @@ OpenGLRenderer::OpenGLRenderer()
|
||||||
isMultisampledFBOSupported = false;
|
isMultisampledFBOSupported = false;
|
||||||
isShaderSupported = false;
|
isShaderSupported = false;
|
||||||
isVAOSupported = false;
|
isVAOSupported = false;
|
||||||
willFlipFramebufferOnGPU = false;
|
willFlipOnlyFramebufferOnGPU = false;
|
||||||
willConvertFramebufferOnGPU = false;
|
willFlipAndConvertFramebufferOnGPU = false;
|
||||||
|
|
||||||
// Init OpenGL rendering states
|
// Init OpenGL rendering states
|
||||||
ref = new OGLRenderRef;
|
ref = new OGLRenderRef;
|
||||||
|
@ -1456,16 +1459,16 @@ Render3DError OpenGLRenderer::_FlushFramebufferFlipAndConvertOnCPU(const Fragmen
|
||||||
|
|
||||||
Render3DError OpenGLRenderer::FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16)
|
Render3DError OpenGLRenderer::FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16)
|
||||||
{
|
{
|
||||||
if (this->willFlipFramebufferOnGPU && this->willConvertFramebufferOnGPU)
|
if (this->willFlipAndConvertFramebufferOnGPU && this->isPBOSupported)
|
||||||
{
|
{
|
||||||
this->_renderNeedsFlushMain = false;
|
this->_renderNeedsFlushMain = false;
|
||||||
return Render3D::FlushFramebuffer(srcFramebuffer, NULL, dstFramebuffer16);
|
return Render3D::FlushFramebuffer(srcFramebuffer, NULL, dstFramebuffer16);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->_FlushFramebufferFlipAndConvertOnCPU(srcFramebuffer,
|
return this->_FlushFramebufferFlipAndConvertOnCPU(srcFramebuffer,
|
||||||
dstFramebufferMain, dstFramebuffer16,
|
dstFramebufferMain, dstFramebuffer16,
|
||||||
!this->willFlipFramebufferOnGPU, !this->willConvertFramebufferOnGPU);
|
!this->willFlipOnlyFramebufferOnGPU, !this->willFlipAndConvertFramebufferOnGPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RENDER3DERROR_NOERR;
|
return RENDER3DERROR_NOERR;
|
||||||
|
@ -1473,7 +1476,7 @@ Render3DError OpenGLRenderer::FlushFramebuffer(const FragmentColor *__restrict s
|
||||||
|
|
||||||
FragmentColor* OpenGLRenderer::GetFramebuffer()
|
FragmentColor* OpenGLRenderer::GetFramebuffer()
|
||||||
{
|
{
|
||||||
return (this->willFlipFramebufferOnGPU && this->willConvertFramebufferOnGPU) ? this->_mappedFramebuffer : GPU->GetEngineMain()->Get3DFramebufferMain();
|
return (this->willFlipAndConvertFramebufferOnGPU && this->isPBOSupported) ? this->_mappedFramebuffer : GPU->GetEngineMain()->Get3DFramebufferMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLTexture* OpenGLRenderer::GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing)
|
OpenGLTexture* OpenGLRenderer::GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing)
|
||||||
|
@ -1679,10 +1682,6 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
|
||||||
|
|
||||||
if (maxColorAttachments >= 4)
|
if (maxColorAttachments >= 4)
|
||||||
{
|
{
|
||||||
// Set these flags now because CreateFBOs() will use them.
|
|
||||||
this->willFlipFramebufferOnGPU = this->isPBOSupported;
|
|
||||||
this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isPBOSupported);
|
|
||||||
|
|
||||||
// This texture will be used as an FBO color attachment.
|
// This texture will be used as an FBO color attachment.
|
||||||
// If this texture wasn't already created by passing the shader support check,
|
// If this texture wasn't already created by passing the shader support check,
|
||||||
// then create the texture now.
|
// then create the texture now.
|
||||||
|
@ -1756,8 +1755,8 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set rendering support flags based on driver features.
|
// Set rendering support flags based on driver features.
|
||||||
this->willFlipFramebufferOnGPU = (this->isPBOSupported && this->isFBOSupported);
|
this->willFlipAndConvertFramebufferOnGPU = this->isShaderSupported && this->isVBOSupported;
|
||||||
this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isPBOSupported && this->isFBOSupported);
|
this->willFlipOnlyFramebufferOnGPU = this->willFlipAndConvertFramebufferOnGPU || this->isFBOSupported;
|
||||||
this->_deviceInfo.isEdgeMarkSupported = (this->isShaderSupported && this->isVBOSupported && this->isFBOSupported);
|
this->_deviceInfo.isEdgeMarkSupported = (this->isShaderSupported && this->isVBOSupported && this->isFBOSupported);
|
||||||
this->_deviceInfo.isFogSupported = (this->isShaderSupported && this->isVBOSupported && this->isFBOSupported);
|
this->_deviceInfo.isFogSupported = (this->isShaderSupported && this->isVBOSupported && this->isFBOSupported);
|
||||||
this->_deviceInfo.isTextureSmoothingSupported = this->isShaderSupported;
|
this->_deviceInfo.isTextureSmoothingSupported = this->isShaderSupported;
|
||||||
|
@ -2982,10 +2981,12 @@ Render3DError OpenGLRenderer_1_2::InitFramebufferOutputShaderLocations()
|
||||||
OGLRenderRef &OGLRef = *this->ref;
|
OGLRenderRef &OGLRef = *this->ref;
|
||||||
|
|
||||||
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||||
|
OGLRef.uniformFramebufferSize_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "framebufferSize");
|
||||||
OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
|
OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
||||||
|
|
||||||
glUseProgram(OGLRef.programFramebufferRGBA8888OutputID);
|
glUseProgram(OGLRef.programFramebufferRGBA8888OutputID);
|
||||||
|
OGLRef.uniformFramebufferSize_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "framebufferSize");
|
||||||
OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor");
|
OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor");
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor);
|
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor);
|
||||||
|
|
||||||
|
@ -3211,68 +3212,50 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
|
||||||
{
|
{
|
||||||
OGLRenderRef &OGLRef = *this->ref;
|
OGLRenderRef &OGLRef = *this->ref;
|
||||||
|
|
||||||
if (!this->isPBOSupported)
|
|
||||||
{
|
|
||||||
this->_pixelReadNeedsFinish = true;
|
|
||||||
return OGLERROR_NOERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->_mappedFramebuffer != NULL)
|
if (this->_mappedFramebuffer != NULL)
|
||||||
{
|
{
|
||||||
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||||
this->_mappedFramebuffer = NULL;
|
this->_mappedFramebuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
|
if (this->willFlipAndConvertFramebufferOnGPU)
|
||||||
if (this->willFlipFramebufferOnGPU)
|
|
||||||
{
|
{
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
|
// Both flips and converts the framebuffer on the GPU. No additional postprocessing
|
||||||
|
// should be necessary at this point.
|
||||||
|
const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID;
|
||||||
|
const GLint uniformTexNumber = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.uniformTexInFragColor_ConvertRGBA6665 : OGLRef.uniformTexInFragColor_ConvertRGBA8888;
|
||||||
|
const GLint uniformFramebufferSize = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.uniformFramebufferSize_ConvertRGBA6665 : OGLRef.uniformFramebufferSize_ConvertRGBA8888;
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
glUseProgram(convertProgramID);
|
||||||
{
|
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
if (this->isFBOSupported)
|
||||||
|
{
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
||||||
{
|
{
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
glUniform1i(uniformTexNumber, OGLTextureUnitID_GColor);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->willConvertFramebufferOnGPU)
|
|
||||||
{
|
|
||||||
// Perform the color space conversion while we're still on the GPU so
|
|
||||||
// that we can avoid having to do it on the CPU.
|
|
||||||
const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID;
|
|
||||||
|
|
||||||
glUseProgram(convertProgramID);
|
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
|
||||||
{
|
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_GColor);
|
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
|
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
glUniform1i(uniformTexNumber, OGLTextureUnitID_FinalColor);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
|
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glUniform1i(uniformTexNumber, OGLTextureUnitID_FinalColor);
|
||||||
|
glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor);
|
||||||
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight);
|
||||||
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
|
glUniform2f(uniformFramebufferSize, this->_framebufferWidth, this->_framebufferHeight);
|
||||||
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
|
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
@ -3305,20 +3288,35 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
|
||||||
glDisableVertexAttribArray(OGLVertexAttributeID_Position);
|
glDisableVertexAttribArray(OGLVertexAttributeID_Position);
|
||||||
glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
|
glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (this->willFlipOnlyFramebufferOnGPU)
|
||||||
|
{
|
||||||
|
// Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
|
||||||
|
// Further colorspace conversion will need to be done in a later step.
|
||||||
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
||||||
{
|
{
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
||||||
|
glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
|
glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->isPBOSupported)
|
||||||
|
{
|
||||||
// Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance
|
// Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance
|
||||||
// penalty if the readback is in any other format.
|
// penalty if the readback is in any other format.
|
||||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
this->_pixelReadNeedsFinish = true;
|
this->_pixelReadNeedsFinish = true;
|
||||||
return OGLERROR_NOERR;
|
return OGLERROR_NOERR;
|
||||||
|
@ -4349,14 +4347,11 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h)
|
||||||
return OGLERROR_BEGINGL_FAILED;
|
return OGLERROR_BEGINGL_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->isPBOSupported)
|
|
||||||
{
|
|
||||||
if (this->_mappedFramebuffer != NULL)
|
if (this->_mappedFramebuffer != NULL)
|
||||||
{
|
{
|
||||||
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||||
this->_mappedFramebuffer = NULL;
|
this->_mappedFramebuffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (this->isShaderSupported || this->isFBOSupported)
|
if (this->isShaderSupported || this->isFBOSupported)
|
||||||
{
|
{
|
||||||
|
|
|
@ -617,8 +617,8 @@ protected:
|
||||||
bool isMultisampledFBOSupported;
|
bool isMultisampledFBOSupported;
|
||||||
bool isShaderSupported;
|
bool isShaderSupported;
|
||||||
bool isVAOSupported;
|
bool isVAOSupported;
|
||||||
bool willFlipFramebufferOnGPU;
|
bool willFlipOnlyFramebufferOnGPU;
|
||||||
bool willConvertFramebufferOnGPU;
|
bool willFlipAndConvertFramebufferOnGPU;
|
||||||
|
|
||||||
FragmentColor *_mappedFramebuffer;
|
FragmentColor *_mappedFramebuffer;
|
||||||
FragmentColor *_workingTextureUnpackBuffer;
|
FragmentColor *_workingTextureUnpackBuffer;
|
||||||
|
|
|
@ -549,11 +549,12 @@ static const char *FramebufferOutputVtxShader_150 = {"\
|
||||||
\n\
|
\n\
|
||||||
in vec2 inPosition;\n\
|
in vec2 inPosition;\n\
|
||||||
in vec2 inTexCoord0;\n\
|
in vec2 inTexCoord0;\n\
|
||||||
|
uniform vec2 framebufferSize;\n\
|
||||||
out vec2 texCoord;\n\
|
out vec2 texCoord;\n\
|
||||||
\n\
|
\n\
|
||||||
void main()\n\
|
void main()\n\
|
||||||
{\n\
|
{\n\
|
||||||
texCoord = inTexCoord0;\n\
|
texCoord = vec2(inTexCoord0.x, (framebufferSize.y - (framebufferSize.y * inTexCoord0.y)) / framebufferSize.y);\n\
|
||||||
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
|
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
|
||||||
}\n\
|
}\n\
|
||||||
"};
|
"};
|
||||||
|
@ -570,7 +571,9 @@ static const char *FramebufferOutputFragShader_150 = {"\
|
||||||
\n\
|
\n\
|
||||||
void main()\n\
|
void main()\n\
|
||||||
{\n\
|
{\n\
|
||||||
vec4 colorRGBA6665 = texture(texInFragColor, texCoord);\n\
|
// Note that we swap B and R since pixel readbacks are done in BGRA format for fastest\n\
|
||||||
|
// performance. The final color is still in RGBA format.\n\
|
||||||
|
vec4 colorRGBA6665 = texture(texInFragColor, texCoord).bgra;\n\
|
||||||
colorRGBA6665 = floor((colorRGBA6665 * 255.0) + 0.5);\n\
|
colorRGBA6665 = floor((colorRGBA6665 * 255.0) + 0.5);\n\
|
||||||
colorRGBA6665.rgb = floor(colorRGBA6665.rgb / 4.0);\n\
|
colorRGBA6665.rgb = floor(colorRGBA6665.rgb / 4.0);\n\
|
||||||
colorRGBA6665.a = floor(colorRGBA6665.a / 8.0);\n\
|
colorRGBA6665.a = floor(colorRGBA6665.a / 8.0);\n\
|
||||||
|
@ -624,8 +627,8 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
|
||||||
this->isShaderSupported = true;
|
this->isShaderSupported = true;
|
||||||
|
|
||||||
// OpenGL v3.2 Core Profile should have all the necessary features to be able to flip and convert the framebuffer.
|
// OpenGL v3.2 Core Profile should have all the necessary features to be able to flip and convert the framebuffer.
|
||||||
this->willFlipFramebufferOnGPU = true;
|
this->willFlipOnlyFramebufferOnGPU = true;
|
||||||
this->willConvertFramebufferOnGPU = true;
|
this->willFlipAndConvertFramebufferOnGPU = true;
|
||||||
|
|
||||||
std::string vertexShaderProgram;
|
std::string vertexShaderProgram;
|
||||||
std::string fragmentShaderProgram;
|
std::string fragmentShaderProgram;
|
||||||
|
@ -803,10 +806,12 @@ Render3DError OpenGLRenderer_3_2::InitFramebufferOutputShaderLocations()
|
||||||
OGLRenderRef &OGLRef = *this->ref;
|
OGLRenderRef &OGLRef = *this->ref;
|
||||||
|
|
||||||
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||||
|
OGLRef.uniformFramebufferSize_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "framebufferSize");
|
||||||
OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
|
OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
||||||
|
|
||||||
glUseProgram(OGLRef.programFramebufferRGBA8888OutputID);
|
glUseProgram(OGLRef.programFramebufferRGBA8888OutputID);
|
||||||
|
OGLRef.uniformFramebufferSize_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "framebufferSize");
|
||||||
OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor");
|
OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor");
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor);
|
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor);
|
||||||
|
|
||||||
|
@ -975,7 +980,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texGDepthID, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texGDepthID, 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, OGLRef.texGPolyID, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, OGLRef.texGPolyID, 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, OGLRef.texZeroAlphaPixelMaskID, 0);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0);
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
@ -1011,7 +1015,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texGColorID, 0);
|
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_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, OGLRef.texZeroAlphaPixelMaskID);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, OGLRef.texZeroAlphaPixelMaskID, 0);
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
{
|
{
|
||||||
|
@ -1393,52 +1397,29 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels()
|
||||||
this->_mappedFramebuffer = NULL;
|
this->_mappedFramebuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
|
||||||
{
|
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
|
||||||
{
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->_outputFormat == NDSColorFormat_BGR666_Rev)
|
if (this->_outputFormat == NDSColorFormat_BGR666_Rev)
|
||||||
{
|
{
|
||||||
// Perform the RGBA6665 color space conversion while we're still on the GPU so
|
// Both flips and converts the framebuffer on the GPU. No additional postprocessing
|
||||||
// that we can avoid having to do it on the CPU.
|
// should be necessary at this point.
|
||||||
|
|
||||||
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
||||||
{
|
{
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_GColor);
|
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_GColor);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
|
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
|
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glUniform2f(OGLRef.uniformFramebufferSize_ConvertRGBA6665, this->_framebufferWidth, this->_framebufferHeight);
|
||||||
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
|
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
@ -1451,19 +1432,32 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels()
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||||
{
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||||
|
|
||||||
|
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
|
||||||
|
{
|
||||||
|
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
||||||
|
glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read back the pixels in RGBA format, since an OpenGL 3.2 device should be able to read back this
|
// Read back the pixels in RGBA format, since an OpenGL 3.2 device should be able to read back this
|
||||||
// format without a performance penalty.
|
// format without a performance penalty.
|
||||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
this->_pixelReadNeedsFinish = true;
|
this->_pixelReadNeedsFinish = true;
|
||||||
return OGLERROR_NOERR;
|
return OGLERROR_NOERR;
|
||||||
|
|
Loading…
Reference in New Issue