diff options
| author | Markus Wick <degasus@users.noreply.github.com> | 2017-03-16 21:39:17 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-16 21:39:17 +0100 |
| commit | a0acdfc070d5bed422d3cdafd7675fc28af4eed5 (patch) | |
| tree | 0edd5873022cafad1caf3c9588ae6fda8e201d75 /Source/Core/VideoBackends/OGL/FramebufferManager.cpp | |
| parent | b2ab713ad93f8734fc65e104f4dc6c1c9a3e9411 (diff) | |
| parent | 134317e07f7c371000389e7c3f45ceaf046eea69 (diff) | |
Merge pull request #5029 from ligfx/bboximagemask
OGL: implement Bounding Box on systems w/o SSBO
Diffstat (limited to 'Source/Core/VideoBackends/OGL/FramebufferManager.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/OGL/FramebufferManager.cpp | 250 |
1 files changed, 121 insertions, 129 deletions
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 45a4b196a0..17244db24e 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" @@ -28,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<GLuint> FramebufferManager::m_efbFramebuffer; @@ -49,7 +51,64 @@ GLuint FramebufferManager::m_EfbPokes_VBO; GLuint FramebufferManager::m_EfbPokes_VAO; SHADER FramebufferManager::m_EfbPokes; -FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) +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; +} + +void FramebufferManager::BindLayeredTexture(GLuint texture, const std::vector<GLuint>& 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); + } +} + +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; @@ -60,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). @@ -76,166 +135,69 @@ 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. + 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; - - 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, depth_internal_format, depth_pixel_format, depth_data_type); // 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); + 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, 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. glGenFramebuffers(1, &m_xfbFramebuffer); // 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); + 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); @@ -243,6 +205,11 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glClearColor(0.f, 0.f, 0.f, 0.f); glClearDepthf(1.0f); 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" @@ -542,6 +509,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) { @@ -557,6 +542,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()); |
