From 134317e07f7c371000389e7c3f45ceaf046eea69 Mon Sep 17 00:00:00 2001
From: Michael Maltese <michaeljosephmaltese@gmail.com>
Date: Fri, 10 Mar 2017 00:07:49 -0800
Subject: [PATCH] videoconfig: add BBoxPreferStencilImplementation

@JMC47 requested this to be able to do performance comparisons.
---
 Source/Core/VideoBackends/OGL/BoundingBox.cpp   | 13 ++++++-------
 Source/Core/VideoBackends/OGL/VertexManager.cpp |  4 ++--
 Source/Core/VideoCommon/PixelShaderGen.cpp      |  3 +--
 Source/Core/VideoCommon/VideoConfig.cpp         |  2 ++
 Source/Core/VideoCommon/VideoConfig.h           |  7 +++++++
 5 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/Source/Core/VideoBackends/OGL/BoundingBox.cpp b/Source/Core/VideoBackends/OGL/BoundingBox.cpp
index 2d370a115d..ebf8433d92 100644
--- a/Source/Core/VideoBackends/OGL/BoundingBox.cpp
+++ b/Source/Core/VideoBackends/OGL/BoundingBox.cpp
@@ -28,7 +28,7 @@ namespace OGL
 {
 void BoundingBox::SetTargetSizeChanged(int target_width, int target_height)
 {
-  if (g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics)
+  if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
     return;
 
   s_target_width = target_width;
@@ -42,7 +42,7 @@ void BoundingBox::SetTargetSizeChanged(int target_width, int target_height)
 
 void BoundingBox::Init(int target_width, int target_height)
 {
-  if (g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics)
+  if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
   {
     int initial_values[4] = {0, 0, 0, 0};
     glGenBuffers(1, &s_bbox_buffer_id);
@@ -60,7 +60,7 @@ void BoundingBox::Init(int target_width, int target_height)
 
 void BoundingBox::Shutdown()
 {
-  if (g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics)
+  if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
   {
     glDeleteBuffers(1, &s_bbox_buffer_id);
   }
@@ -72,7 +72,7 @@ void BoundingBox::Shutdown()
 
 void BoundingBox::Set(int index, int value)
 {
-  if (g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics)
+  if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
   {
     glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
     glBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &value);
@@ -95,7 +95,7 @@ void BoundingBox::Set(int index, int value)
 
 int BoundingBox::Get(int index)
 {
-  if (g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics)
+  if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
   {
     int data = 0;
     glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
@@ -170,7 +170,6 @@ void BoundingBox::StencilWasUpdated()
 
 bool BoundingBox::NeedsStencilBuffer()
 {
-  return g_ActiveConfig.bBBoxEnable &&
-         !g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics;
+  return g_ActiveConfig.bBBoxEnable && !g_ActiveConfig.BBoxUseFragmentShaderImplementation();
 }
 };
diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp
index d8d9249965..58d7b19ad9 100644
--- a/Source/Core/VideoBackends/OGL/VertexManager.cpp
+++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp
@@ -158,14 +158,14 @@ void VertexManager::vFlush()
   // setup the pointers
   nativeVertexFmt->SetupVertexPointers();
 
-  if (!g_Config.backend_info.bSupportsFragmentStoresAndAtomics && ::BoundingBox::active)
+  if (::BoundingBox::active && !g_Config.BBoxUseFragmentShaderImplementation())
   {
     glEnable(GL_STENCIL_TEST);
   }
 
   Draw(stride);
 
-  if (!g_Config.backend_info.bSupportsFragmentStoresAndAtomics && ::BoundingBox::active)
+  if (::BoundingBox::active && !g_Config.BBoxUseFragmentShaderImplementation())
   {
     OGL::BoundingBox::StencilWasUpdated();
     glDisable(GL_STENCIL_TEST);
diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp
index 6360a68a37..9eb0d625cb 100644
--- a/Source/Core/VideoCommon/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/PixelShaderGen.cpp
@@ -171,8 +171,7 @@ PixelShaderUid GetPixelShaderUid()
   uid_data->genMode_numtevstages = bpmem.genMode.numtevstages;
   uid_data->genMode_numtexgens = bpmem.genMode.numtexgens;
   uid_data->per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
-  uid_data->bounding_box = g_ActiveConfig.backend_info.bSupportsBBox &&
-                           g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics &&
+  uid_data->bounding_box = g_ActiveConfig.BBoxUseFragmentShaderImplementation() &&
                            g_ActiveConfig.bBBoxEnable && BoundingBox::active;
   uid_data->rgba6_format =
       bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor;
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index 2db2494a05..7579c90c6e 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -119,6 +119,7 @@ void VideoConfig::Load(const std::string& ini_file)
   IniFile::Section* hacks = iniFile.GetOrCreateSection("Hacks");
   hacks->Get("EFBAccessEnable", &bEFBAccessEnable, true);
   hacks->Get("BBoxEnable", &bBBoxEnable, false);
+  hacks->Get("BBoxPreferStencilImplementation", &bBBoxPreferStencilImplementation, false);
   hacks->Get("ForceProgressive", &bForceProgressive, true);
   hacks->Get("EFBToTextureEnable", &bSkipEFBCopyToRam, true);
   hacks->Get("EFBScaledCopy", &bCopyEFBScaled, true);
@@ -342,6 +343,7 @@ void VideoConfig::Save(const std::string& ini_file)
   IniFile::Section* hacks = iniFile.GetOrCreateSection("Hacks");
   hacks->Set("EFBAccessEnable", bEFBAccessEnable);
   hacks->Set("BBoxEnable", bBBoxEnable);
+  hacks->Set("BBoxPreferStencilImplementation", bBBoxPreferStencilImplementation);
   hacks->Set("ForceProgressive", bForceProgressive);
   hacks->Set("EFBToTextureEnable", bSkipEFBCopyToRam);
   hacks->Set("EFBScaledCopy", bCopyEFBScaled);
diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h
index b8e348157d..a3a44f2ec7 100644
--- a/Source/Core/VideoCommon/VideoConfig.h
+++ b/Source/Core/VideoCommon/VideoConfig.h
@@ -114,6 +114,7 @@ struct VideoConfig final
   bool bEFBAccessEnable;
   bool bPerfQueriesEnable;
   bool bBBoxEnable;
+  bool bBBoxPreferStencilImplementation;  // OpenGL-only, to see how slow it is compared to SSBOs
   bool bForceProgressive;
 
   bool bEFBEmulateFormatChanges;
@@ -203,6 +204,12 @@ struct VideoConfig final
   {
     return backend_info.bSupportsExclusiveFullscreen && !bBorderlessFullscreen;
   }
+  bool BBoxUseFragmentShaderImplementation() const
+  {
+    if (backend_info.api_type == APIType::OpenGL && bBBoxPreferStencilImplementation)
+      return false;
+    return backend_info.bSupportsBBox && backend_info.bSupportsFragmentStoresAndAtomics;
+  }
 };
 
 extern VideoConfig g_Config;