From 0ae082fb617b548eddb800cfce41e214b334ed41 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 19 Dec 2014 15:02:17 +0100 Subject: [PATCH 1/3] FramebufferManager: Return the depth texture instead of the color texture in GetResolvedEFBDepthTexture() when AA is enabled. --- Source/Core/VideoBackends/D3D/FramebufferManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index a1b66dc3e7..e1f297271d 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -40,8 +40,8 @@ D3DTexture2D* &FramebufferManager::GetResolvedEFBDepthTexture() { if (g_ActiveConfig.iMultisampleMode) { - D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); - return m_efb.resolved_color_tex; + D3D::context->ResolveSubresource(m_efb.resolved_depth_tex->GetTex(), 0, m_efb.depth_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); + return m_efb.resolved_depth_tex; } else return m_efb.depth_tex; From 761749e07fc251e4ea946a5c900e04c4229aff86 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 19 Dec 2014 15:51:14 +0100 Subject: [PATCH 2/3] FramebufferManager: Support resolving a multi-layered EFB in D3D. --- .../VideoBackends/D3D/FramebufferManager.cpp | 6 +- .../VideoBackends/OGL/FramebufferManager.cpp | 59 +++++++++++++------ 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index e1f297271d..d4d620320a 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -29,7 +29,8 @@ D3DTexture2D* &FramebufferManager::GetResolvedEFBColorTexture() { if (g_ActiveConfig.iMultisampleMode) { - D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); + for (int i = 0; i < m_efb.slices; i++) + D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), D3D11CalcSubresource(0, i, 1), m_efb.color_tex->GetTex(), D3D11CalcSubresource(0, i, 1), DXGI_FORMAT_R8G8B8A8_UNORM); return m_efb.resolved_color_tex; } else @@ -40,7 +41,8 @@ D3DTexture2D* &FramebufferManager::GetResolvedEFBDepthTexture() { if (g_ActiveConfig.iMultisampleMode) { - D3D::context->ResolveSubresource(m_efb.resolved_depth_tex->GetTex(), 0, m_efb.depth_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); + for (int i = 0; i < m_efb.slices; i++) + D3D::context->ResolveSubresource(m_efb.resolved_depth_tex->GetTex(), D3D11CalcSubresource(0, i, 1), m_efb.depth_tex->GetTex(), D3D11CalcSubresource(0, i, 1), DXGI_FORMAT_R8G8B8A8_UNORM); return m_efb.resolved_depth_tex; } else diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 1089884b96..2567641595 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -99,17 +99,17 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms } else { - m_textureType = GL_TEXTURE_2D_MULTISAMPLE; + m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; GLenum resolvedType = GL_TEXTURE_2D_ARRAY; glBindTexture(m_textureType, m_efbColor); - glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false); + glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbDepth); - glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, false); + glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbColorSwap); - glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false); + glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, 0); // Although we are able to access the multisampled texture directly, we don't do it everywhere. @@ -180,25 +180,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 + From d37b65c1176ae661210282be772101e20b0240a2 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 19 Dec 2014 19:45:53 +0100 Subject: [PATCH 3/3] FramebufferManager: Support resolving a multi-layered EFB in OGL. --- .../VideoBackends/OGL/FramebufferManager.cpp | 120 ++++++++++++------ .../VideoBackends/OGL/FramebufferManager.h | 8 +- 2 files changed, 86 insertions(+), 42 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; } diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.h b/Source/Core/VideoBackends/OGL/FramebufferManager.h index 8d42523bcc..ffc2970ee6 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.h +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.h @@ -68,11 +68,11 @@ public: static GLuint GetEFBColorTexture(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; } // 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 FramebufferTexture(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); @@ -102,14 +102,14 @@ private: static int m_msaaSamples; static GLenum m_textureType; - static GLuint m_efbFramebuffer; + static GLuint* m_efbFramebuffer; static GLuint m_xfbFramebuffer; static GLuint m_efbColor; static GLuint m_efbDepth; 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 - static GLuint m_resolvedFramebuffer; + static GLuint* m_resolvedFramebuffer; static GLuint m_resolvedColorTexture; static GLuint m_resolvedDepthTexture;