diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-08-08 16:24:52 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-08-13 15:20:23 +0300 |
commit | 38ef35b1ed1d38ab58c7d7fb121f4f3b33869810 (patch) | |
tree | 6b3d8317b9e43a5875eb05cadb79ce2ebae859de /source/blender/gpu/intern | |
parent | cb2565195e72ee4dc5c0b53b7cd5037b2169d55f (diff) |
GPUDrawList: GL backend isolation
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_backend.hh | 12 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_batch.cc | 187 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_context.cc | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_drawlist.cc | 59 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_drawlist_private.hh | 40 |
5 files changed, 114 insertions, 194 deletions
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh index 24f592f214f..4dd6036e672 100644 --- a/source/blender/gpu/intern/gpu_backend.hh +++ b/source/blender/gpu/intern/gpu_backend.hh @@ -25,13 +25,21 @@ #pragma once -struct GPUContext; +#include "gpu_context_private.hh" +#include "gpu_drawlist_private.hh" + +namespace blender { +namespace gpu { class GPUBackend { public: virtual ~GPUBackend(){}; + static GPUBackend *get(void); + virtual GPUContext *context_alloc(void *ghost_window) = 0; + virtual DrawList *drawlist_alloc(int list_length) = 0; }; -GPUBackend *gpu_backend_get(void); +} // namespace gpu +} // namespace blender diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc index a6ba4d3d89a..5b8a3c4636b 100644 --- a/source/blender/gpu/intern/gpu_batch.cc +++ b/source/blender/gpu/intern/gpu_batch.cc @@ -796,193 +796,6 @@ void GPU_draw_primitive(GPUPrimType prim_type, int v_count) } /* -------------------------------------------------------------------- */ -/** \name Indirect Draw Calls - * \{ */ - -#if 0 -# define USE_MULTI_DRAW_INDIRECT 0 -#else -# define USE_MULTI_DRAW_INDIRECT \ - (GL_ARB_multi_draw_indirect && GPU_arb_base_instance_is_supported()) -#endif - -typedef struct GPUDrawCommand { - uint v_count; - uint i_count; - uint v_first; - uint i_first; -} GPUDrawCommand; - -typedef struct GPUDrawCommandIndexed { - uint v_count; - uint i_count; - uint v_first; - uint base_index; - uint i_first; -} GPUDrawCommandIndexed; - -struct GPUDrawList { - GPUBatch *batch; - uint base_index; /* Avoid dereferencing batch. */ - uint cmd_offset; /* in bytes, offset inside indirect command buffer. */ - uint cmd_len; /* Number of used command for the next call. */ - uint buffer_size; /* in bytes, size of indirect command buffer. */ - GLuint buffer_id; /* Draw Indirect Buffer id */ - union { - GPUDrawCommand *commands; - GPUDrawCommandIndexed *commands_indexed; - }; -}; - -GPUDrawList *GPU_draw_list_create(int length) -{ - GPUDrawList *list = (GPUDrawList *)MEM_callocN(sizeof(GPUDrawList), "GPUDrawList"); - /* Alloc the biggest possible command list which is indexed. */ - list->buffer_size = sizeof(GPUDrawCommandIndexed) * length; - if (USE_MULTI_DRAW_INDIRECT) { - list->buffer_id = GPU_buf_alloc(); - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id); - glBufferData(GL_DRAW_INDIRECT_BUFFER, list->buffer_size, NULL, GL_DYNAMIC_DRAW); - } - else { - list->commands = (GPUDrawCommand *)MEM_mallocN(list->buffer_size, "GPUDrawList data"); - } - return list; -} - -void GPU_draw_list_discard(GPUDrawList *list) -{ - if (list->buffer_id) { - GPU_buf_free(list->buffer_id); - } - else { - MEM_SAFE_FREE(list->commands); - } - MEM_freeN(list); -} - -void GPU_draw_list_init(GPUDrawList *list, GPUBatch *batch) -{ - BLI_assert(batch->phase == GPU_BATCH_READY_TO_DRAW); - list->batch = batch; - list->base_index = batch->elem ? BASE_INDEX(batch->elem) : UINT_MAX; - list->cmd_len = 0; - - if (USE_MULTI_DRAW_INDIRECT) { - if (list->commands == NULL) { - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id); - if (list->cmd_offset >= list->buffer_size) { - /* Orphan buffer data and start fresh. */ - glBufferData(GL_DRAW_INDIRECT_BUFFER, list->buffer_size, NULL, GL_DYNAMIC_DRAW); - list->cmd_offset = 0; - } - GLenum flags = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; - list->commands = (GPUDrawCommand *)glMapBufferRange( - GL_DRAW_INDIRECT_BUFFER, list->cmd_offset, list->buffer_size - list->cmd_offset, flags); - } - } - else { - list->cmd_offset = 0; - } -} - -void GPU_draw_list_command_add( - GPUDrawList *list, int v_first, int v_count, int i_first, int i_count) -{ - BLI_assert(list->commands); - - if (v_count == 0 || i_count == 0) { - return; - } - - if (list->base_index != UINT_MAX) { - GPUDrawCommandIndexed *cmd = list->commands_indexed + list->cmd_len; - cmd->v_first = v_first; - cmd->v_count = v_count; - cmd->i_count = i_count; - cmd->base_index = list->base_index; - cmd->i_first = i_first; - } - else { - GPUDrawCommand *cmd = list->commands + list->cmd_len; - cmd->v_first = v_first; - cmd->v_count = v_count; - cmd->i_count = i_count; - cmd->i_first = i_first; - } - - list->cmd_len++; - uint offset = list->cmd_offset + list->cmd_len * sizeof(GPUDrawCommandIndexed); - - if (offset == list->buffer_size) { - GPU_draw_list_submit(list); - GPU_draw_list_init(list, list->batch); - } -} - -void GPU_draw_list_submit(GPUDrawList *list) -{ - GPUBatch *batch = list->batch; - - if (list->cmd_len == 0) { - return; - } - - BLI_assert(list->commands); - BLI_assert(batch->program_in_use); - /* TODO could assert that VAO is bound. */ - - /* TODO We loose a bit of memory here if we only draw arrays. Fix that. */ - uintptr_t offset = list->cmd_offset; - uint cmd_len = list->cmd_len; - size_t bytes_used = cmd_len * sizeof(GPUDrawCommandIndexed); - list->cmd_len = 0; /* Avoid reuse. */ - - /* Only do multi-draw indirect if doing more than 2 drawcall. - * This avoids the overhead of buffer mapping if scene is - * not very instance friendly. - * BUT we also need to take into account the case where only - * a few instances are needed to finish filling a call buffer. */ - const bool do_mdi = (cmd_len > 2) || (list->cmd_offset + bytes_used == list->buffer_size); - - if (USE_MULTI_DRAW_INDIRECT && do_mdi) { - GLenum prim = batch->gl_prim_type; - - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id); - glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, bytes_used); - glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); - list->commands = NULL; /* Unmapped */ - list->cmd_offset += bytes_used; - - if (batch->elem) { - glMultiDrawElementsIndirect(prim, INDEX_TYPE(batch->elem), (void *)offset, cmd_len, 0); - } - else { - glMultiDrawArraysIndirect(prim, (void *)offset, cmd_len, 0); - } - } - else { - /* Fallback */ - if (batch->elem) { - GPUDrawCommandIndexed *cmd = list->commands_indexed; - for (int i = 0; i < cmd_len; i++, cmd++) { - /* Index start was added by Draw manager. Avoid counting it twice. */ - cmd->v_first -= batch->elem->index_start; - GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count); - } - } - else { - GPUDrawCommand *cmd = list->commands; - for (int i = 0; i < cmd_len; i++, cmd++) { - GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count); - } - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Utilities * \{ */ diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index 283784aec20..da0d3cd395f 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -83,12 +83,12 @@ bool GPUContext::is_active_on_thread(void) GPUContext *GPU_context_create(void *ghost_window) { - if (gpu_backend_get() == NULL) { + if (GPUBackend::get() == NULL) { /* TODO move where it make sense. */ GPU_backend_init(GPU_BACKEND_OPENGL); } - GPUContext *ctx = gpu_backend_get()->context_alloc(ghost_window); + GPUContext *ctx = GPUBackend::get()->context_alloc(ghost_window); GPU_context_active_set(ctx); return ctx; @@ -173,14 +173,14 @@ void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx) void GPU_buf_free(GLuint buf_id) { /* TODO avoid using backend */ - GPUBackend *backend = gpu_backend_get(); + GPUBackend *backend = GPUBackend::get(); static_cast<GLBackend *>(backend)->buf_free(buf_id); } void GPU_tex_free(GLuint tex_id) { /* TODO avoid using backend */ - GPUBackend *backend = gpu_backend_get(); + GPUBackend *backend = GPUBackend::get(); static_cast<GLBackend *>(backend)->tex_free(tex_id); } @@ -285,7 +285,7 @@ void GPU_backend_exit(void) delete g_backend; } -GPUBackend *gpu_backend_get(void) +GPUBackend *GPUBackend::get(void) { return g_backend; } diff --git a/source/blender/gpu/intern/gpu_drawlist.cc b/source/blender/gpu/intern/gpu_drawlist.cc new file mode 100644 index 00000000000..7b807a2fa80 --- /dev/null +++ b/source/blender/gpu/intern/gpu_drawlist.cc @@ -0,0 +1,59 @@ +/* + * 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 + * + * Implementation of Multi Draw Indirect. + */ + +#include "MEM_guardedalloc.h" + +#include "GPU_batch.h" +#include "GPU_drawlist.h" + +#include "gpu_backend.hh" + +#include "gpu_drawlist_private.hh" + +using namespace blender::gpu; + +GPUDrawList GPU_draw_list_create(int list_length) +{ + DrawList *list_ptr = GPUBackend::get()->drawlist_alloc(list_length); + return reinterpret_cast<DrawList *>(list_ptr); +} + +void GPU_draw_list_discard(GPUDrawList list) +{ + DrawList *list_ptr = reinterpret_cast<DrawList *>(list); + delete list_ptr; +} + +void GPU_draw_list_append(GPUDrawList list, GPUBatch *batch, int i_first, int i_count) +{ + DrawList *list_ptr = reinterpret_cast<DrawList *>(list); + list_ptr->append(batch, i_first, i_count); +} + +void GPU_draw_list_submit(GPUDrawList list) +{ + DrawList *list_ptr = reinterpret_cast<DrawList *>(list); + list_ptr->submit(); +} diff --git a/source/blender/gpu/intern/gpu_drawlist_private.hh b/source/blender/gpu/intern/gpu_drawlist_private.hh new file mode 100644 index 00000000000..04cc18a5ffd --- /dev/null +++ b/source/blender/gpu/intern/gpu_drawlist_private.hh @@ -0,0 +1,40 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "MEM_guardedalloc.h" + +namespace blender { +namespace gpu { + +class DrawList { + public: + virtual ~DrawList(){}; + + virtual void append(GPUBatch *batch, int i_first, int i_count) = 0; + virtual void submit() = 0; +}; + +} // namespace gpu +} // namespace blender |