summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp
diff options
context:
space:
mode:
authorConnor McLaughlin <stenzek@gmail.com>2021-05-28 21:17:44 +1000
committerGitHub <noreply@github.com>2021-05-28 21:17:44 +1000
commit37d05594933ab104eba82ad3bbffb20222982b20 (patch)
tree98a98d253865e3438f23380adad1c680feb602c9 /Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp
parentee4c0ba168995ae54e02768430268030bfd792e5 (diff)
parent7fd0a526e1a6c48d0180eb8368cc9aed5f6d0ece (diff)
Merge pull request #9648 from stenzek/dx11-gl-bbox-caching
Cache bounding box values between register reads in DX11/GL
Diffstat (limited to 'Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp94
1 files changed, 80 insertions, 14 deletions
diff --git a/Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp b/Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp
index 9e88767afc..cee200d4ad 100644
--- a/Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp
+++ b/Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include <algorithm>
+#include <array>
#include <cstring>
#include "Common/GL/GLUtil.h"
@@ -12,7 +14,15 @@
#include "VideoCommon/DriverDetails.h"
#include "VideoCommon/VideoConfig.h"
+enum : u32
+{
+ NUM_BBOX_VALUES = 4,
+};
+
static GLuint s_bbox_buffer_id;
+static std::array<s32, NUM_BBOX_VALUES> s_bbox_values;
+static std::array<bool, NUM_BBOX_VALUES> s_bbox_dirty;
+static bool s_bbox_valid = false;
namespace OGL
{
@@ -21,10 +31,14 @@ void BoundingBox::Init()
if (!g_ActiveConfig.backend_info.bSupportsBBox)
return;
- int initial_values[4] = {0, 0, 0, 0};
+ const s32 initial_values[NUM_BBOX_VALUES] = {0, 0, 0, 0};
+ std::memcpy(s_bbox_values.data(), initial_values, sizeof(s_bbox_values));
+ s_bbox_dirty = {};
+ s_bbox_valid = true;
+
glGenBuffers(1, &s_bbox_buffer_id);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
- glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(s32), initial_values, GL_DYNAMIC_DRAW);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(initial_values), initial_values, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, s_bbox_buffer_id);
}
@@ -36,22 +50,42 @@ void BoundingBox::Shutdown()
glDeleteBuffers(1, &s_bbox_buffer_id);
}
-void BoundingBox::Set(int index, int value)
+void BoundingBox::Flush()
{
- if (!g_ActiveConfig.backend_info.bSupportsBBox)
+ s_bbox_valid = false;
+
+ if (std::none_of(s_bbox_dirty.begin(), s_bbox_dirty.end(), [](bool dirty) { return dirty; }))
return;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
- glBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &value);
+
+ for (u32 start = 0; start < NUM_BBOX_VALUES;)
+ {
+ if (!s_bbox_dirty[start])
+ {
+ start++;
+ continue;
+ }
+
+ u32 end = start + 1;
+ s_bbox_dirty[start] = false;
+ for (; end < NUM_BBOX_VALUES; end++)
+ {
+ if (!s_bbox_dirty[end])
+ break;
+
+ s_bbox_dirty[end] = false;
+ }
+
+ glBufferSubData(GL_SHADER_STORAGE_BUFFER, start * sizeof(s32), (end - start) * sizeof(s32),
+ &s_bbox_values[start]);
+ }
+
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
-int BoundingBox::Get(int index)
+void BoundingBox::Readback()
{
- if (!g_ActiveConfig.backend_info.bSupportsBBox)
- return 0;
-
- int data = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
if (!DriverDetails::HasBug(DriverDetails::BUG_SLOW_GETBUFFERSUBDATA) &&
!static_cast<Renderer*>(g_renderer.get())->IsGLES())
@@ -59,20 +93,52 @@ int BoundingBox::Get(int index)
// Using glMapBufferRange to read back the contents of the SSBO is extremely slow
// on nVidia drivers. This is more noticeable at higher internal resolutions.
// Using glGetBufferSubData instead does not seem to exhibit this slowdown.
- glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &data);
+ std::array<s32, NUM_BBOX_VALUES> gpu_values;
+ glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(s32) * NUM_BBOX_VALUES,
+ gpu_values.data());
+ for (u32 i = 0; i < NUM_BBOX_VALUES; i++)
+ {
+ if (!s_bbox_dirty[i])
+ s_bbox_values[i] = gpu_values[i];
+ }
}
else
{
// Using glMapBufferRange is faster on AMD cards by a measurable margin.
- void* ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int),
+ void* ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(s32) * NUM_BBOX_VALUES,
GL_MAP_READ_BIT);
if (ptr)
{
- memcpy(&data, ptr, sizeof(int));
+ for (u32 i = 0; i < NUM_BBOX_VALUES; i++)
+ {
+ if (!s_bbox_dirty[i])
+ {
+ std::memcpy(&s_bbox_values[i], reinterpret_cast<const u8*>(ptr) + sizeof(s32) * i,
+ sizeof(s32));
+ }
+ }
+
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
- return data;
+ s_bbox_valid = true;
+}
+
+void BoundingBox::Set(int index, int value)
+{
+ if (s_bbox_valid && s_bbox_values[index] == value)
+ return;
+
+ s_bbox_values[index] = value;
+ s_bbox_dirty[index] = true;
+}
+
+int BoundingBox::Get(int index)
+{
+ if (!s_bbox_valid)
+ Readback();
+
+ return s_bbox_values[index];
}
}; // namespace OGL