Blender V4.3
gpu_context.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 by Mike Erwin. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
16#include "GHOST_C-api.h"
17
18#include "BKE_global.hh"
19
20#include "BLI_assert.h"
21#include "BLI_utildefines.h"
22#include "BLI_vector_set.hh"
23
24#include "GPU_context.hh"
25#include "GPU_framebuffer.hh"
26
27#include "GPU_batch.hh"
28#include "gpu_backend.hh"
30#include "gpu_matrix_private.hh"
31#include "gpu_private.hh"
32#include "gpu_shader_private.hh"
33
34#ifdef WITH_OPENGL_BACKEND
35# include "gl_backend.hh"
36# include "gl_context.hh"
37#endif
38#ifdef WITH_VULKAN_BACKEND
39# include "vk_backend.hh"
40#endif
41#ifdef WITH_METAL_BACKEND
42# include "mtl_backend.hh"
43#endif
44#include "dummy_backend.hh"
45
46#include <mutex>
47#include <vector>
48
49using namespace blender::gpu;
50
51static thread_local Context *active_ctx = nullptr;
52
53static std::mutex backend_users_mutex;
54static int num_backend_users = 0;
55
56static void gpu_backend_create();
57static void gpu_backend_discard();
58
59/* -------------------------------------------------------------------- */
63namespace blender::gpu {
64
75
77{
79 delete state_manager;
80 delete front_left;
81 delete back_left;
82 delete front_right;
83 delete back_right;
84 delete imm;
85}
86
88{
89 return (this == active_ctx) && pthread_equal(pthread_self(), thread_);
90}
91
93{
94 return active_ctx;
95}
96
97} // namespace blender::gpu
98
101/* -------------------------------------------------------------------- */
102
103GPUContext *GPU_context_create(void *ghost_window, void *ghost_context)
104{
105 {
106 std::scoped_lock lock(backend_users_mutex);
107 if (num_backend_users == 0) {
108 /* Automatically create backend when first context is created. */
110 }
112 }
113
114 Context *ctx = GPUBackend::get()->context_alloc(ghost_window, ghost_context);
115
117 return wrap(ctx);
118}
119
121{
122 Context *ctx = unwrap(ctx_);
123 printf_end(ctx);
124 delete ctx;
125 active_ctx = nullptr;
126
127 {
128 std::scoped_lock lock(backend_users_mutex);
131 if (num_backend_users == 0) {
132 /* Discard backend when last context is discarded. */
134 }
135 }
136}
137
139{
140 Context *ctx = unwrap(ctx_);
141
142 if (active_ctx) {
145 }
146
147 active_ctx = ctx;
148
149 if (ctx) {
150 ctx->activate();
151 printf_begin(ctx);
152 }
153}
154
159
161{
162 blender::gpu::Context *_ctx = unwrap(ctx);
163 if (_ctx) {
164 _ctx->begin_frame();
165 }
166}
167
169{
170 blender::gpu::Context *_ctx = unwrap(ctx);
171 if (_ctx) {
172 _ctx->end_frame();
173 }
174}
175
176/* -------------------------------------------------------------------- */
182static std::mutex main_context_mutex;
183
185{
186 main_context_mutex.lock();
187}
188
190{
191 main_context_mutex.unlock();
192}
193
196/* -------------------------------------------------------------------- */
204{
205 GPUBackend *backend = GPUBackend::get();
206 BLI_assert(backend);
207 /* WORKAROUND: Currently a band-aid for the heist production. Has no side effect for GL backend
208 * but should be fixed for Metal. */
209 if (backend) {
210 backend->render_begin();
213 }
214}
216{
217 GPUBackend *backend = GPUBackend::get();
218 BLI_assert(backend);
219 if (backend) {
222 backend->render_end();
223 }
224}
226{
227 GPUBackend *backend = GPUBackend::get();
228 BLI_assert(backend);
229 if (backend) {
231 backend->render_step();
233 }
234}
235
238/* -------------------------------------------------------------------- */
243static std::optional<eGPUBackendType> g_backend_type_override = std::nullopt;
244static std::optional<bool> g_backend_type_supported = std::nullopt;
245static GPUBackend *g_backend = nullptr;
246static GHOST_SystemHandle g_ghost_system = nullptr;
247
248void GPU_backend_ghost_system_set(void *ghost_system_handle)
249{
250 g_ghost_system = reinterpret_cast<GHOST_SystemHandle>(ghost_system_handle);
251}
252
254{
255 return g_ghost_system;
256}
257
259{
260 g_backend_type = backend;
261 g_backend_type_supported = std::nullopt;
262}
263
268
270{
271 g_backend_type_override = backend_type;
272}
273
278
280{
281 blender::VectorSet<eGPUBackendType> backends_to_check;
283 backends_to_check.add(*g_backend_type_override);
284 }
285#if defined(WITH_OPENGL_BACKEND)
286 backends_to_check.add(GPU_BACKEND_OPENGL);
287#elif defined(WITH_METAL_BACKEND)
288 backends_to_check.add(GPU_BACKEND_METAL);
289#endif
290
291 for (const eGPUBackendType backend_type : backends_to_check) {
292 GPU_backend_type_selection_set(backend_type);
293 if (GPU_backend_supported()) {
294 return true;
295 }
297 }
298
300 return false;
301}
302
304{
305 switch (g_backend_type) {
307#ifdef WITH_OPENGL_BACKEND
308 return true;
309#else
310 return false;
311#endif
313#ifdef WITH_VULKAN_BACKEND
315#else
316 return false;
317#endif
319#ifdef WITH_METAL_BACKEND
321#else
322 return false;
323#endif
324 case GPU_BACKEND_NONE:
325 return true;
326 default:
327 BLI_assert(false && "No backend specified");
328 return false;
329 }
330}
331
339
341{
342 BLI_assert(g_backend == nullptr);
344
345 switch (g_backend_type) {
346#ifdef WITH_OPENGL_BACKEND
348 g_backend = new GLBackend;
349 break;
350#endif
351#ifdef WITH_VULKAN_BACKEND
353 g_backend = new VKBackend;
354 break;
355#endif
356#ifdef WITH_METAL_BACKEND
358 g_backend = new MTLBackend;
359 break;
360#endif
361 case GPU_BACKEND_NONE:
363 break;
364 default:
365 BLI_assert(0);
366 break;
367 }
368}
369
375
377{
378 /* TODO: assert no resource left. */
379 delete g_backend;
380 g_backend = nullptr;
381}
382
384{
385
386#ifdef WITH_OPENGL_BACKEND
387 if (g_backend && dynamic_cast<GLBackend *>(g_backend) != nullptr) {
388 return GPU_BACKEND_OPENGL;
389 }
390#endif
391
392#ifdef WITH_METAL_BACKEND
393 if (g_backend && dynamic_cast<MTLBackend *>(g_backend) != nullptr) {
394 return GPU_BACKEND_METAL;
395 }
396#endif
397
398#ifdef WITH_VULKAN_BACKEND
399 if (g_backend && dynamic_cast<VKBackend *>(g_backend) != nullptr) {
400 return GPU_BACKEND_VULKAN;
401 }
402#endif
403
404 return GPU_BACKEND_NONE;
405}
406
408{
409 return g_backend;
410}
411
@ G_FLAG_GPU_BACKEND_FALLBACK
#define BLI_assert(a)
Definition BLI_assert.h:50
GHOST C-API function and type declarations.
void GPU_render_end()
GPUContext * GPU_context_create(void *ghost_window, void *ghost_context)
void GPU_context_main_lock()
void GPU_backend_type_selection_set(const eGPUBackendType backend)
bool GPU_backend_supported()
void * GPU_backend_ghost_system_get()
void GPU_context_begin_frame(GPUContext *ctx)
void GPU_render_begin()
bool GPU_backend_type_selection_is_overridden()
GPUContext * GPU_context_active_get()
eGPUBackendType GPU_backend_type_selection_get()
void GPU_render_step()
void GPU_context_main_unlock()
void GPU_context_discard(GPUContext *)
bool GPU_backend_type_selection_detect()
void GPU_context_end_frame(GPUContext *ctx)
void GPU_context_active_set(GPUContext *)
eGPUBackendType GPU_backend_get_type()
void GPU_backend_ghost_system_set(void *ghost_system_handle)
void GPU_backend_type_selection_set_override(eGPUBackendType backend_type)
volatile int lock
struct GPUContext GPUContext
bool add(const Key &key)
static Context * get()
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
static GPUBackend * get()
virtual void delete_resources()=0
virtual void render_begin()=0
virtual Context * context_alloc(void *ghost_window, void *ghost_context)=0
virtual void render_step()=0
static bool metal_is_supported()
static bool is_supported()
static std::optional< bool > g_backend_type_supported
static bool gpu_backend_supported()
static thread_local Context * active_ctx
static std::mutex backend_users_mutex
static int num_backend_users
static eGPUBackendType g_backend_type
static void gpu_backend_discard()
void gpu_backend_delete_resources()
static std::mutex main_context_mutex
static void gpu_backend_create()
static GHOST_SystemHandle g_ghost_system
static GPUBackend * g_backend
static std::optional< eGPUBackendType > g_backend_type_override
GPUMatrixState * GPU_matrix_state_create()
Definition gpu_matrix.cc:55
void GPU_matrix_state_discard(GPUMatrixState *state)
Definition gpu_matrix.cc:76
#define G(x, y, z)
static Context * unwrap(GPUContext *ctx)
static GPUContext * wrap(Context *ctx)
void printf_begin(Context *ctx)
void printf_end(Context *ctx)