Blender  V3.3
gpu_context.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2016 by Mike Erwin. All rights reserved. */
3 
15 /* TODO: Create cmake option. */
16 #if WITH_OPENGL
17 # define WITH_OPENGL_BACKEND 1
18 #endif
19 
20 #include "BLI_assert.h"
21 #include "BLI_utildefines.h"
22 
23 #include "GPU_context.h"
24 #include "GPU_framebuffer.h"
25 
26 #include "gpu_backend.hh"
27 #include "gpu_batch_private.hh"
28 #include "gpu_context_private.hh"
29 #include "gpu_matrix_private.h"
30 #include "gpu_private.h"
31 
32 #ifdef WITH_OPENGL_BACKEND
33 # include "gl_backend.hh"
34 # include "gl_context.hh"
35 #endif
36 #ifdef WITH_METAL_BACKEND
37 # include "mtl_backend.hh"
38 #endif
39 
40 #include <mutex>
41 #include <vector>
42 
43 using namespace blender::gpu;
44 
45 static thread_local Context *active_ctx = nullptr;
46 
48 static int num_backend_users = 0;
49 
50 static void gpu_backend_create();
51 static void gpu_backend_discard();
52 
53 /* -------------------------------------------------------------------- */
57 namespace blender::gpu {
58 
60 {
61  thread_ = pthread_self();
62  is_active_ = false;
64 }
65 
67 {
69  delete state_manager;
70  delete front_left;
71  delete back_left;
72  delete front_right;
73  delete back_right;
74  delete imm;
75 }
76 
78 {
79  return (this == active_ctx) && pthread_equal(pthread_self(), thread_);
80 }
81 
83 {
84  return active_ctx;
85 }
86 
87 } // namespace blender::gpu
88 
91 /* -------------------------------------------------------------------- */
92 
93 GPUContext *GPU_context_create(void *ghost_window)
94 {
95  {
96  std::scoped_lock lock(backend_users_mutex);
97  if (num_backend_users == 0) {
98  /* Automatically create backend when first context is created. */
100  }
102  }
103 
104  Context *ctx = GPUBackend::get()->context_alloc(ghost_window);
105 
107  return wrap(ctx);
108 }
109 
111 {
112  Context *ctx = unwrap(ctx_);
113  delete ctx;
114  active_ctx = nullptr;
115 
116  {
117  std::scoped_lock lock(backend_users_mutex);
120  if (num_backend_users == 0) {
121  /* Discard backend when last context is discarded. */
123  }
124  }
125 }
126 
128 {
129  Context *ctx = unwrap(ctx_);
130 
131  if (active_ctx) {
133  }
134 
135  active_ctx = ctx;
136 
137  if (ctx) {
138  ctx->activate();
139  }
140 }
141 
143 {
144  return wrap(Context::get());
145 }
146 
148 {
149  blender::gpu::Context *_ctx = unwrap(ctx);
150  if (_ctx) {
151  _ctx->begin_frame();
152  }
153 }
154 
156 {
157  blender::gpu::Context *_ctx = unwrap(ctx);
158  if (_ctx) {
159  _ctx->end_frame();
160  }
161 }
162 
163 /* -------------------------------------------------------------------- */
170 
172 {
173  main_context_mutex.lock();
174 }
175 
177 {
178  main_context_mutex.unlock();
179 }
180 
183 /* -------------------------------------------------------------------- */
191 {
192  GPUBackend *backend = GPUBackend::get();
193  BLI_assert(backend);
194  backend->render_begin();
195 }
197 {
198  GPUBackend *backend = GPUBackend::get();
199  BLI_assert(backend);
200  backend->render_end();
201 }
203 {
204  GPUBackend *backend = GPUBackend::get();
205  BLI_assert(backend);
206  backend->render_step();
207 }
208 
211 /* -------------------------------------------------------------------- */
216 static GPUBackend *g_backend = nullptr;
217 
219 {
220  switch (g_backend_type) {
221  case GPU_BACKEND_OPENGL:
222 #ifdef WITH_OPENGL_BACKEND
223  return true;
224 #else
225  return false;
226 #endif
227  case GPU_BACKEND_METAL:
228 #ifdef WITH_METAL_BACKEND
229  return MTLBackend::metal_is_supported();
230 #else
231  return false;
232 #endif
233  default:
234  BLI_assert(false && "No backend specified");
235  return false;
236  }
237 }
238 
239 static void gpu_backend_create()
240 {
241  BLI_assert(g_backend == nullptr);
243 
244  switch (g_backend_type) {
245 #ifdef WITH_OPENGL_BACKEND
246  case GPU_BACKEND_OPENGL:
247  g_backend = new GLBackend;
248  break;
249 #endif
250 #ifdef WITH_METAL_BACKEND
251  case GPU_BACKEND_METAL:
252  g_backend = new MTLBackend;
253  break;
254 #endif
255  default:
256  BLI_assert(0);
257  break;
258  }
259 }
260 
262 {
265 }
266 
268 {
269  /* TODO: assert no resource left. */
270  delete g_backend;
271  g_backend = nullptr;
272 }
273 
275 {
276 
277 #ifdef WITH_OPENGL_BACKEND
278  if (g_backend && dynamic_cast<GLBackend *>(g_backend) != nullptr) {
279  return GPU_BACKEND_OPENGL;
280  }
281 #endif
282 
283 #ifdef WITH_METAL_BACKEND
284  if (g_backend && dynamic_cast<MTLBackend *>(g_backend) != nullptr) {
285  return GPU_BACKEND_METAL;
286  }
287 #endif
288 
289  return GPU_BACKEND_NONE;
290 }
291 
292 GPUBackend *GPUBackend::get()
293 {
294  return g_backend;
295 }
296 
#define BLI_assert(a)
Definition: BLI_assert.h:46
ThreadMutex mutex
struct GPUContext GPUContext
Definition: GPU_context.h:27
eGPUBackendType
Definition: GPU_platform.h:15
@ GPU_BACKEND_NONE
Definition: GPU_platform.h:16
@ GPU_BACKEND_METAL
Definition: GPU_platform.h:18
@ GPU_BACKEND_OPENGL
Definition: GPU_platform.h:17
volatile int lock
static Context * get()
Definition: gpu_context.cc:82
GPUMatrixState * matrix_state
virtual void activate()=0
virtual void end_frame()=0
virtual void begin_frame()=0
virtual void deactivate()=0
virtual void render_end()=0
virtual void delete_resources()=0
virtual void render_begin()=0
virtual void render_step()=0
void GPU_render_end()
Definition: gpu_context.cc:196
GPUContext * GPU_context_active_get()
Definition: gpu_context.cc:142
static const eGPUBackendType g_backend_type
Definition: gpu_context.cc:215
void GPU_context_main_lock()
Definition: gpu_context.cc:171
static thread_local Context * active_ctx
Definition: gpu_context.cc:45
void GPU_context_begin_frame(GPUContext *ctx)
Definition: gpu_context.cc:147
static std::mutex backend_users_mutex
Definition: gpu_context.cc:47
static int num_backend_users
Definition: gpu_context.cc:48
void GPU_render_begin()
Definition: gpu_context.cc:190
void GPU_context_active_set(GPUContext *ctx_)
Definition: gpu_context.cc:127
static void gpu_backend_discard()
Definition: gpu_context.cc:267
void GPU_render_step()
Definition: gpu_context.cc:202
void gpu_backend_delete_resources()
Definition: gpu_context.cc:261
void GPU_context_discard(GPUContext *ctx_)
Definition: gpu_context.cc:110
static std::mutex main_context_mutex
Definition: gpu_context.cc:169
void GPU_context_main_unlock()
Definition: gpu_context.cc:176
static void gpu_backend_create()
Definition: gpu_context.cc:239
GPUContext * GPU_context_create(void *ghost_window)
Definition: gpu_context.cc:93
void GPU_context_end_frame(GPUContext *ctx)
Definition: gpu_context.cc:155
static GPUBackend * g_backend
Definition: gpu_context.cc:216
eGPUBackendType GPU_backend_get_type()
Definition: gpu_context.cc:274
bool GPU_backend_supported(void)
Definition: gpu_context.cc:218
GPUMatrixState * GPU_matrix_state_create()
Definition: gpu_matrix.cc:54
void GPU_matrix_state_discard(GPUMatrixState *state)
Definition: gpu_matrix.cc:75
static PartialUpdateUserImpl * unwrap(struct PartialUpdateUser *user)
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)