From 69cedf4144293153d0b40749ae178501db529c89 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Thu, 9 Mar 2017 14:14:47 -0800 Subject: extract OGL::FramebufferManager::CreateTexture --- .../Core/VideoBackends/OGL/FramebufferManager.cpp | 150 +++++++-------------- 1 file changed, 47 insertions(+), 103 deletions(-) (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp') diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 45a4b196a0..144fa20d36 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -12,6 +12,7 @@ #include "Common/CommonTypes.h" #include "Common/GL/GLInterfaceBase.h" #include "Common/Logging/Log.h" +#include "Common/MsgHandler.h" #include "Core/HW/Memmap.h" @@ -49,6 +50,44 @@ GLuint FramebufferManager::m_EfbPokes_VBO; GLuint FramebufferManager::m_EfbPokes_VAO; SHADER FramebufferManager::m_EfbPokes; +GLuint FramebufferManager::CreateTexture(GLenum texture_type, GLenum internal_format, + GLenum pixel_format, GLenum data_type) +{ + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(texture_type, texture); + if (texture_type == GL_TEXTURE_2D_ARRAY) + { + glTexParameteri(texture_type, GL_TEXTURE_MAX_LEVEL, 0); + glTexImage3D(texture_type, 0, internal_format, m_targetWidth, m_targetHeight, m_EFBLayers, 0, + pixel_format, data_type, nullptr); + } + else if (texture == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + { + if (g_ogl_config.bSupports3DTextureStorage) + glTexStorage3DMultisample(texture_type, m_msaaSamples, internal_format, m_targetWidth, + m_targetHeight, m_EFBLayers, false); + else + glTexImage3DMultisample(texture_type, m_msaaSamples, internal_format, m_targetWidth, + m_targetHeight, m_EFBLayers, false); + } + else if (texture == GL_TEXTURE_2D_MULTISAMPLE) + { + if (g_ogl_config.bSupports2DTextureStorage) + glTexStorage2DMultisample(texture_type, m_msaaSamples, internal_format, m_targetWidth, + m_targetHeight, false); + else + glTexImage2DMultisample(texture_type, m_msaaSamples, internal_format, m_targetWidth, + m_targetHeight, false); + } + else + { + PanicAlert("Unhandled texture type %d", texture_type); + } + glBindTexture(texture_type, 0); + return texture; +} + FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) { m_xfbFramebuffer = 0; @@ -76,132 +115,33 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glActiveTexture(GL_TEXTURE9); - GLuint glObj[3]; - glGenTextures(3, glObj); - m_efbColor = glObj[0]; - m_efbDepth = glObj[1]; - m_efbColorSwap = glObj[2]; - m_EFBLayers = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1; m_efbFramebuffer.resize(m_EFBLayers); m_resolvedFramebuffer.resize(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. if (m_msaaSamples <= 1) { m_textureType = GL_TEXTURE_2D_ARRAY; - - glBindTexture(m_textureType, m_efbColor); - glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); - - glBindTexture(m_textureType, m_efbDepth); - glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage3D(m_textureType, 0, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, - m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); - - glBindTexture(m_textureType, m_efbColorSwap); - glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); } else { - GLenum resolvedType = GL_TEXTURE_2D_ARRAY; - // 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; - - if (g_ogl_config.bSupports3DTextureStorage) - { - glBindTexture(m_textureType, m_efbColor); - glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, - m_targetHeight, m_EFBLayers, false); - - glBindTexture(m_textureType, m_efbDepth); - glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, - m_targetWidth, m_targetHeight, m_EFBLayers, false); - - glBindTexture(m_textureType, m_efbColorSwap); - glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, - m_targetHeight, m_EFBLayers, false); - glBindTexture(m_textureType, 0); - } - else - { - glBindTexture(m_textureType, m_efbColor); - glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, - m_targetHeight, m_EFBLayers, false); - - glBindTexture(m_textureType, m_efbDepth); - glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, 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; - if (g_ogl_config.bSupports2DTextureStorage) - { - glBindTexture(m_textureType, m_efbColor); - glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, - m_targetHeight, false); - - glBindTexture(m_textureType, m_efbDepth); - glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, - m_targetWidth, m_targetHeight, false); - - glBindTexture(m_textureType, m_efbColorSwap); - glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, - m_targetHeight, false); - glBindTexture(m_textureType, 0); - } - else - { - 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_COMPONENT32F, 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. // This would lead to an unneeded copy of the EFB, so we are going to avoid it. // But as this job isn't done right now, we do need that texture for resolving: - glGenTextures(2, glObj); - m_resolvedColorTexture = glObj[0]; - m_resolvedDepthTexture = glObj[1]; - - glBindTexture(resolvedType, m_resolvedColorTexture); - glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage3D(resolvedType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); + GLenum resolvedType = GL_TEXTURE_2D_ARRAY; - glBindTexture(resolvedType, m_resolvedDepthTexture); - glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage3D(resolvedType, 0, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, - 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + m_resolvedColorTexture = CreateTexture(resolvedType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); + m_resolvedDepthTexture = + CreateTexture(resolvedType, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); // Bind resolved textures to resolved framebuffer. glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); @@ -220,6 +160,10 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms } } + m_efbColor = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); + m_efbDepth = CreateTexture(m_textureType, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); + m_efbColorSwap = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); + // Create XFB framebuffer; targets will be created elsewhere. glGenFramebuffers(1, &m_xfbFramebuffer); -- cgit v1.2.3 From 56fe938366950062984e11364af5ce1ffe474f27 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Thu, 9 Mar 2017 14:55:31 -0800 Subject: extract OGL::FramebufferManager::BindLayeredTexture --- .../Core/VideoBackends/OGL/FramebufferManager.cpp | 42 +++++++++------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp') diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 144fa20d36..001cbb59fc 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -88,6 +88,17 @@ GLuint FramebufferManager::CreateTexture(GLenum texture_type, GLenum internal_fo return texture; } +void FramebufferManager::BindLayeredTexture(GLuint texture, const std::vector& framebuffers, GLenum attachment, GLenum texture_type) +{ + glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]); + FramebufferTexture(GL_FRAMEBUFFER, attachment, texture_type, texture, 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, attachment, texture, 0, i); + } +} + FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) { m_xfbFramebuffer = 0; @@ -145,23 +156,13 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms // Bind resolved textures to resolved framebuffer. glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); - 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); - } + BindLayeredTexture(m_resolvedColorTexture, m_resolvedFramebuffer, GL_COLOR_ATTACHMENT0, resolvedType); + BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_DEPTH_ATTACHMENT, resolvedType); } m_efbColor = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); - m_efbDepth = CreateTexture(m_textureType, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); + m_efbDepth = CreateTexture(m_textureType, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV); m_efbColorSwap = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); // Create XFB framebuffer; targets will be created elsewhere. @@ -169,17 +170,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms // Bind target textures to EFB framebuffer. glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data()); - 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); - } + BindLayeredTexture(m_efbColor, m_efbFramebuffer, GL_COLOR_ATTACHMENT0, m_textureType); + BindLayeredTexture(m_efbDepth, m_efbFramebuffer, GL_DEPTH_ATTACHMENT, m_textureType); // EFB framebuffer is currently bound, make sure to clear it before use. glViewport(0, 0, m_targetWidth, m_targetHeight); -- cgit v1.2.3 From ba6e917b49fcb192bc658557742106e29159dff7 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Sun, 5 Mar 2017 15:34:30 -0800 Subject: OGL: implement Bounding Box on systems w/o SSBO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit should have zero performance effect if SSBOs are supported. If they aren't (e.g. on all Macs), this commit alters FramebufferManager to attach a new stencil buffer and VertexManager to draw to it when bounding box is active. `BBoxRead` gets the pixel data from the buffer and dumbly loops through it to find the bounding box. This patch can run Paper Mario: The Thousand-Year Door at almost full speed (50–60 FPS) without Dual-Core enabled for all common bounding box-using actions I tested (going through pipes, Plane Mode, Paper Mode, Prof. Frankly's gate, combat, walking around the overworld, etc.) on my computer (macOS 10.12.3, 2.8 GHz Intel Core i7, 16 GB 1600 MHz DDR3, and Intel Iris 1536 MB). A few more demanding scenes (e.g. the self-building bridge on the way to Petalburg) slow to ~15% of their speed without this patch (though they don't run quite at full speed even on master). The slowdown is caused almost solely by `glReadPixels` in `OGL::BoundingBox::Get`. Other implementation ideas: - Use a stencil buffer that's separate from the depth buffer. This would require ARB_texture_stencil8 / OpenGL 4.4, which isn't available on macOS. - Use `glGetTexImage` instead of `glReadPixels`. This is ~5 FPS slower on my computer, presumably because it has to transfer the entire combined depth-stencil buffer instead of only the stencil data. Getting only stencil data from `glGetTexImage` requires ARB_texture_stencil8 / OpenGL 4.4, which (again) is not available on macOS. - Don't use a PBO, and use `glReadPixels` synchronously. This has no visible performance effect on my computer, and is theoretically slower. --- .../Core/VideoBackends/OGL/FramebufferManager.cpp | 32 ++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp') diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 001cbb59fc..13b6759a01 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -152,12 +152,13 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms m_resolvedColorTexture = CreateTexture(resolvedType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); m_resolvedDepthTexture = - CreateTexture(resolvedType, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); + CreateTexture(resolvedType, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV); // Bind resolved textures to resolved framebuffer. glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); BindLayeredTexture(m_resolvedColorTexture, m_resolvedFramebuffer, GL_COLOR_ATTACHMENT0, resolvedType); BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_DEPTH_ATTACHMENT, resolvedType); + BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_STENCIL_ATTACHMENT, resolvedType); } m_efbColor = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); @@ -172,13 +173,15 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data()); BindLayeredTexture(m_efbColor, m_efbFramebuffer, GL_COLOR_ATTACHMENT0, m_textureType); BindLayeredTexture(m_efbDepth, m_efbFramebuffer, GL_DEPTH_ATTACHMENT, m_textureType); + BindLayeredTexture(m_efbDepth, m_efbFramebuffer, GL_STENCIL_ATTACHMENT, m_textureType); // EFB framebuffer is currently bound, make sure to clear it before use. glViewport(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight); glClearColor(0.f, 0.f, 0.f, 0.f); glClearDepthf(1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearStencil(0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // reinterpret pixel format const char* vs = m_EFBLayers > 1 ? "void main(void) {\n" @@ -478,6 +481,24 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc) } } +void FramebufferManager::ResolveEFBStencilTexture() +{ + if (m_msaaSamples <= 1) + return; + + // Resolve. + for (unsigned int i = 0; i < m_EFBLayers; i++) + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer[i]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer[i]); + glBlitFramebuffer(0, 0, m_targetWidth, m_targetHeight, 0, 0, m_targetWidth, m_targetHeight, + GL_STENCIL_BUFFER_BIT, GL_NEAREST); + } + + // Return to EFB. + glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]); +} + void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { @@ -493,6 +514,13 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, sourceRc.GetWidth(), fbStride, fbHeight); } +GLuint FramebufferManager::GetResolvedFramebuffer() +{ + if (m_msaaSamples <= 1) + return m_efbFramebuffer[0]; + return m_resolvedFramebuffer[0]; +} + void FramebufferManager::SetFramebuffer(GLuint fb) { glBindFramebuffer(GL_FRAMEBUFFER, fb != 0 ? fb : GetEFBFramebuffer()); -- cgit v1.2.3 From 53224d41d05a9ec70d0a2715e1a7601a0e60bb14 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Thu, 9 Mar 2017 15:33:10 -0800 Subject: OGL: only create stencil buffer when needed --- .../Core/VideoBackends/OGL/FramebufferManager.cpp | 54 ++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp') diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 13b6759a01..17244db24e 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -29,6 +29,7 @@ namespace OGL int FramebufferManager::m_targetWidth; int FramebufferManager::m_targetHeight; int FramebufferManager::m_msaaSamples; +bool FramebufferManager::m_enable_stencil_buffer; GLenum FramebufferManager::m_textureType; std::vector FramebufferManager::m_efbFramebuffer; @@ -88,18 +89,26 @@ GLuint FramebufferManager::CreateTexture(GLenum texture_type, GLenum internal_fo return texture; } -void FramebufferManager::BindLayeredTexture(GLuint texture, const std::vector& framebuffers, GLenum attachment, GLenum texture_type) +void FramebufferManager::BindLayeredTexture(GLuint texture, const std::vector& framebuffers, + GLenum attachment, GLenum texture_type) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]); FramebufferTexture(GL_FRAMEBUFFER, attachment, texture_type, texture, 0); // Bind all the other layers as separate FBOs for blitting. - for (unsigned int i = 1; i < m_EFBLayers; i++) { + for (unsigned int i = 1; i < m_EFBLayers; i++) + { glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[i]); glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, texture, 0, i); } } -FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) +bool FramebufferManager::HasStencilBuffer() +{ + return m_enable_stencil_buffer; +} + +FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, + bool enable_stencil_buffer) { m_xfbFramebuffer = 0; m_efbColor = 0; @@ -110,8 +119,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms m_targetWidth = targetWidth; m_targetHeight = targetHeight; - m_msaaSamples = msaaSamples; + m_enable_stencil_buffer = enable_stencil_buffer; // The EFB can be set to different pixel formats by the game through the // BPMEM_ZCOMPARE register (which should probably have a different name). @@ -130,6 +139,16 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms m_efbFramebuffer.resize(m_EFBLayers); m_resolvedFramebuffer.resize(m_EFBLayers); + GLenum depth_internal_format = GL_DEPTH_COMPONENT32F; + GLenum depth_pixel_format = GL_DEPTH_COMPONENT; + GLenum depth_data_type = GL_FLOAT; + if (m_enable_stencil_buffer) + { + depth_internal_format = GL_DEPTH32F_STENCIL8; + depth_pixel_format = GL_DEPTH_STENCIL; + depth_data_type = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + } + if (m_msaaSamples <= 1) { m_textureType = GL_TEXTURE_2D_ARRAY; @@ -152,18 +171,22 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms m_resolvedColorTexture = CreateTexture(resolvedType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); m_resolvedDepthTexture = - CreateTexture(resolvedType, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + CreateTexture(resolvedType, depth_internal_format, depth_pixel_format, depth_data_type); // Bind resolved textures to resolved framebuffer. glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); - BindLayeredTexture(m_resolvedColorTexture, m_resolvedFramebuffer, GL_COLOR_ATTACHMENT0, resolvedType); - BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_DEPTH_ATTACHMENT, resolvedType); - BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_STENCIL_ATTACHMENT, resolvedType); + BindLayeredTexture(m_resolvedColorTexture, m_resolvedFramebuffer, GL_COLOR_ATTACHMENT0, + resolvedType); + BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_DEPTH_ATTACHMENT, + resolvedType); + if (m_enable_stencil_buffer) + BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_STENCIL_ATTACHMENT, + resolvedType); } m_efbColor = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); - m_efbDepth = CreateTexture(m_textureType, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, - GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + m_efbDepth = + CreateTexture(m_textureType, depth_internal_format, depth_pixel_format, depth_data_type); m_efbColorSwap = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); // Create XFB framebuffer; targets will be created elsewhere. @@ -173,15 +196,20 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data()); BindLayeredTexture(m_efbColor, m_efbFramebuffer, GL_COLOR_ATTACHMENT0, m_textureType); BindLayeredTexture(m_efbDepth, m_efbFramebuffer, GL_DEPTH_ATTACHMENT, m_textureType); - BindLayeredTexture(m_efbDepth, m_efbFramebuffer, GL_STENCIL_ATTACHMENT, m_textureType); + if (m_enable_stencil_buffer) + BindLayeredTexture(m_efbDepth, m_efbFramebuffer, GL_STENCIL_ATTACHMENT, m_textureType); // EFB framebuffer is currently bound, make sure to clear it before use. glViewport(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight); glClearColor(0.f, 0.f, 0.f, 0.f); glClearDepthf(1.0f); - glClearStencil(0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (m_enable_stencil_buffer) + { + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + } // reinterpret pixel format const char* vs = m_EFBLayers > 1 ? "void main(void) {\n" -- cgit v1.2.3