Gawain: manage GL buffer IDs in a thread-safe way
Needed because deps graph can destroy objects from any thread. We ran into the same problem & solved it in GPU_buffers. Implemented in C++11 since it provides the needed machinery. The interface is in C like the rest of Gawain.
This commit is contained in:
@@ -70,6 +70,8 @@ set(SRC
|
||||
gawain/attrib_binding.h
|
||||
gawain/batch.c
|
||||
gawain/batch.h
|
||||
gawain/buffer_id.h
|
||||
gawain/buffer_id.cpp
|
||||
gawain/common.h
|
||||
gawain/element.c
|
||||
gawain/element.h
|
||||
|
||||
116
source/blender/gpu/gawain/buffer_id.cpp
Normal file
116
source/blender/gpu/gawain/buffer_id.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
// Gawain buffer IDs
|
||||
//
|
||||
// This code is part of the Gawain library, with modifications
|
||||
// specific to integration with Blender.
|
||||
//
|
||||
// Copyright 2016 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/.#include "buffer_id.h"
|
||||
|
||||
#include "buffer_id.h"
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#define ORPHAN_DEBUG 0
|
||||
|
||||
#if ORPHAN_DEBUG
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
static std::vector<GLuint> orphaned_buffer_ids;
|
||||
static std::vector<GLuint> orphaned_vao_ids;
|
||||
|
||||
static std::mutex orphan_mutex;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
GLuint buffer_id_alloc()
|
||||
{
|
||||
#if TRUST_NO_ONE
|
||||
assert(thread_is_main());
|
||||
#endif
|
||||
|
||||
// delete orphaned IDs
|
||||
orphan_mutex.lock();
|
||||
if (!orphaned_buffer_ids.empty())
|
||||
{
|
||||
const auto orphaned_buffer_ct = (unsigned)orphaned_buffer_ids.size();
|
||||
#if ORPHAN_DEBUG
|
||||
printf("deleting %u orphaned VBO%s\n", orphaned_buffer_ct, orphaned_buffer_ct == 1 ? "" : "s");
|
||||
#endif
|
||||
glDeleteBuffers(orphaned_buffer_ct, orphaned_buffer_ids.data());
|
||||
orphaned_buffer_ids.clear();
|
||||
}
|
||||
orphan_mutex.unlock();
|
||||
|
||||
GLuint new_buffer_id;
|
||||
glGenBuffers(1, &new_buffer_id);
|
||||
return new_buffer_id;
|
||||
}
|
||||
|
||||
void buffer_id_free(GLuint buffer_id)
|
||||
{
|
||||
if (thread_is_main())
|
||||
glDeleteBuffers(1, &buffer_id);
|
||||
else
|
||||
{
|
||||
// add this ID to the orphaned list
|
||||
orphan_mutex.lock();
|
||||
#if ORPHAN_DEBUG
|
||||
printf("orphaning VBO %u\n", buffer_id);
|
||||
#endif
|
||||
orphaned_buffer_ids.emplace_back(buffer_id);
|
||||
orphan_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
GLuint vao_id_alloc()
|
||||
{
|
||||
#if TRUST_NO_ONE
|
||||
assert(thread_is_main());
|
||||
#endif
|
||||
|
||||
GLuint new_vao_id;
|
||||
|
||||
// delete orphaned IDs
|
||||
orphan_mutex.lock();
|
||||
if (!orphaned_vao_ids.empty())
|
||||
{
|
||||
const auto orphaned_vao_ct = (unsigned)orphaned_vao_ids.size();
|
||||
#if ORPHAN_DEBUG
|
||||
printf("deleting %u orphaned VAO%s\n", orphaned_vao_ct, orphaned_vao_ct == 1 ? "" : "s");
|
||||
#endif
|
||||
glDeleteVertexArrays(orphaned_vao_ct, orphaned_vao_ids.data());
|
||||
orphaned_vao_ids.clear();
|
||||
}
|
||||
orphan_mutex.unlock();
|
||||
|
||||
glGenVertexArrays(1, &new_vao_id);
|
||||
return new_vao_id;
|
||||
}
|
||||
|
||||
void vao_id_free(GLuint vao_id)
|
||||
{
|
||||
if (thread_is_main())
|
||||
glDeleteVertexArrays(1, &vao_id);
|
||||
else
|
||||
{
|
||||
// add this ID to the orphaned list
|
||||
orphan_mutex.lock();
|
||||
#if ORPHAN_DEBUG
|
||||
printf("orphaning VAO %u\n", vao_id);
|
||||
#endif
|
||||
orphaned_vao_ids.emplace_back(vao_id);
|
||||
orphan_mutex.unlock();
|
||||
}
|
||||
}
|
||||
34
source/blender/gpu/gawain/buffer_id.h
Normal file
34
source/blender/gpu/gawain/buffer_id.h
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
// Gawain buffer IDs
|
||||
//
|
||||
// This code is part of the Gawain library, with modifications
|
||||
// specific to integration with Blender.
|
||||
//
|
||||
// Copyright 2016 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
|
||||
|
||||
// Manage GL buffer IDs in a thread-safe way
|
||||
// Use these instead of glGenBuffers & its friends
|
||||
// - alloc must be called from main thread
|
||||
// - free can be called from any thread
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
|
||||
GLuint buffer_id_alloc(void);
|
||||
void buffer_id_free(GLuint buffer_id);
|
||||
|
||||
GLuint vao_id_alloc(void);
|
||||
void vao_id_free(GLuint vao_id);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user