summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/VertexManager.cpp
diff options
context:
space:
mode:
authorTilka <tilkax@gmail.com>2019-02-26 04:21:05 +0000
committerGitHub <noreply@github.com>2019-02-26 04:21:05 +0000
commit6ce7f44b8a0bb3b95d3f12ebffbef7a71a443fdd (patch)
tree98380ce3a3284c52597a6fba86589c847219ecd5 /Source/Core/VideoBackends/OGL/VertexManager.cpp
parent19673ce79af814ca3b77d7f8ea60458e564bfa51 (diff)
parentf039149198657c1891e1c6462ed30c31ed4b8486 (diff)
Merge pull request #7753 from stenzek/videocommon-all-the-things
Move a significant amount of video backend logic to VideoCommon
Diffstat (limited to 'Source/Core/VideoBackends/OGL/VertexManager.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/VertexManager.cpp186
1 files changed, 114 insertions, 72 deletions
diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp
index 3883a13595..543a85dac8 100644
--- a/Source/Core/VideoBackends/OGL/VertexManager.cpp
+++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp
@@ -9,17 +9,14 @@
#include <string>
#include <vector>
+#include "Common/Align.h"
#include "Common/CommonTypes.h"
-#include "Common/FileUtil.h"
#include "Common/GL/GLExtensions/GLExtensions.h"
-#include "Common/StringUtil.h"
-#include "VideoBackends/OGL/BoundingBox.h"
#include "VideoBackends/OGL/OGLPipeline.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/StreamBuffer.h"
-#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/Statistics.h"
@@ -28,79 +25,147 @@
namespace OGL
{
-// This are the initially requested size for the buffers expressed in bytes
-const u32 MAX_IBUFFER_SIZE = 2 * 1024 * 1024;
-const u32 MAX_VBUFFER_SIZE = 32 * 1024 * 1024;
-
-VertexManager::VertexManager() : m_cpu_v_buffer(MAX_VBUFFER_SIZE), m_cpu_i_buffer(MAX_IBUFFER_SIZE)
+static void CheckBufferBinding()
{
- CreateDeviceObjects();
+ // The index buffer is part of the VAO state, therefore we need to bind it first.
+ if (!ProgramShaderCache::IsValidVertexFormatBound())
+ {
+ ProgramShaderCache::BindVertexFormat(
+ static_cast<GLVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat()));
+ }
}
+VertexManager::VertexManager() = default;
+
VertexManager::~VertexManager()
{
- DestroyDeviceObjects();
-}
+ if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
+ {
+ glDeleteTextures(static_cast<GLsizei>(m_texel_buffer_views.size()),
+ m_texel_buffer_views.data());
+ }
-void VertexManager::CreateDeviceObjects()
-{
- m_vertex_buffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
- m_index_buffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
+ // VAO must be found when destroying the index buffer.
+ CheckBufferBinding();
+ m_texel_buffer.reset();
+ m_index_buffer.reset();
+ m_vertex_buffer.reset();
}
-void VertexManager::DestroyDeviceObjects()
+bool VertexManager::Initialize()
{
- m_vertex_buffer.reset();
- m_index_buffer.reset();
+ if (!VertexManagerBase::Initialize())
+ return false;
+
+ m_vertex_buffer = StreamBuffer::Create(GL_ARRAY_BUFFER, VERTEX_STREAM_BUFFER_SIZE);
+ m_index_buffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, INDEX_STREAM_BUFFER_SIZE);
+
+ if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
+ {
+ // The minimum MAX_TEXTURE_BUFFER_SIZE that the spec mandates is 65KB, we are asking for a 1MB
+ // buffer here. This buffer is also used as storage for undecoded textures when compute shader
+ // texture decoding is enabled, in which case the requested size is 32MB.
+ GLint max_buffer_size;
+ glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_buffer_size);
+ m_texel_buffer = StreamBuffer::Create(
+ GL_TEXTURE_BUFFER, std::min(max_buffer_size, static_cast<GLint>(TEXEL_STREAM_BUFFER_SIZE)));
+
+ // Allocate texture views backed by buffer.
+ static constexpr std::array<std::pair<TexelBufferFormat, GLenum>, NUM_TEXEL_BUFFER_FORMATS>
+ format_mapping = {{
+ {TEXEL_BUFFER_FORMAT_R8_UINT, GL_R8UI},
+ {TEXEL_BUFFER_FORMAT_R16_UINT, GL_R16UI},
+ {TEXEL_BUFFER_FORMAT_RGBA8_UINT, GL_RGBA8},
+ {TEXEL_BUFFER_FORMAT_R32G32_UINT, GL_RG32UI},
+ }};
+ glGenTextures(static_cast<GLsizei>(m_texel_buffer_views.size()), m_texel_buffer_views.data());
+ glActiveTexture(GL_MUTABLE_TEXTURE_INDEX);
+ for (const auto& it : format_mapping)
+ {
+ glBindTexture(GL_TEXTURE_BUFFER, m_texel_buffer_views[it.first]);
+ glTexBuffer(GL_TEXTURE_BUFFER, it.second, m_texel_buffer->GetGLBufferId());
+ }
+ }
+
+ return true;
}
void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
{
- ProgramShaderCache::InvalidateConstants();
+ InvalidateConstants();
ProgramShaderCache::UploadConstants(uniforms, uniforms_size);
}
-GLuint VertexManager::GetVertexBufferHandle() const
+bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
+ u32* out_offset)
{
- return m_vertex_buffer->m_buffer;
+ if (data_size > m_texel_buffer->GetSize())
+ return false;
+
+ const u32 elem_size = GetTexelBufferElementSize(format);
+ const auto dst = m_texel_buffer->Map(data_size, elem_size);
+ std::memcpy(dst.first, data, data_size);
+ ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
+ *out_offset = dst.second / elem_size;
+ m_texel_buffer->Unmap(data_size);
+
+ // Bind the correct view to the texel buffer slot.
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_BUFFER, m_texel_buffer_views[static_cast<u32>(format)]);
+ Renderer::GetInstance()->InvalidateTextureBinding(0);
+ return true;
}
-GLuint VertexManager::GetIndexBufferHandle() const
+bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
+ u32* out_offset, const void* palette_data, u32 palette_size,
+ TexelBufferFormat palette_format, u32* out_palette_offset)
{
- return m_index_buffer->m_buffer;
+ const u32 elem_size = GetTexelBufferElementSize(format);
+ const u32 palette_elem_size = GetTexelBufferElementSize(palette_format);
+ const u32 reserve_size = data_size + palette_size + palette_elem_size;
+ if (reserve_size > m_texel_buffer->GetSize())
+ return false;
+
+ const auto dst = m_texel_buffer->Map(reserve_size, elem_size);
+ const u32 palette_byte_offset = Common::AlignUp(data_size, palette_elem_size);
+ std::memcpy(dst.first, data, data_size);
+ std::memcpy(dst.first + palette_byte_offset, palette_data, palette_size);
+ ADDSTAT(stats.thisFrame.bytesUniformStreamed, palette_byte_offset + palette_size);
+ *out_offset = dst.second / elem_size;
+ *out_palette_offset = (dst.second + palette_byte_offset) / palette_elem_size;
+ m_texel_buffer->Unmap(palette_byte_offset + palette_size);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_BUFFER, m_texel_buffer_views[static_cast<u32>(format)]);
+ Renderer::GetInstance()->InvalidateTextureBinding(0);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_BUFFER, m_texel_buffer_views[static_cast<u32>(palette_format)]);
+ Renderer::GetInstance()->InvalidateTextureBinding(1);
+
+ return true;
}
-static void CheckBufferBinding()
+GLuint VertexManager::GetVertexBufferHandle() const
{
- // The index buffer is part of the VAO state, therefore we need to bind it first.
- if (!ProgramShaderCache::IsValidVertexFormatBound())
- {
- ProgramShaderCache::BindVertexFormat(
- static_cast<GLVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat()));
- }
+ return m_vertex_buffer->m_buffer;
}
-void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
+GLuint VertexManager::GetIndexBufferHandle() const
{
- if (cull_all)
- {
- // This buffer isn't getting sent to the GPU. Just allocate it on the cpu.
- m_cur_buffer_pointer = m_base_buffer_pointer = m_cpu_v_buffer.data();
- m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_v_buffer.size();
+ return m_index_buffer->m_buffer;
+}
- IndexGenerator::Start((u16*)m_cpu_i_buffer.data());
- }
- else
- {
- CheckBufferBinding();
+void VertexManager::ResetBuffer(u32 vertex_stride)
+{
+ CheckBufferBinding();
- auto buffer = m_vertex_buffer->Map(MAXVBUFFERSIZE, vertex_stride);
- m_cur_buffer_pointer = m_base_buffer_pointer = buffer.first;
- m_end_buffer_pointer = buffer.first + MAXVBUFFERSIZE;
+ auto buffer = m_vertex_buffer->Map(MAXVBUFFERSIZE, vertex_stride);
+ m_cur_buffer_pointer = m_base_buffer_pointer = buffer.first;
+ m_end_buffer_pointer = buffer.first + MAXVBUFFERSIZE;
- buffer = m_index_buffer->Map(MAXIBUFFERSIZE * sizeof(u16));
- IndexGenerator::Start((u16*)buffer.first);
- }
+ buffer = m_index_buffer->Map(MAXIBUFFERSIZE * sizeof(u16));
+ IndexGenerator::Start((u16*)buffer.first);
}
void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
@@ -120,31 +185,8 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size);
}
-void VertexManager::UploadConstants()
+void VertexManager::UploadUniforms()
{
ProgramShaderCache::UploadConstants();
}
-
-void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
-{
- if (::BoundingBox::active && !g_Config.BBoxUseFragmentShaderImplementation())
- {
- glEnable(GL_STENCIL_TEST);
- }
-
- if (m_current_pipeline_object)
- {
- static_cast<Renderer*>(g_renderer.get())->SetPipeline(m_current_pipeline_object);
- static_cast<Renderer*>(g_renderer.get())->DrawIndexed(base_index, num_indices, base_vertex);
- }
-
- if (::BoundingBox::active && !g_Config.BBoxUseFragmentShaderImplementation())
- {
- OGL::BoundingBox::StencilWasUpdated();
- glDisable(GL_STENCIL_TEST);
- }
-
- g_Config.iSaveTargetId++;
- ClearEFBCache();
-}
} // namespace OGL