diff options
| author | Connor McLaughlin <stenzek@gmail.com> | 2021-05-28 21:17:44 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-28 21:17:44 +1000 |
| commit | 37d05594933ab104eba82ad3bbffb20222982b20 (patch) | |
| tree | 98a98d253865e3438f23380adad1c680feb602c9 /Source/Core/VideoBackends/OGL/OGLBoundingBox.cpp | |
| parent | ee4c0ba168995ae54e02768430268030bfd792e5 (diff) | |
| parent | 7fd0a526e1a6c48d0180eb8368cc9aed5f6d0ece (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.cpp | 94 |
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 |
