diff options
Diffstat (limited to 'Source/Core/VideoBackends/OGL/VertexManager.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/OGL/VertexManager.cpp | 186 |
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 |
