FramebufferManager: Support resolving a multi-layered EFB in OGL.

This commit is contained in:
Jules Blok 2014-12-19 19:45:53 +01:00
parent 761749e07f
commit d37b65c117
2 changed files with 86 additions and 42 deletions

View File

@ -21,14 +21,14 @@ int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples; int FramebufferManager::m_msaaSamples;
GLenum FramebufferManager::m_textureType; GLenum FramebufferManager::m_textureType;
GLuint FramebufferManager::m_efbFramebuffer; GLuint* FramebufferManager::m_efbFramebuffer;
GLuint FramebufferManager::m_xfbFramebuffer; GLuint FramebufferManager::m_xfbFramebuffer;
GLuint FramebufferManager::m_efbColor; GLuint FramebufferManager::m_efbColor;
GLuint FramebufferManager::m_efbDepth; GLuint FramebufferManager::m_efbDepth;
GLuint FramebufferManager::m_efbColorSwap; // for hot swap when reinterpreting EFB pixel formats GLuint FramebufferManager::m_efbColorSwap; // for hot swap when reinterpreting EFB pixel formats
// Only used in MSAA mode. // Only used in MSAA mode.
GLuint FramebufferManager::m_resolvedFramebuffer; GLuint* FramebufferManager::m_resolvedFramebuffer;
GLuint FramebufferManager::m_resolvedColorTexture; GLuint FramebufferManager::m_resolvedColorTexture;
GLuint FramebufferManager::m_resolvedDepthTexture; GLuint FramebufferManager::m_resolvedDepthTexture;
@ -38,12 +38,10 @@ SHADER FramebufferManager::m_pixel_format_shaders[2];
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples)
{ {
m_efbFramebuffer = 0;
m_xfbFramebuffer = 0; m_xfbFramebuffer = 0;
m_efbColor = 0; m_efbColor = 0;
m_efbDepth = 0; m_efbDepth = 0;
m_efbColorSwap = 0; m_efbColorSwap = 0;
m_resolvedFramebuffer = 0;
m_resolvedColorTexture = 0; m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0; m_resolvedDepthTexture = 0;
@ -72,6 +70,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_efbColorSwap = glObj[2]; m_efbColorSwap = glObj[2];
m_EFBLayers = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1; m_EFBLayers = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1;
m_efbFramebuffer = new GLuint[m_EFBLayers]();
m_resolvedFramebuffer = new GLuint[m_EFBLayers]();
// OpenGL MSAA textures are a different kind of texture type and must be allocated // OpenGL MSAA textures are a different kind of texture type and must be allocated
// with a different function, so we create them separately. // with a different function, so we create them separately.
@ -99,18 +99,38 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
} }
else else
{ {
m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
GLenum resolvedType = GL_TEXTURE_2D_ARRAY; GLenum resolvedType = GL_TEXTURE_2D_ARRAY;
glBindTexture(m_textureType, m_efbColor); // Only use a layered multisample texture if needed. Some drivers
glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); // slow down significantly with single-layered multisample textures.
if (m_EFBLayers > 1)
{
m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
glBindTexture(m_textureType, m_efbDepth); glBindTexture(m_textureType, m_efbColor);
glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, false); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false);
glBindTexture(m_textureType, m_efbColorSwap); glBindTexture(m_textureType, m_efbDepth);
glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, false);
glBindTexture(m_textureType, 0);
glBindTexture(m_textureType, m_efbColorSwap);
glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false);
glBindTexture(m_textureType, 0);
}
else
{
m_textureType = GL_TEXTURE_2D_MULTISAMPLE;
glBindTexture(m_textureType, m_efbColor);
glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false);
glBindTexture(m_textureType, m_efbDepth);
glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, false);
glBindTexture(m_textureType, m_efbColorSwap);
glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false);
glBindTexture(m_textureType, 0);
}
// Although we are able to access the multisampled texture directly, we don't do it everywhere. // Although we are able to access the multisampled texture directly, we don't do it everywhere.
// The old way is to "resolve" this multisampled texture by copying it into a non-sampled texture. // The old way is to "resolve" this multisampled texture by copying it into a non-sampled texture.
@ -133,21 +153,37 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glTexImage3D(resolvedType, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glTexImage3D(resolvedType, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
// Bind resolved textures to resolved framebuffer. // Bind resolved textures to resolved framebuffer.
glGenFramebuffers(1, &m_resolvedFramebuffer); glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[0]);
FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolvedType, m_resolvedColorTexture, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolvedType, m_resolvedColorTexture, 0);
FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, resolvedType, m_resolvedDepthTexture, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, resolvedType, m_resolvedDepthTexture, 0);
// Bind all the other layers as separate FBOs for blitting.
for (unsigned int i = 1; i < m_EFBLayers; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[i]);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_resolvedColorTexture, 0, i);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_resolvedDepthTexture, 0, i);
}
} }
// Create XFB framebuffer; targets will be created elsewhere. // Create XFB framebuffer; targets will be created elsewhere.
glGenFramebuffers(1, &m_xfbFramebuffer); glGenFramebuffers(1, &m_xfbFramebuffer);
// Bind target textures to EFB framebuffer. // Bind target textures to EFB framebuffer.
glGenFramebuffers(1, &m_efbFramebuffer); glGenFramebuffers(m_EFBLayers, m_efbFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textureType, m_efbColor, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textureType, m_efbColor, 0);
FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_textureType, m_efbDepth, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_textureType, m_efbDepth, 0);
// Bind all the other layers as separate FBOs for blitting.
for (unsigned int i = 1; i < m_EFBLayers; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[i]);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_efbColor, 0, i);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_efbDepth, 0, i);
}
// EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f // EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f
glViewport(0, 0, m_targetWidth, m_targetHeight); glViewport(0, 0, m_targetWidth, m_targetHeight);
glScissor(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight);
@ -264,13 +300,15 @@ FramebufferManager::~FramebufferManager()
// Note: OpenGL deletion functions silently ignore parameters of "0". // Note: OpenGL deletion functions silently ignore parameters of "0".
glObj[0] = m_efbFramebuffer; glDeleteFramebuffers(m_EFBLayers, m_efbFramebuffer);
glObj[1] = m_xfbFramebuffer; glDeleteFramebuffers(m_EFBLayers, m_resolvedFramebuffer);
glObj[2] = m_resolvedFramebuffer; delete [] m_efbFramebuffer;
glDeleteFramebuffers(3, glObj); delete [] m_resolvedFramebuffer;
m_efbFramebuffer = 0; m_efbFramebuffer = nullptr;
m_resolvedFramebuffer = nullptr;
glDeleteFramebuffers(1, &m_xfbFramebuffer);
m_xfbFramebuffer = 0; m_xfbFramebuffer = 0;
m_resolvedFramebuffer = 0;
glObj[0] = m_resolvedColorTexture; glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture; glObj[1] = m_resolvedDepthTexture;
@ -306,16 +344,19 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight); targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve. // Resolve.
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer); for (unsigned int i = 0; i < m_EFBLayers; i++)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer); {
glBlitFramebuffer( glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer[i]);
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer[i]);
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, glBlitFramebuffer(
GL_COLOR_BUFFER_BIT, GL_NEAREST targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
); targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
}
// Return to EFB. // Return to EFB.
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
return m_resolvedColorTexture; return m_resolvedColorTexture;
} }
@ -335,16 +376,19 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight); targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve. // Resolve.
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer); for (unsigned int i = 0; i < m_EFBLayers; i++)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer); {
glBlitFramebuffer( glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer[i]);
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer[i]);
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, glBlitFramebuffer(
GL_DEPTH_BUFFER_BIT, GL_NEAREST targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
); targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
}
// Return to EFB. // Return to EFB.
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
return m_resolvedDepthTexture; return m_resolvedDepthTexture;
} }

View File

@ -68,11 +68,11 @@ public:
static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc); static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc);
static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc); static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc);
static GLuint GetEFBFramebuffer() { return m_efbFramebuffer; } static GLuint GetEFBFramebuffer() { return m_efbFramebuffer[0]; }
static GLuint GetXFBFramebuffer() { return m_xfbFramebuffer; } static GLuint GetXFBFramebuffer() { return m_xfbFramebuffer; }
// Resolved framebuffer is only used in MSAA mode. // Resolved framebuffer is only used in MSAA mode.
static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer; } static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer[0]; }
static void SetFramebuffer(GLuint fb); static void SetFramebuffer(GLuint fb);
static void FramebufferTexture(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); static void FramebufferTexture(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
@ -102,14 +102,14 @@ private:
static int m_msaaSamples; static int m_msaaSamples;
static GLenum m_textureType; static GLenum m_textureType;
static GLuint m_efbFramebuffer; static GLuint* m_efbFramebuffer;
static GLuint m_xfbFramebuffer; static GLuint m_xfbFramebuffer;
static GLuint m_efbColor; static GLuint m_efbColor;
static GLuint m_efbDepth; static GLuint m_efbDepth;
static GLuint m_efbColorSwap;// will be hot swapped with m_efbColor when reinterpreting EFB pixel formats static GLuint m_efbColorSwap;// will be hot swapped with m_efbColor when reinterpreting EFB pixel formats
// Only used in MSAA mode, TODO: try to avoid them // Only used in MSAA mode, TODO: try to avoid them
static GLuint m_resolvedFramebuffer; static GLuint* m_resolvedFramebuffer;
static GLuint m_resolvedColorTexture; static GLuint m_resolvedColorTexture;
static GLuint m_resolvedDepthTexture; static GLuint m_resolvedDepthTexture;