diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-08-31 16:14:47 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-08-31 16:14:47 +0300 |
commit | 1804eb57fd27fceb0ed113e3ef2f4a55db0d03c8 (patch) | |
tree | 003ceca6cdb280e5f6fc408b6833dea8b36f2bd6 /source/blender/gpu/opengl/gl_immediate.cc | |
parent | 1b3a0ae2316063d9817210a8fe5fd4588cee47cf (diff) |
GPUImmediate: GL backend isolation
This is part of the Vulkan backend task T68990.
This is mostly a cleanup, however, there is a small change:
We don't use a special Vertex Array binding function for Immediate
anymore and just reuse the one for batches.
This might create a bit more state changes but this could be fixed
easily if it causes perf regression.
# Conflicts:
# source/blender/gpu/intern/gpu_context.cc
Diffstat (limited to 'source/blender/gpu/opengl/gl_immediate.cc')
-rw-r--r-- | source/blender/gpu/opengl/gl_immediate.cc | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/source/blender/gpu/opengl/gl_immediate.cc b/source/blender/gpu/opengl/gl_immediate.cc new file mode 100644 index 00000000000..ff598f79b3f --- /dev/null +++ b/source/blender/gpu/opengl/gl_immediate.cc @@ -0,0 +1,183 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + * + * Mimics old style opengl immediate mode drawing. + */ + +#include "BKE_global.h" + +#include "gpu_context_private.hh" +#include "gpu_shader_private.hh" +#include "gpu_vertex_format_private.h" + +#include "gl_context.hh" +#include "gl_primitive.hh" +#include "gl_vertex_array.hh" + +#include "gl_immediate.hh" + +namespace blender::gpu { + +/* -------------------------------------------------------------------- */ +/** \name Creation & Deletion + * \{ */ + +GLImmediate::GLImmediate() +{ + glGenVertexArrays(1, &vao_id_); + + buffer.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE; + glGenBuffers(1, &buffer.vbo_id); + glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id); + glBufferData(GL_ARRAY_BUFFER, buffer.buffer_size, NULL, GL_DYNAMIC_DRAW); + + buffer_strict.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE; + glGenBuffers(1, &buffer_strict.vbo_id); + glBindBuffer(GL_ARRAY_BUFFER, buffer_strict.vbo_id); + glBufferData(GL_ARRAY_BUFFER, buffer_strict.buffer_size, NULL, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + +#ifndef __APPLE__ + if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) { + glObjectLabel(GL_VERTEX_ARRAY, vao_id_, -1, "VAO-Immediate"); + glObjectLabel(GL_BUFFER, buffer.vbo_id, -1, "VBO-ImmediateBuffer"); + glObjectLabel(GL_BUFFER, buffer_strict.vbo_id, -1, "VBO-ImmediateBufferStrict"); + } +#endif +} + +GLImmediate::~GLImmediate() +{ + glDeleteVertexArrays(1, &vao_id_); + + glDeleteBuffers(1, &buffer.vbo_id); + glDeleteBuffers(1, &buffer_strict.vbo_id); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Buffer management + * \{ */ + +uchar *GLImmediate::begin() +{ + /* How many bytes do we need for this draw call? */ + const size_t bytes_needed = vertex_buffer_size(&vertex_format, vertex_len); + /* Does the current buffer have enough room? */ + const size_t available_bytes = buffer_size() - buffer_offset(); + + glBindBuffer(GL_ARRAY_BUFFER, vbo_id()); + + bool recreate_buffer = false; + if (bytes_needed > buffer_size()) { + /* expand the internal buffer */ + buffer_size() = bytes_needed; + recreate_buffer = true; + } + else if (bytes_needed < DEFAULT_INTERNAL_BUFFER_SIZE && + buffer_size() > DEFAULT_INTERNAL_BUFFER_SIZE) { + /* shrink the internal buffer */ + buffer_size() = DEFAULT_INTERNAL_BUFFER_SIZE; + recreate_buffer = true; + } + + /* ensure vertex data is aligned */ + /* Might waste a little space, but it's safe. */ + const uint pre_padding = padding(buffer_offset(), vertex_format.stride); + + if (!recreate_buffer && ((bytes_needed + pre_padding) <= available_bytes)) { + buffer_offset() += pre_padding; + } + else { + /* orphan this buffer & start with a fresh one */ + glBufferData(GL_ARRAY_BUFFER, buffer_size(), NULL, GL_DYNAMIC_DRAW); + buffer_offset() = 0; + } + +#ifndef NDEBUG + { + GLint bufsize; + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufsize); + BLI_assert(buffer_offset() + bytes_needed <= bufsize); + } +#endif + + GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT; + if (!strict_vertex_len) { + access |= GL_MAP_FLUSH_EXPLICIT_BIT; + } + void *data = glMapBufferRange(GL_ARRAY_BUFFER, buffer_offset(), bytes_needed, access); + BLI_assert(data != NULL); + + bytes_mapped_ = bytes_needed; + return (uchar *)data; +} + +void GLImmediate::end(void) +{ + BLI_assert(prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + + uint buffer_bytes_used = bytes_mapped_; + if (!strict_vertex_len) { + if (vertex_idx != vertex_len) { + vertex_len = vertex_idx; + buffer_bytes_used = vertex_buffer_size(&vertex_format, vertex_len); + /* unused buffer bytes are available to the next immBegin */ + } + /* tell OpenGL what range was modified so it doesn't copy the whole mapped range */ + glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used); + } + glUnmapBuffer(GL_ARRAY_BUFFER); + + if (vertex_len > 0) { + GPU_context_active_get()->state_manager->apply_state(); + + /* We convert the offset in vertex offset from the buffer's start. + * This works because we added some padding to align the first vertex vertex. */ + uint v_first = buffer_offset() / vertex_format.stride; + GLVertArray::update_bindings( + vao_id_, v_first, &vertex_format, reinterpret_cast<Shader *>(shader)->interface); + + /* Update matrices. */ + GPU_shader_bind(shader); + +#ifdef __APPLE__ + glDisable(GL_PRIMITIVE_RESTART); +#endif + glDrawArrays(to_gl(prim_type), 0, vertex_len); +#ifdef __APPLE__ + glEnable(GL_PRIMITIVE_RESTART); +#endif + /* These lines are causing crash on startup on some old GPU + drivers. + * They are not required so just comment them. (T55722) */ + // glBindBuffer(GL_ARRAY_BUFFER, 0); + // glBindVertexArray(0); + } + + buffer_offset() += buffer_bytes_used; +} + +/** \} */ + +} // namespace blender::gpu
\ No newline at end of file |