GPUBackend: Add new GPUBackend object to manage GL object allocations

This just set a global object responsible for allocating new objects
in a thread safe way without needing any GPUContext bound to this
thread.

This also introduce the GLContext which will contain all the GL related
functions for the current context.
This commit is contained in:
Clément Foucault 2020-08-07 17:00:28 +02:00
parent 0ccf3f89d2
commit 1dd7377596
9 changed files with 287 additions and 49 deletions

View File

@ -28,6 +28,8 @@ endif()
set(INC
.
intern
opengl
../blenkernel
../blenlib
../bmesh
@ -86,6 +88,8 @@ set(SRC
intern/gpu_vertex_format.cc
intern/gpu_viewport.c
opengl/gl_context.cc
GPU_attr_binding.h
GPU_batch.h
GPU_batch_presets.h
@ -117,6 +121,7 @@ set(SRC
GPU_viewport.h
intern/gpu_attr_binding_private.h
intern/gpu_backend.hh
intern/gpu_batch_private.h
intern/gpu_codegen.h
intern/gpu_context_private.h
@ -128,6 +133,9 @@ set(SRC
intern/gpu_select_private.h
intern/gpu_shader_private.h
intern/gpu_vertex_format_private.h
opengl/gl_backend.hh
opengl/gl_context.hh
)
set(LIB

View File

@ -35,6 +35,14 @@ extern "C" {
typedef struct GPUContext GPUContext;
typedef enum eGPUBackendType {
GPU_BACKEND_NONE = 0,
GPU_BACKEND_OPENGL,
} eGPUBackendType;
void GPU_backend_init(eGPUBackendType backend);
void GPU_backend_exit(void);
GPUContext *GPU_context_create(void *ghost_window);
void GPU_context_discard(GPUContext *);

View File

@ -0,0 +1,37 @@
/*
* 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.
*
* Copyright 2020, Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup gpu
*
* GPUBackend derived class contain allocators that do not need a context bound.
* The backend is init at startup and is accessible using GPU_backend_get() */
#pragma once
struct GPUContext;
class GPUBackend {
public:
virtual ~GPUBackend(){};
virtual GPUContext *context_alloc(void *ghost_window) = 0;
};
GPUBackend *gpu_backend_get(void);

View File

@ -28,6 +28,9 @@
* - free can be called from any thread
*/
/* TODO Create cmake option. */
#define WITH_OPENGL_BACKEND 1
#include "BLI_assert.h"
#include "BLI_utildefines.h"
@ -36,63 +39,25 @@
#include "GHOST_C-api.h"
#include "gpu_backend.hh"
#include "gpu_batch_private.h"
#include "gpu_context_private.h"
#include "gpu_matrix_private.h"
#include <mutex>
#include <pthread.h>
#include <string.h>
#include <unordered_set>
#include <vector>
#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
#ifdef WITH_OPENGL_BACKEND
# include "gl_backend.hh"
# include "gl_context.hh"
#endif
#include <mutex>
#include <vector>
static std::vector<GLuint> orphaned_buffer_ids;
static std::vector<GLuint> orphaned_texture_ids;
static std::mutex orphans_mutex;
static std::mutex main_context_mutex;
struct GPUContext {
GLuint default_vao;
GLuint default_framebuffer;
GPUFrameBuffer *current_fbo;
std::unordered_set<GPUBatch *> batches; /* Batches that have VAOs from this context */
#ifdef DEBUG
std::unordered_set<GPUFrameBuffer *>
framebuffers; /* Framebuffers that have FBO from this context */
#endif
struct GPUMatrixState *matrix_state;
std::vector<GLuint> orphaned_vertarray_ids;
std::vector<GLuint> orphaned_framebuffer_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;
#endif
GPUContext()
{
#if TRUST_NO_ONE
thread_is_used = false;
#endif
current_fbo = 0;
}
};
static thread_local GPUContext *active_ctx = NULL;
static void orphans_add(GPUContext *ctx, std::vector<GLuint> *orphan_list, GLuint id)
@ -142,8 +107,12 @@ static void orphans_clear(GPUContext *ctx)
GPUContext *GPU_context_create(void *ghost_window)
{
/* BLI_assert(thread_is_main()); */
GPUContext *ctx = new GPUContext;
if (gpu_backend_get() == NULL) {
/* TODO move where it make sense. */
GPU_backend_init(GPU_BACKEND_OPENGL);
}
GPUContext *ctx = gpu_backend_get()->context_alloc(ghost_window);
glGenVertexArrays(1, &ctx->default_vao);
if (ghost_window != NULL) {
ctx->default_framebuffer = GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window);
@ -364,3 +333,37 @@ void GPU_context_main_unlock(void)
{
main_context_mutex.unlock();
}
/* -------------------------------------------------------------------- */
/** \name Backend selection
* \{ */
static GPUBackend *g_backend;
void GPU_backend_init(eGPUBackendType backend_type)
{
BLI_assert(g_backend == NULL);
switch (backend_type) {
#if WITH_OPENGL_BACKEND
case GPU_BACKEND_OPENGL:
g_backend = new GLBackend;
break;
#endif
default:
BLI_assert(0);
break;
}
}
void GPU_backend_exit(void)
{
delete g_backend;
}
GPUBackend *gpu_backend_get(void)
{
return g_backend;
}
/** \} */

View File

@ -27,12 +27,52 @@
#include "GPU_context.h"
/* TODO cleanup this ifdef */
#ifdef __cplusplus
# include <mutex>
# include <pthread.h>
# include <string.h>
# include <unordered_set>
# include <vector>
struct GPUFrameBuffer;
struct GPUContext {
GLuint default_vao;
GLuint default_framebuffer;
GPUFrameBuffer *current_fbo;
std::unordered_set<GPUBatch *> batches; /* Batches that have VAOs from this context */
# ifdef DEBUG
std::unordered_set<GPUFrameBuffer *>
framebuffers; /* Framebuffers that have FBO from this context */
# endif
struct GPUMatrixState *matrix_state;
std::vector<GLuint> orphaned_vertarray_ids;
std::vector<GLuint> orphaned_framebuffer_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;
# endif
GPUContext()
{
# if TRUST_NO_ONE
thread_is_used = false;
# endif
current_fbo = 0;
};
virtual ~GPUContext(){};
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct GPUFrameBuffer;
GLuint GPU_vao_default(void);
GLuint GPU_framebuffer_default(void);

View File

@ -26,6 +26,7 @@
#include "BLI_sys_types.h"
#include "GPU_batch.h"
#include "GPU_buffers.h"
#include "GPU_context.h"
#include "GPU_immediate.h"
#include "intern/gpu_codegen.h"
@ -92,6 +93,8 @@ void GPU_exit(void)
gpu_extensions_exit();
gpu_platform_exit(); /* must come last */
GPU_backend_exit();
initialized = false;
}

View File

@ -0,0 +1,36 @@
/*
* 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.
*
* Copyright 2020, Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup gpu
*/
#pragma once
#include "gpu_backend.hh"
#include "gl_context.hh"
class GLBackend : public GPUBackend {
public:
GPUContext *context_alloc(void *ghost_window)
{
return new GLContext(ghost_window);
};
};

View File

@ -0,0 +1,53 @@
/*
* 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.
*
* Copyright 2020, Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup gpu
*/
#include "BLI_assert.h"
#include "BLI_utildefines.h"
#include "GPU_framebuffer.h"
#include "GHOST_C-api.h"
#include "gpu_context_private.h"
#include "gl_context.hh"
// TODO(fclem) this requires too much refactor for now.
// using namespace blender::gpu;
/* -------------------------------------------------------------------- */
/** \name Constructor / Destructor
* \{ */
GLContext::GLContext(void *ghost_window) : GPUContext()
{
default_framebuffer_ = ghost_window ?
GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window) :
0;
}
GLContext::~GLContext()
{
}
/** \} */

View File

@ -0,0 +1,50 @@
/*
* 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.
*
* Copyright 2020, Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup gpu
*/
#pragma once
#include "gpu_context_private.h"
#include "glew-mx.h"
#include <iostream>
#include <mutex>
#include <unordered_set>
#include <vector>
// TODO(fclem) this requires too much refactor for now.
// namespace blender {
// namespace gpu {
class GLContext : public GPUContext {
public:
GLContext(void *ghost_window);
~GLContext();
private:
/** Default framebuffer object for some GL implementation. */
GLuint default_framebuffer_;
};
// } // namespace gpu
// } // namespace blender