summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/FramebufferManager.cpp171
1 files changed, 120 insertions, 51 deletions
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
index 1089884b96..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;
GLenum resolvedType = GL_TEXTURE_2D_ARRAY;
- glBindTexture(m_textureType, m_efbColor);
- glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, 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);
- glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 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);
- glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, 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);
@@ -180,25 +216,50 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// msaa + sample shading available, so just fetch the sample
// This will lead to sample shading, but it's the only way to not loose
// the values of each sample.
- sampler =
- "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n"
- "vec4 sampleEFB(ivec2 pos) {\n"
- " return texelFetch(samp9, pos, gl_SampleID);\n"
- "}\n";
+ if (m_EFBLayers > 1)
+ {
+ sampler =
+ "SAMPLER_BINDING(9) uniform sampler2DMSArray samp9;\n"
+ "vec4 sampleEFB(ivec2 pos) {\n"
+ " return texelFetch(samp9, ivec3(pos, 0), gl_SampleID);\n"
+ "}\n";
+ }
+ else
+ {
+ sampler =
+ "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n"
+ "vec4 sampleEFB(ivec2 pos) {\n"
+ " return texelFetch(samp9, pos, gl_SampleID);\n"
+ "}\n";
+ }
}
else
{
// msaa without sample shading: calculate the mean value of the pixel
std::stringstream samples;
samples << m_msaaSamples;
- sampler =
- "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n"
- "vec4 sampleEFB(ivec2 pos) {\n"
- " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n"
- " for(int i=0; i<" + samples.str() + "; i++)\n"
- " color += texelFetch(samp9, pos, i);\n"
- " return color / " + samples.str() + ";\n"
- "}\n";
+ if (m_EFBLayers > 1)
+ {
+ sampler =
+ "SAMPLER_BINDING(9) uniform sampler2DMSArray samp9;\n"
+ "vec4 sampleEFB(ivec2 pos) {\n"
+ " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " for(int i=0; i<" + samples.str() + "; i++)\n"
+ " color += texelFetch(samp9, ivec3(pos, 0), i);\n"
+ " return color / " + samples.str() + ";\n"
+ "}\n";
+ }
+ else
+ {
+ sampler =
+ "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n"
+ "vec4 sampleEFB(ivec2 pos) {\n"
+ " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " for(int i=0; i<" + samples.str() + "; i++)\n"
+ " color += texelFetch(samp9, pos, i);\n"
+ " return color / " + samples.str() + ";\n"
+ "}\n";
+ }
}
std::string ps_rgba6_to_rgb8 = sampler +
@@ -239,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;
@@ -281,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;
}
@@ -310,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;
}