diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-07-17 22:11:23 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-07-18 01:17:57 +0300 |
commit | 247ad2034de2c33a6d9cb7d3b6f1ef7ffa5b859d (patch) | |
tree | 153014a1b6f2fc8c09dddb11ef752eae047b3509 /source/blender/gpu/intern/gpu_vertex_array_id.cpp | |
parent | 6329629bb9eab86a989367a148154a7ebfa074df (diff) |
GWN: Port to GPU module: Move files to GPU
This does not include all the struct and type renaming. Only files were
renamed.
gwn_batch.c/h was fusioned with GPU_batch.c/h
gwn_immediate.c/h was fusioned with GPU_immediate.c/h
gwn_imm_util.c/h was fusioned with GPU_immediate_util.c/h
Diffstat (limited to 'source/blender/gpu/intern/gpu_vertex_array_id.cpp')
-rw-r--r-- | source/blender/gpu/intern/gpu_vertex_array_id.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/source/blender/gpu/intern/gpu_vertex_array_id.cpp b/source/blender/gpu/intern/gpu_vertex_array_id.cpp new file mode 100644 index 00000000000..de5be15ec19 --- /dev/null +++ b/source/blender/gpu/intern/gpu_vertex_array_id.cpp @@ -0,0 +1,196 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * Contributor(s): Blender Foundation, Clément Foucault + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_vertex_array_id.cpp + * \ingroup gpu + * + * Manage GL vertex array IDs in a thread-safe way + * Use these instead of glGenBuffers & its friends + * - alloc must be called from a thread that is bound + * to the context that will be used for drawing with + * this vao. + * - free can be called from any thread + */ + +#include "gpu_batch_private.h" +#include "GPU_vertex_array_id.h" +#include "GPU_context.h" +#include <vector> +#include <string.h> +#include <pthread.h> +#include <mutex> +#include <unordered_set> + +#if TRUST_NO_ONE +#if 0 +extern "C" { +extern int BLI_thread_is_main(void); /* Blender-specific function */ +} + +static bool thread_is_main() { + /* "main" here means the GL context's thread */ + return BLI_thread_is_main(); +} +#endif +#endif + +struct Gwn_Context { + GLuint default_vao; + std::unordered_set<Gwn_Batch*> batches; /* Batches that have VAOs from this context */ + std::vector<GLuint> orphaned_vertarray_ids; + std::mutex orphans_mutex; /* todo: try spinlock instead */ +#if TRUST_NO_ONE + pthread_t thread; /* Thread on which this context is active. */ + bool thread_is_used; + + Gwn_Context() { + thread_is_used = false; + } +#endif +}; + +#if defined(_MSC_VER) && (_MSC_VER == 1800) +#define thread_local __declspec(thread) +thread_local Gwn_Context* active_ctx = NULL; +#else +static thread_local Gwn_Context* active_ctx = NULL; +#endif + +static void clear_orphans(Gwn_Context* ctx) +{ + ctx->orphans_mutex.lock(); + if (!ctx->orphaned_vertarray_ids.empty()) { + uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size(); + glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data()); + ctx->orphaned_vertarray_ids.clear(); + } + ctx->orphans_mutex.unlock(); +} + +Gwn_Context* GWN_context_create(void) +{ +#if TRUST_NO_ONE + /* assert(thread_is_main()); */ +#endif + Gwn_Context* ctx = new Gwn_Context; + glGenVertexArrays(1, &ctx->default_vao); + GWN_context_active_set(ctx); + return ctx; +} + +/* to be called after GWN_context_active_set(ctx_to_destroy) */ +void GWN_context_discard(Gwn_Context* ctx) +{ +#if TRUST_NO_ONE + /* Make sure no other thread has locked it. */ + assert(ctx == active_ctx); + assert(pthread_equal(pthread_self(), ctx->thread)); + assert(ctx->orphaned_vertarray_ids.empty()); +#endif + /* delete remaining vaos */ + while (!ctx->batches.empty()) { + /* this removes the array entry */ + gwn_batch_vao_cache_clear(*ctx->batches.begin()); + } + glDeleteVertexArrays(1, &ctx->default_vao); + delete ctx; + active_ctx = NULL; +} + +/* ctx can be NULL */ +void GWN_context_active_set(Gwn_Context* ctx) +{ +#if TRUST_NO_ONE + if (active_ctx) { + active_ctx->thread_is_used = false; + } + /* Make sure no other context is already bound to this thread. */ + if (ctx) { + /* Make sure no other thread has locked it. */ + assert(ctx->thread_is_used == false); + ctx->thread = pthread_self(); + ctx->thread_is_used = true; + } +#endif + if (ctx) { + clear_orphans(ctx); + } + active_ctx = ctx; +} + +Gwn_Context* GWN_context_active_get(void) +{ + return active_ctx; +} + +GLuint GWN_vao_default(void) +{ +#if TRUST_NO_ONE + assert(active_ctx); /* need at least an active context */ + assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ +#endif + return active_ctx->default_vao; +} + +GLuint GWN_vao_alloc(void) +{ +#if TRUST_NO_ONE + assert(active_ctx); /* need at least an active context */ + assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ +#endif + clear_orphans(active_ctx); + + GLuint new_vao_id = 0; + glGenVertexArrays(1, &new_vao_id); + return new_vao_id; +} + +/* this can be called from multiple thread */ +void GWN_vao_free(GLuint vao_id, Gwn_Context* ctx) +{ +#if TRUST_NO_ONE + assert(ctx); +#endif + if (ctx == active_ctx) { + glDeleteVertexArrays(1, &vao_id); + } + else { + ctx->orphans_mutex.lock(); + ctx->orphaned_vertarray_ids.emplace_back(vao_id); + ctx->orphans_mutex.unlock(); + } +} + +void gwn_context_add_batch(Gwn_Context* ctx, Gwn_Batch* batch) +{ + ctx->batches.emplace(batch); +} + +void gwn_context_remove_batch(Gwn_Context* ctx, Gwn_Batch* batch) +{ + ctx->orphans_mutex.lock(); + ctx->batches.erase(batch); + ctx->orphans_mutex.unlock(); +} |