summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
diff options
context:
space:
mode:
authorJules Blok <jules.blok@gmail.com>2014-12-19 19:45:53 +0100
committerJules Blok <jules.blok@gmail.com>2014-12-20 16:08:00 +0100
commitd37b65c1176ae661210282be772101e20b0240a2 (patch)
tree0c6fe1eaf31b7a7da1e908eb21a193a788efffc2 /Source/Core/VideoBackends/OGL/FramebufferManager.cpp
parent761749e07fc251e4ea946a5c900e04c4229aff86 (diff)
FramebufferManager: Support resolving a multi-layered EFB in OGL.
Diffstat (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/FramebufferManager.cpp120
1 files changed, 82 insertions, 38 deletions
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
index 2567641595..e9d2ba7294 100644
--- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
@@ -21,14 +21,14 @@ int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples;
GLenum FramebufferManager::m_textureType;
-GLuint FramebufferManager::m_efbFramebuffer;
+GLuint* FramebufferManager::m_efbFramebuffer;
GLuint FramebufferManager::m_xfbFramebuffer;
GLuint FramebufferManager::m_efbColor;
GLuint FramebufferManager::m_efbDepth;
GLuint FramebufferManager::m_efbColorSwap; // for hot swap when reinterpreting EFB pixel formats
// Only used in MSAA mode.
-GLuint FramebufferManager::m_resolvedFramebuffer;
+GLuint* FramebufferManager::m_resolvedFramebuffer;
GLuint FramebufferManager::m_resolvedColorTexture;
GLuint FramebufferManager::m_resolvedDepthTexture;
@@ -38,12 +38,10 @@ SHADER FramebufferManager::m_pixel_format_shaders[2];
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples)
{
- m_efbFramebuffer = 0;
m_xfbFramebuffer = 0;
m_efbColor = 0;
m_efbDepth = 0;
m_efbColorSwap = 0;
- m_resolvedFramebuffer = 0;
m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0;
@@ -72,6 +70,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_efbColorSwap = glObj[2];
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
// with a different function, so we create them separately.
@@ -99,18 +99,38 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
}
else
{
- m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
GLenum resolvedType = GL_TEXTURE_2D_ARRAY;
- glBindTexture(m_textureType, m_efbColor);
- glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false);
+ // Only use a layered multisample texture if needed. Some drivers
+ // slow down significantly with single-layered multisample textures.
+ if (m_EFBLayers > 1)
+ {
+ m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
- glBindTexture(m_textureType, m_efbDepth);
- glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, false);
+ glBindTexture(m_textureType, m_efbColor);
+ glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false);
- glBindTexture(m_textureType, m_efbColorSwap);
- glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false);
- glBindTexture(m_textureType, 0);
+ glBindTexture(m_textureType, m_efbDepth);
+ glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, false);
+
+ 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.
// 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);
// Bind resolved textures to resolved framebuffer.
- glGenFramebuffers(1, &m_resolvedFramebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer);
+ glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[0]);
FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolvedType, m_resolvedColorTexture, 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.
glGenFramebuffers(1, &m_xfbFramebuffer);
// Bind target textures to EFB framebuffer.
- glGenFramebuffers(1, &m_efbFramebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
+ glGenFramebuffers(m_EFBLayers, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textureType, m_efbColor, 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
glViewport(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".
- glObj[0] = m_efbFramebuffer;
- glObj[1] = m_xfbFramebuffer;
- glObj[2] = m_resolvedFramebuffer;
- glDeleteFramebuffers(3, glObj);
- m_efbFramebuffer = 0;
+ glDeleteFramebuffers(m_EFBLayers, m_efbFramebuffer);
+ glDeleteFramebuffers(m_EFBLayers, m_resolvedFramebuffer);
+ delete [] m_efbFramebuffer;
+ delete [] m_resolvedFramebuffer;
+ m_efbFramebuffer = nullptr;
+ m_resolvedFramebuffer = nullptr;
+
+ glDeleteFramebuffers(1, &m_xfbFramebuffer);
m_xfbFramebuffer = 0;
- m_resolvedFramebuffer = 0;
glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture;
@@ -306,16 +344,19 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
- glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
- glBlitFramebuffer(
- targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
- targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
- GL_COLOR_BUFFER_BIT, GL_NEAREST
- );
+ for (unsigned int i = 0; i < m_EFBLayers; i++)
+ {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer[i]);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer[i]);
+ glBlitFramebuffer(
+ 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.
- glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
return m_resolvedColorTexture;
}
@@ -335,16 +376,19 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
- glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
- glBlitFramebuffer(
- targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
- targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
- GL_DEPTH_BUFFER_BIT, GL_NEAREST
- );
+ for (unsigned int i = 0; i < m_EFBLayers; i++)
+ {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer[i]);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer[i]);
+ glBlitFramebuffer(
+ 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.
- glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
return m_resolvedDepthTexture;
}