Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-02-20 01:50:52 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-02-21 17:28:26 +0300
commit1b3f9ecd0d0bdf20de24f72d73517cc97d925a15 (patch)
treee56337f844a8f58ce249d28ae60486f94175c718 /intern/gawain
parentd4ee0cee51e01cf62acc1e239844fcb6c7dbf449 (diff)
Gawain: Add new context/vao manager.
This allows allocation of VAOs from different opengl contexts and thread as long as the drawing happens in the same context. Allocation is thread safe as long as we abide by the "one opengl context per thread" rule. We can still free from any thread and actual freeing will occur at new vao allocation or next context binding.
Diffstat (limited to 'intern/gawain')
-rw-r--r--intern/gawain/gawain/gwn_context.h34
-rw-r--r--intern/gawain/gawain/gwn_vertex_array_id.h34
-rw-r--r--intern/gawain/src/gwn_vertex_array_id.cpp136
3 files changed, 204 insertions, 0 deletions
diff --git a/intern/gawain/gawain/gwn_context.h b/intern/gawain/gawain/gwn_context.h
new file mode 100644
index 00000000000..3addce762b3
--- /dev/null
+++ b/intern/gawain/gawain/gwn_context.h
@@ -0,0 +1,34 @@
+
+// Gawain context
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2018 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+// This interface allow Gawain to manage VAOs for mutiple context and threads.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gwn_common.h"
+#include "gwn_batch.h"
+#include "gwn_shader_interface.h"
+
+typedef struct Gwn_Context Gwn_Context;
+
+Gwn_Context* GWN_context_create(void);
+void GWN_context_discard(Gwn_Context*);
+
+void GWN_context_active_set(Gwn_Context*);
+Gwn_Context* GWN_context_active_get(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/intern/gawain/gawain/gwn_vertex_array_id.h b/intern/gawain/gawain/gwn_vertex_array_id.h
new file mode 100644
index 00000000000..6d2a059b9bd
--- /dev/null
+++ b/intern/gawain/gawain/gwn_vertex_array_id.h
@@ -0,0 +1,34 @@
+
+// Gawain buffer IDs
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2018 Mike Erwin, Clément Foucault
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+// 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gwn_common.h"
+#include "gwn_context.h"
+
+GLuint GWN_vao_default(void);
+GLuint GWN_vao_alloc_new(void);
+void GWN_vao_free_new(GLuint vao_id, Gwn_Context*);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/intern/gawain/src/gwn_vertex_array_id.cpp b/intern/gawain/src/gwn_vertex_array_id.cpp
new file mode 100644
index 00000000000..602c1c4919c
--- /dev/null
+++ b/intern/gawain/src/gwn_vertex_array_id.cpp
@@ -0,0 +1,136 @@
+
+// Gawain vertex array IDs
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin, Clément Foucault
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.#include "buffer_id.h"
+
+#include "gwn_vertex_array_id.h"
+#include "gwn_context.h"
+#include <vector>
+#include <string.h>
+#include <pthread.h>
+#include <mutex>
+
+#if TRUST_NO_ONE
+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
+
+struct Gwn_Context {
+ GLuint default_vao;
+ 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.
+#endif
+};
+
+static thread_local Gwn_Context* active_ctx = NULL;
+
+static void clear_orphans(Gwn_Context* ctx)
+ {
+ ctx->orphans_mutex.lock();
+ if (!ctx->orphaned_vertarray_ids.empty())
+ {
+ unsigned orphan_ct = (unsigned)ctx->orphaned_vertarray_ids.size();
+ glDeleteVertexArrays(orphan_ct, 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 = (Gwn_Context*)calloc(1, sizeof(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(ctx->thread == pthread_self());
+ assert(ctx->orphaned_vertarray_ids.empty());
+#endif
+ glDeleteVertexArrays(1, &ctx->default_vao);
+ free(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 = 0;
+ // Make sure no other context is already bound to this thread.
+ if (ctx)
+ {
+ // Make sure no other thread has locked it.
+ assert(ctx->thread == 0);
+ ctx->thread = pthread_self();
+ }
+#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(active_ctx->thread == pthread_self()); // context has been activated by another thread!
+#endif
+ return active_ctx->default_vao;
+ }
+
+GLuint GWN_vao_alloc_new(void)
+ {
+#if TRUST_NO_ONE
+ assert(active_ctx); // need at least an active context
+ assert(active_ctx->thread == pthread_self()); // 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_new(GLuint vao_id, Gwn_Context* ctx)
+ {
+ 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();
+ }
+ }