Added CopyToFb function.

Replaces glBlitFramebuffer for multisampled framebuffers.
This commit is contained in:
Jean-Philip Desjardins 2016-03-03 23:48:30 -05:00
parent bb2dcf45c0
commit f065965d4f
3 changed files with 192 additions and 3 deletions

View File

@ -8,6 +8,7 @@
#include "GSH_OpenGL.h" #include "GSH_OpenGL.h"
#define NUM_SAMPLES 8 #define NUM_SAMPLES 8
//#define USE_COPYTOFB
GLenum CGSH_OpenGL::g_nativeClampModes[CGSHandler::CLAMP_MODE_MAX] = GLenum CGSH_OpenGL::g_nativeClampModes[CGSHandler::CLAMP_MODE_MAX] =
{ {
@ -78,10 +79,13 @@ void CGSH_OpenGL::ReleaseImpl()
m_presentProgram.reset(); m_presentProgram.reset();
m_presentVertexBuffer.Reset(); m_presentVertexBuffer.Reset();
m_presentVertexArray.Reset(); m_presentVertexArray.Reset();
m_copyToFbProgram.reset();
m_copyToFbFramebuffer.Reset();
m_copyToFbTexture.Reset();
m_copyToFbVertexBuffer.Reset();
m_copyToFbVertexArray.Reset();
m_primBuffer.Reset(); m_primBuffer.Reset();
m_primVertexArray.Reset(); m_primVertexArray.Reset();
m_copyToFbTexture.Reset();
m_copyToFbFramebuffer.Reset();
m_vertexParamsBuffer.Reset(); m_vertexParamsBuffer.Reset();
m_fragmentParamsBuffer.Reset(); m_fragmentParamsBuffer.Reset();
} }
@ -312,8 +316,13 @@ void CGSH_OpenGL::InitializeRC()
m_presentTextureUniform = glGetUniformLocation(*m_presentProgram, "g_texture"); m_presentTextureUniform = glGetUniformLocation(*m_presentProgram, "g_texture");
m_presentTexCoordScaleUniform = glGetUniformLocation(*m_presentProgram, "g_texCoordScale"); m_presentTexCoordScaleUniform = glGetUniformLocation(*m_presentProgram, "g_texCoordScale");
m_copyToFbProgram = GenerateCopyToFbProgram();
m_copyToFbTexture = Framework::OpenGl::CTexture::Create(); m_copyToFbTexture = Framework::OpenGl::CTexture::Create();
m_copyToFbFramebuffer = Framework::OpenGl::CFramebuffer::Create(); m_copyToFbFramebuffer = Framework::OpenGl::CFramebuffer::Create();
m_copyToFbVertexBuffer = GenerateCopyToFbVertexBuffer();
m_copyToFbVertexArray = GenerateCopyToFbVertexArray();
m_copyToFbSrcPositionUniform = glGetUniformLocation(*m_copyToFbProgram, "g_srcPosition");
m_copyToFbSrcSizeUniform = glGetUniformLocation(*m_copyToFbProgram, "g_srcSize");
m_primBuffer = Framework::OpenGl::CBuffer::Create(); m_primBuffer = Framework::OpenGl::CBuffer::Create();
m_primVertexArray = GeneratePrimVertexArray(); m_primVertexArray = GeneratePrimVertexArray();
@ -371,6 +380,52 @@ Framework::OpenGl::CVertexArray CGSH_OpenGL::GeneratePresentVertexArray()
return vertexArray; return vertexArray;
} }
Framework::OpenGl::CBuffer CGSH_OpenGL::GenerateCopyToFbVertexBuffer()
{
auto buffer = Framework::OpenGl::CBuffer::Create();
static const float bufferContents[] =
{
//Pos UV
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
};
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(bufferContents), bufferContents, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECKGLERROR();
return buffer;
}
Framework::OpenGl::CVertexArray CGSH_OpenGL::GenerateCopyToFbVertexArray()
{
auto vertexArray = Framework::OpenGl::CVertexArray::Create();
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, m_copyToFbVertexBuffer);
glEnableVertexAttribArray(static_cast<GLuint>(PRIM_VERTEX_ATTRIB::POSITION));
glVertexAttribPointer(static_cast<GLuint>(PRIM_VERTEX_ATTRIB::POSITION), 2, GL_FLOAT,
GL_FALSE, sizeof(float) * 4, reinterpret_cast<const GLvoid*>(0));
glEnableVertexAttribArray(static_cast<GLuint>(PRIM_VERTEX_ATTRIB::TEXCOORD));
glVertexAttribPointer(static_cast<GLuint>(PRIM_VERTEX_ATTRIB::TEXCOORD), 2, GL_FLOAT,
GL_FALSE, sizeof(float) * 4, reinterpret_cast<const GLvoid*>(8));
glBindVertexArray(0);
CHECKGLERROR();
return vertexArray;
}
Framework::OpenGl::CVertexArray CGSH_OpenGL::GeneratePrimVertexArray() Framework::OpenGl::CVertexArray CGSH_OpenGL::GeneratePrimVertexArray()
{ {
auto vertexArray = Framework::OpenGl::CVertexArray::Create(); auto vertexArray = Framework::OpenGl::CVertexArray::Create();
@ -1647,6 +1702,47 @@ void CGSH_OpenGL::DrawToDepth(unsigned int primitiveType, uint64 primReg)
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
} }
void CGSH_OpenGL::CopyToFb(
int32 srcX0, int32 srcY0, int32 srcX1, int32 srcY1,
int32 srcWidth, int32 srcHeight,
int32 dstX0, int32 dstY0, int32 dstX1, int32 dstY1)
{
m_validGlState &= ~(GLSTATE_BLEND | GLSTATE_COLORMASK | GLSTATE_SCISSOR | GLSTATE_PROGRAM);
m_validGlState &= ~(GLSTATE_VIEWPORT);
assert(srcX1 >= srcX0);
assert(srcY1 >= srcY0);
assert(dstX1 >= dstX0);
assert(dstY1 >= dstY0);
float positionX = static_cast<float>(srcX0) / static_cast<float>(srcWidth);
float positionY = static_cast<float>(srcY0) / static_cast<float>(srcHeight);
float sizeX = static_cast<float>(srcX1 - srcX0) / static_cast<float>(srcWidth);
float sizeY = static_cast<float>(srcY1 - srcY0) / static_cast<float>(srcHeight);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glUseProgram(*m_copyToFbProgram);
glUniform2f(m_copyToFbSrcPositionUniform, positionX, positionY);
glUniform2f(m_copyToFbSrcSizeUniform, sizeX, sizeY);
glViewport(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
glBindBuffer(GL_ARRAY_BUFFER, m_copyToFbVertexBuffer);
glBindVertexArray(m_copyToFbVertexArray);
#ifdef _DEBUG
m_copyToFbProgram->Validate();
#endif
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
CHECKGLERROR();
}
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// Other Functions // Other Functions
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
@ -2004,6 +2100,10 @@ void CGSH_OpenGL::PopulateFramebuffer(const FramebufferPtr& framebuffer)
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_copyToFbTexture); glBindTexture(GL_TEXTURE_2D, m_copyToFbTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
((this)->*(m_textureUploader[framebuffer->m_psm]))(framebuffer->m_basePtr, ((this)->*(m_textureUploader[framebuffer->m_psm]))(framebuffer->m_basePtr,
framebuffer->m_width / 64, framebuffer->m_width, framebuffer->m_height); framebuffer->m_width / 64, framebuffer->m_width, framebuffer->m_height);
CHECKGLERROR(); CHECKGLERROR();
@ -2015,6 +2115,8 @@ void CGSH_OpenGL::PopulateFramebuffer(const FramebufferPtr& framebuffer)
CHECKGLERROR(); CHECKGLERROR();
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->m_framebuffer);
#ifndef USE_COPYTOFB
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_copyToFbFramebuffer); glBindFramebuffer(GL_READ_FRAMEBUFFER, m_copyToFbFramebuffer);
//Copy buffers //Copy buffers
@ -2022,9 +2124,16 @@ void CGSH_OpenGL::PopulateFramebuffer(const FramebufferPtr& framebuffer)
0, 0, framebuffer->m_width, framebuffer->m_height, 0, 0, framebuffer->m_width, framebuffer->m_height,
0, 0, framebuffer->m_width * m_fbScale, framebuffer->m_height * m_fbScale, 0, 0, framebuffer->m_width * m_fbScale, framebuffer->m_height * m_fbScale,
GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT, GL_NEAREST);
CHECKGLERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#else
CopyToFb(
0, 0, framebuffer->m_width, framebuffer->m_height,
framebuffer->m_width, framebuffer->m_height,
0, 0, framebuffer->m_width, framebuffer->m_height);
framebuffer->m_resolveNeeded = true;
#endif
CHECKGLERROR();
} }
void CGSH_OpenGL::CommitFramebufferDirtyPages(const FramebufferPtr& framebuffer, unsigned int minY, unsigned int maxY) void CGSH_OpenGL::CommitFramebufferDirtyPages(const FramebufferPtr& framebuffer, unsigned int minY, unsigned int maxY)
@ -2047,6 +2156,10 @@ void CGSH_OpenGL::CommitFramebufferDirtyPages(const FramebufferPtr& framebuffer,
glBindTexture(GL_TEXTURE_2D, copyToFbTexture); glBindTexture(GL_TEXTURE_2D, copyToFbTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, framebuffer->m_width, framebuffer->m_height, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, framebuffer->m_width, framebuffer->m_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, copyToFbFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, copyToFbFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyToFbTexture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyToFbTexture, 0);
@ -2104,10 +2217,18 @@ void CGSH_OpenGL::CommitFramebufferDirtyPages(const FramebufferPtr& framebuffer,
((this)->*(m_textureUpdater[framebuffer->m_psm]))(framebuffer->m_basePtr, framebuffer->m_width / 64, ((this)->*(m_textureUpdater[framebuffer->m_psm]))(framebuffer->m_basePtr, framebuffer->m_width / 64,
texX, texY, texWidth, texHeight); texX, texY, texWidth, texHeight);
#ifndef USE_COPYTOFB
glBlitFramebuffer( glBlitFramebuffer(
texX, texY, (texX + texWidth), (texY + texHeight), texX, texY, (texX + texWidth), (texY + texHeight),
texX * m_fbScale, texY * m_fbScale, (texX + texWidth) * m_fbScale, (texY + texHeight) * m_fbScale, texX * m_fbScale, texY * m_fbScale, (texX + texWidth) * m_fbScale, (texY + texHeight) * m_fbScale,
GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT, GL_NEAREST);
#else
CopyToFb(
texX, texY, (texX + texWidth), (texY + texHeight),
framebuffer->m_width, framebuffer->m_height,
texX * m_fbScale, texY * m_fbScale, (texX + texWidth) * m_fbScale, (texY + texHeight) * m_fbScale);
framebuffer->m_resolveNeeded = true;
#endif
CHECKGLERROR(); CHECKGLERROR();
} }

View File

@ -288,6 +288,11 @@ private:
Framework::OpenGl::ProgramPtr GeneratePresentProgram(); Framework::OpenGl::ProgramPtr GeneratePresentProgram();
Framework::OpenGl::CBuffer GeneratePresentVertexBuffer(); Framework::OpenGl::CBuffer GeneratePresentVertexBuffer();
Framework::OpenGl::CVertexArray GeneratePresentVertexArray(); Framework::OpenGl::CVertexArray GeneratePresentVertexArray();
Framework::OpenGl::ProgramPtr GenerateCopyToFbProgram();
Framework::OpenGl::CBuffer GenerateCopyToFbVertexBuffer();
Framework::OpenGl::CVertexArray GenerateCopyToFbVertexArray();
Framework::OpenGl::CVertexArray GeneratePrimVertexArray(); Framework::OpenGl::CVertexArray GeneratePrimVertexArray();
Framework::OpenGl::CBuffer GenerateUniformBlockBuffer(size_t); Framework::OpenGl::CBuffer GenerateUniformBlockBuffer(size_t);
@ -298,6 +303,7 @@ private:
void FlushVertexBuffer(); void FlushVertexBuffer();
void CopyToFb(int32, int32, int32, int32, int32, int32, int32, int32, int32, int32);
void DrawToDepth(unsigned int, uint64); void DrawToDepth(unsigned int, uint64);
void SetRenderingContext(uint64); void SetRenderingContext(uint64);
@ -369,8 +375,13 @@ private:
GLint m_presentTextureUniform = -1; GLint m_presentTextureUniform = -1;
GLint m_presentTexCoordScaleUniform = -1; GLint m_presentTexCoordScaleUniform = -1;
Framework::OpenGl::ProgramPtr m_copyToFbProgram;
Framework::OpenGl::CFramebuffer m_copyToFbFramebuffer; Framework::OpenGl::CFramebuffer m_copyToFbFramebuffer;
Framework::OpenGl::CTexture m_copyToFbTexture; Framework::OpenGl::CTexture m_copyToFbTexture;
Framework::OpenGl::CBuffer m_copyToFbVertexBuffer;
Framework::OpenGl::CVertexArray m_copyToFbVertexArray;
GLint m_copyToFbSrcPositionUniform = -1;
GLint m_copyToFbSrcSizeUniform = -1;
TextureList m_textureCache; TextureList m_textureCache;
PaletteList m_paletteCache; PaletteList m_paletteCache;

View File

@ -446,3 +446,60 @@ Framework::OpenGl::ProgramPtr CGSH_OpenGL::GeneratePresentProgram()
return program; return program;
} }
Framework::OpenGl::ProgramPtr CGSH_OpenGL::GenerateCopyToFbProgram()
{
Framework::OpenGl::CShader vertexShader(GL_VERTEX_SHADER);
Framework::OpenGl::CShader pixelShader(GL_FRAGMENT_SHADER);
{
std::stringstream shaderBuilder;
shaderBuilder << GLSL_VERSION << std::endl;
shaderBuilder << "in vec2 a_position;" << std::endl;
shaderBuilder << "in vec2 a_texCoord;" << std::endl;
shaderBuilder << "out vec2 v_texCoord;" << std::endl;
shaderBuilder << "uniform vec2 g_srcPosition;" << std::endl;
shaderBuilder << "uniform vec2 g_srcSize;" << std::endl;
shaderBuilder << "void main()" << std::endl;
shaderBuilder << "{" << std::endl;
shaderBuilder << " v_texCoord = (a_texCoord * g_srcSize) + g_srcPosition;" << std::endl;
shaderBuilder << " gl_Position = vec4(a_position, 0, 1);" << std::endl;
shaderBuilder << "}" << std::endl;
vertexShader.SetSource(shaderBuilder.str().c_str());
bool result = vertexShader.Compile();
assert(result);
}
{
std::stringstream shaderBuilder;
shaderBuilder << GLSL_VERSION << std::endl;
shaderBuilder << "precision mediump float;" << std::endl;
shaderBuilder << "in vec2 v_texCoord;" << std::endl;
shaderBuilder << "out vec4 fragColor;" << std::endl;
shaderBuilder << "uniform sampler2D g_texture;" << std::endl;
shaderBuilder << "void main()" << std::endl;
shaderBuilder << "{" << std::endl;
shaderBuilder << " fragColor = texture(g_texture, v_texCoord);" << std::endl;
shaderBuilder << "}" << std::endl;
pixelShader.SetSource(shaderBuilder.str().c_str());
bool result = pixelShader.Compile();
assert(result);
}
auto program = std::make_shared<Framework::OpenGl::CProgram>();
{
program->AttachShader(vertexShader);
program->AttachShader(pixelShader);
glBindAttribLocation(*program, static_cast<GLuint>(PRIM_VERTEX_ATTRIB::POSITION), "a_position");
glBindAttribLocation(*program, static_cast<GLuint>(PRIM_VERTEX_ATTRIB::TEXCOORD), "a_texCoord");
bool result = program->Link();
assert(result);
}
return program;
}