OGL: only create stencil buffer when needed

This commit is contained in:
Michael Maltese 2017-03-09 15:33:10 -08:00
parent ba6e917b49
commit 53224d41d0
5 changed files with 86 additions and 42 deletions

View File

@ -167,4 +167,10 @@ void BoundingBox::StencilWasUpdated()
s_stencil_updated = true; s_stencil_updated = true;
s_stencil_cleared = false; s_stencil_cleared = false;
} }
bool BoundingBox::NeedsStencilBuffer()
{
return g_ActiveConfig.bBBoxEnable &&
!g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics;
}
}; };

View File

@ -15,8 +15,10 @@ public:
static void SetTargetSizeChanged(int target_width, int target_height); static void SetTargetSizeChanged(int target_width, int target_height);
// When SSBO isn't available, the bounding box is calculated directly from the // When SSBO isn't available, the bounding box is calculated directly from the
// stencil buffer. When the stencil buffer is changed, this function needs to // stencil buffer.
// be called to invalidate the cached bounding box data. static bool NeedsStencilBuffer();
// When the stencil buffer is changed, this function needs to be called to
// invalidate the cached bounding box data.
static void StencilWasUpdated(); static void StencilWasUpdated();
static void Set(int index, int value); static void Set(int index, int value);

View File

@ -29,6 +29,7 @@ namespace OGL
int FramebufferManager::m_targetWidth; int FramebufferManager::m_targetWidth;
int FramebufferManager::m_targetHeight; int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples; int FramebufferManager::m_msaaSamples;
bool FramebufferManager::m_enable_stencil_buffer;
GLenum FramebufferManager::m_textureType; GLenum FramebufferManager::m_textureType;
std::vector<GLuint> FramebufferManager::m_efbFramebuffer; std::vector<GLuint> FramebufferManager::m_efbFramebuffer;
@ -88,18 +89,26 @@ GLuint FramebufferManager::CreateTexture(GLenum texture_type, GLenum internal_fo
return texture; return texture;
} }
void FramebufferManager::BindLayeredTexture(GLuint texture, const std::vector<GLuint>& framebuffers, GLenum attachment, GLenum texture_type) void FramebufferManager::BindLayeredTexture(GLuint texture, const std::vector<GLuint>& framebuffers,
GLenum attachment, GLenum texture_type)
{ {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]); glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]);
FramebufferTexture(GL_FRAMEBUFFER, attachment, texture_type, texture, 0); FramebufferTexture(GL_FRAMEBUFFER, attachment, texture_type, texture, 0);
// Bind all the other layers as separate FBOs for blitting. // 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]); glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[i]);
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, texture, 0, 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_xfbFramebuffer = 0;
m_efbColor = 0; m_efbColor = 0;
@ -110,8 +119,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_targetWidth = targetWidth; m_targetWidth = targetWidth;
m_targetHeight = targetHeight; m_targetHeight = targetHeight;
m_msaaSamples = msaaSamples; m_msaaSamples = msaaSamples;
m_enable_stencil_buffer = enable_stencil_buffer;
// The EFB can be set to different pixel formats by the game through the // The EFB can be set to different pixel formats by the game through the
// BPMEM_ZCOMPARE register (which should probably have a different name). // 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_efbFramebuffer.resize(m_EFBLayers);
m_resolvedFramebuffer.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) if (m_msaaSamples <= 1)
{ {
m_textureType = GL_TEXTURE_2D_ARRAY; 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_resolvedColorTexture = CreateTexture(resolvedType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
m_resolvedDepthTexture = 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. // Bind resolved textures to resolved framebuffer.
glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data());
BindLayeredTexture(m_resolvedColorTexture, m_resolvedFramebuffer, GL_COLOR_ATTACHMENT0, resolvedType); BindLayeredTexture(m_resolvedColorTexture, m_resolvedFramebuffer, GL_COLOR_ATTACHMENT0,
BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_DEPTH_ATTACHMENT, resolvedType); resolvedType);
BindLayeredTexture(m_resolvedDepthTexture, m_resolvedFramebuffer, GL_STENCIL_ATTACHMENT, 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_efbColor = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
m_efbDepth = CreateTexture(m_textureType, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, m_efbDepth =
GL_FLOAT_32_UNSIGNED_INT_24_8_REV); CreateTexture(m_textureType, depth_internal_format, depth_pixel_format, depth_data_type);
m_efbColorSwap = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); m_efbColorSwap = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
// Create XFB framebuffer; targets will be created elsewhere. // 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()); glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data());
BindLayeredTexture(m_efbColor, m_efbFramebuffer, GL_COLOR_ATTACHMENT0, m_textureType); 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_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. // EFB framebuffer is currently bound, make sure to clear it before use.
glViewport(0, 0, m_targetWidth, m_targetHeight); glViewport(0, 0, m_targetWidth, m_targetHeight);
glScissor(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight);
glClearColor(0.f, 0.f, 0.f, 0.f); glClearColor(0.f, 0.f, 0.f, 0.f);
glClearDepthf(1.0f); glClearDepthf(1.0f);
glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); if (m_enable_stencil_buffer)
{
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
}
// reinterpret pixel format // reinterpret pixel format
const char* vs = m_EFBLayers > 1 ? "void main(void) {\n" const char* vs = m_EFBLayers > 1 ? "void main(void) {\n"

View File

@ -63,7 +63,8 @@ struct XFBSource : public XFBSourceBase
class FramebufferManager : public FramebufferManagerBase class FramebufferManager : public FramebufferManagerBase
{ {
public: public:
FramebufferManager(int targetWidth, int targetHeight, int msaaSamples); FramebufferManager(int targetWidth, int targetHeight, int msaaSamples,
bool enable_stencil_buffer);
~FramebufferManager(); ~FramebufferManager();
// To get the EFB in texture form, these functions may have to transfer // To get the EFB in texture form, these functions may have to transfer
@ -101,11 +102,13 @@ public:
static void ReinterpretPixelData(unsigned int convtype); static void ReinterpretPixelData(unsigned int convtype);
static void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points); static void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points);
static bool HasStencilBuffer();
private: private:
GLuint CreateTexture(GLenum texture_type, GLenum internal_format, GLenum pixel_format, GLuint CreateTexture(GLenum texture_type, GLenum internal_format, GLenum pixel_format,
GLenum data_type); GLenum data_type);
void BindLayeredTexture(GLuint texture, const std::vector<GLuint>& framebuffers, GLenum attachment, GLenum texture_type); void BindLayeredTexture(GLuint texture, const std::vector<GLuint>& framebuffers,
GLenum attachment, GLenum texture_type);
std::unique_ptr<XFBSourceBase> CreateXFBSource(unsigned int target_width, std::unique_ptr<XFBSourceBase> CreateXFBSource(unsigned int target_width,
unsigned int target_height, unsigned int target_height,
unsigned int layers) override; unsigned int layers) override;
@ -126,6 +129,8 @@ private:
static GLuint static GLuint
m_efbColorSwap; // will be hot swapped with m_efbColor when reinterpreting EFB pixel formats m_efbColorSwap; // will be hot swapped with m_efbColor when reinterpreting EFB pixel formats
static bool m_enable_stencil_buffer;
// Only used in MSAA mode, TODO: try to avoid them // Only used in MSAA mode, TODO: try to avoid them
static std::vector<GLuint> m_resolvedFramebuffer; static std::vector<GLuint> m_resolvedFramebuffer;
static GLuint m_resolvedColorTexture; static GLuint m_resolvedColorTexture;

View File

@ -734,8 +734,8 @@ void Renderer::Shutdown()
void Renderer::Init() void Renderer::Init()
{ {
// Initialize the FramebufferManager // Initialize the FramebufferManager
g_framebuffer_manager = g_framebuffer_manager = std::make_unique<FramebufferManager>(
std::make_unique<FramebufferManager>(m_target_width, m_target_height, s_MSAASamples); m_target_width, m_target_height, s_MSAASamples, BoundingBox::NeedsStencilBuffer());
m_post_processor = std::make_unique<OpenGLPostProcessing>(); m_post_processor = std::make_unique<OpenGLPostProcessing>();
s_raster_font = std::make_unique<RasterFont>(); s_raster_font = std::make_unique<RasterFont>();
@ -1338,35 +1338,38 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
} }
bool target_size_changed = CalculateTargetSize(); bool target_size_changed = CalculateTargetSize();
if (target_size_changed || xfbchanged || window_resized || bool stencil_buffer_enabled =
(s_last_multisamples != g_ActiveConfig.iMultisamples) || static_cast<FramebufferManager*>(g_framebuffer_manager.get())->HasStencilBuffer();
(s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0)))
bool fb_needs_update = target_size_changed ||
s_last_multisamples != g_ActiveConfig.iMultisamples ||
stencil_buffer_enabled != BoundingBox::NeedsStencilBuffer() ||
s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0);
if (xfbchanged || window_resized || fb_needs_update)
{ {
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
UpdateDrawRectangle(); UpdateDrawRectangle();
}
if (fb_needs_update)
{
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
s_last_multisamples = g_ActiveConfig.iMultisamples;
s_MSAASamples = s_last_multisamples;
if (target_size_changed || s_last_multisamples != g_ActiveConfig.iMultisamples || if (s_MSAASamples > 1 && s_MSAASamples > g_ogl_config.max_samples)
s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0))
{ {
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_MSAASamples = g_ogl_config.max_samples;
s_last_multisamples = g_ActiveConfig.iMultisamples; OSD::AddMessage(
s_MSAASamples = s_last_multisamples; StringFromFormat("%d Anti Aliasing samples selected, but only %d supported by your GPU.",
s_last_multisamples, g_ogl_config.max_samples),
if (s_MSAASamples > 1 && s_MSAASamples > g_ogl_config.max_samples) 10000);
{
s_MSAASamples = g_ogl_config.max_samples;
OSD::AddMessage(StringFromFormat(
"%d Anti Aliasing samples selected, but only %d supported by your GPU.",
s_last_multisamples, g_ogl_config.max_samples),
10000);
}
g_framebuffer_manager.reset();
g_framebuffer_manager =
std::make_unique<FramebufferManager>(m_target_width, m_target_height, s_MSAASamples);
BoundingBox::SetTargetSizeChanged(m_target_width, m_target_height);
} }
g_framebuffer_manager.reset();
g_framebuffer_manager = std::make_unique<FramebufferManager>(
m_target_width, m_target_height, s_MSAASamples, BoundingBox::NeedsStencilBuffer());
BoundingBox::SetTargetSizeChanged(m_target_width, m_target_height);
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------