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:
authorSergey Sharybin <sergey.vfx@gmail.com>2015-11-04 19:30:25 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2015-11-04 19:30:25 +0300
commita5f4f1e2cea831415c045be4927320dc060798c9 (patch)
tree6ba079a4cadf5bdb10d6815326b42ebbd83259d0 /source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
parent4ff6e08a6df9dedfe26df539c1147481da07a9de (diff)
OpenSubdiv: Use pool for delayed OpenGL buffers free when freeing from non-main thread
This is really similar to what GPU module was already doing. There are number of possible improvements still: - Re-use allocated VAOs when requesting new ones instead of going to the trouble of freeing VAO and then re-creating it again. - Move VAO handling to GPU module. Fixes T46589: OpenSubdiv crash with drivers
Diffstat (limited to 'source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c')
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c88
1 files changed, 85 insertions, 3 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index 9d5ef1079b8..0f61a50ed13 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -28,12 +28,15 @@
#include "BLI_sys_types.h" // for intptr_t support
#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
#include "CCGSubSurf.h"
#include "CCGSubSurf_intern.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_subsurf.h"
#include "DNA_userdef_types.h"
@@ -236,7 +239,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
if (ss->osd_mesh_invalid) {
if (ss->osd_mesh != NULL) {
- openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
ss->osd_mesh = NULL;
}
ss->osd_mesh_invalid = false;
@@ -897,8 +900,7 @@ void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss)
void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss)
{
if (ss->osd_mesh != NULL) {
- /* TODO(sergey): Make sure free happens form the main thread! */
- openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
ss->osd_mesh = NULL;
}
if (ss->osd_vao != 0) {
@@ -921,4 +923,84 @@ void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3])
}
}
+/* ** Delayed delete routines ** */
+
+typedef struct OsdDeletePendingItem {
+ struct OsdDeletePendingItem *next, *prev;
+ OpenSubdiv_GLMesh *osd_mesh;
+ unsigned int vao;
+} OsdDeletePendingItem;
+
+static SpinLock delete_spin;
+static ListBase delete_pool = {NULL, NULL};
+
+static void delete_pending_push(OpenSubdiv_GLMesh *osd_mesh,
+ unsigned int vao)
+{
+ OsdDeletePendingItem *new_entry = MEM_mallocN(sizeof(OsdDeletePendingItem),
+ "opensubdiv delete entry");
+ new_entry->osd_mesh = osd_mesh;
+ new_entry->vao = vao;
+ BLI_spin_lock(&delete_spin);
+ BLI_addtail(&delete_pool, new_entry);
+ BLI_spin_unlock(&delete_spin);
+}
+
+void ccgSubSurf__delete_osdGLMesh(OpenSubdiv_GLMesh *osd_mesh)
+{
+ if (BLI_thread_is_main()) {
+ openSubdiv_deleteOsdGLMesh(osd_mesh);
+ }
+ else {
+ delete_pending_push(osd_mesh, 0);
+ }
+}
+
+void ccgSubSurf__delete_vertex_array(unsigned int vao)
+{
+ if (BLI_thread_is_main()) {
+ glDeleteVertexArrays(1, &vao);
+ }
+ else {
+ delete_pending_push(NULL, vao);
+ }
+}
+
+void ccgSubSurf__delete_pending(void)
+{
+ OsdDeletePendingItem *entry;
+ BLI_assert(BLI_thread_is_main());
+ BLI_spin_lock(&delete_spin);
+ for (entry = delete_pool.first; entry != NULL; entry = entry->next) {
+ if (entry->osd_mesh != NULL) {
+ openSubdiv_deleteOsdGLMesh(entry->osd_mesh);
+ }
+ if (entry->vao != 0) {
+ glDeleteVertexArrays(1, &entry->vao);
+ }
+ }
+ BLI_freelistN(&delete_pool);
+ BLI_spin_unlock(&delete_spin);
+}
+
+/* ** Public API ** */
+
+void BKE_subsurf_osd_init(void)
+{
+ openSubdiv_init();
+ BLI_spin_init(&delete_spin);
+}
+
+void BKE_subsurf_free_unused_buffers(void)
+{
+ ccgSubSurf__delete_pending();
+}
+
+void BKE_subsurf_osd_cleanup(void)
+{
+ openSubdiv_cleanup();
+ ccgSubSurf__delete_pending();
+ BLI_spin_end(&delete_spin);
+}
+
#endif /* WITH_OPENSUBDIV */