Blender V4.5
gpu_state.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#ifndef GPU_STANDALONE
10# include "DNA_userdef_types.h"
11# define PIXELSIZE (U.pixelsize)
12#else
13# define PIXELSIZE (1.0f)
14#endif
15
16#include "BLI_math_vector.h"
17#include "BLI_utildefines.h"
18
19#include "GPU_state.hh"
20
21#include "gpu_backend.hh"
23
24#include "gpu_state_private.hh"
25
26using namespace blender::gpu;
27
28#define SET_STATE(_prefix, _state, _value) \
29 do { \
30 StateManager *stack = Context::get()->state_manager; \
31 auto &state_object = stack->_prefix##state; \
32 state_object._state = (_value); \
33 } while (0)
34
35#define SET_IMMUTABLE_STATE(_state, _value) SET_STATE(, _state, _value)
36#define SET_MUTABLE_STATE(_state, _value) SET_STATE(mutable_, _state, _value)
37
38/* -------------------------------------------------------------------- */
41
46
48{
49 SET_IMMUTABLE_STATE(culling_test, culling);
50}
51
57
59{
60 SET_IMMUTABLE_STATE(invert_facing, invert);
61}
62
64{
65 SET_IMMUTABLE_STATE(provoking_vert, vert);
66}
67
69{
70 SET_IMMUTABLE_STATE(depth_test, test);
71}
72
74{
75 SET_IMMUTABLE_STATE(stencil_test, test);
76}
77
78void GPU_line_smooth(bool enable)
79{
80 SET_IMMUTABLE_STATE(line_smooth, enable);
81}
82
83void GPU_polygon_smooth(bool enable)
84{
85 SET_IMMUTABLE_STATE(polygon_smooth, enable);
86}
87
88void GPU_logic_op_xor_set(bool enable)
89{
90 SET_IMMUTABLE_STATE(logic_op_xor, enable);
91}
92
97
98void GPU_color_mask(bool r, bool g, bool b, bool a)
99{
101 auto &state = stack->state;
102 uint32_t write_mask = state.write_mask;
103 SET_FLAG_FROM_TEST(write_mask, r, uint32_t(GPU_WRITE_RED));
104 SET_FLAG_FROM_TEST(write_mask, g, uint32_t(GPU_WRITE_GREEN));
105 SET_FLAG_FROM_TEST(write_mask, b, uint32_t(GPU_WRITE_BLUE));
106 SET_FLAG_FROM_TEST(write_mask, a, uint32_t(GPU_WRITE_ALPHA));
107 state.write_mask = write_mask;
108}
109
110void GPU_depth_mask(bool depth)
111{
113 auto &state = stack->state;
114 uint32_t write_mask = state.write_mask;
115 SET_FLAG_FROM_TEST(write_mask, depth, uint32_t(GPU_WRITE_DEPTH));
116 state.write_mask = write_mask;
117}
118
119void GPU_shadow_offset(bool enable)
120{
121 SET_IMMUTABLE_STATE(shadow_bias, enable);
122}
123
124void GPU_clip_distances(int distances_enabled)
125{
126 SET_IMMUTABLE_STATE(clip_distances, distances_enabled);
127}
128
131 eGPUFaceCullTest culling_test,
132 eGPUDepthTest depth_test,
133 eGPUStencilTest stencil_test,
134 eGPUStencilOp stencil_op,
135 eGPUProvokingVertex provoking_vert)
136{
138 auto &state = stack->state;
139 state.write_mask = uint32_t(write_mask);
140 state.blend = uint32_t(blend);
141 state.culling_test = uint32_t(culling_test);
142 state.depth_test = uint32_t(depth_test);
143 state.stencil_test = uint32_t(stencil_test);
144 state.stencil_op = uint32_t(stencil_op);
145 state.provoking_vert = uint32_t(provoking_vert);
146}
147
149{
150 SET_IMMUTABLE_STATE(clip_control, enable);
151}
152
154
155/* -------------------------------------------------------------------- */
158
159void GPU_depth_range(float near, float far)
160{
162 auto &state = stack->mutable_state;
163 copy_v2_fl2(state.depth_range, near, far);
164}
165
166void GPU_line_width(float width)
167{
168 width = max_ff(1.0f, width * PIXELSIZE);
169 SET_MUTABLE_STATE(line_width, width);
170}
171
173{
175 auto &state = stack->mutable_state;
176 /* Keep the sign of point_size since it represents the enable state. */
177 state.point_size = size * ((state.point_size > 0.0) ? 1.0f : -1.0f);
178}
179
180void GPU_program_point_size(bool enable)
181{
183 auto &state = stack->mutable_state;
184 /* Set point size sign negative to disable. */
185 state.point_size = fabsf(state.point_size) * (enable ? 1 : -1);
186}
187
188void GPU_scissor_test(bool enable)
189{
191}
192
193void GPU_scissor(int x, int y, int width, int height)
194{
195 int scissor_rect[4] = {x, y, width, height};
196 Context::get()->active_fb->scissor_set(scissor_rect);
197}
198
199void GPU_viewport(int x, int y, int width, int height)
200{
201 int viewport_rect[4] = {x, y, width, height};
202 Context::get()->active_fb->viewport_set(viewport_rect);
203}
204
206{
207 SET_MUTABLE_STATE(stencil_reference, uint8_t(reference));
208}
209
211{
212 SET_MUTABLE_STATE(stencil_write_mask, uint8_t(write_mask));
213}
214
216{
217 SET_MUTABLE_STATE(stencil_compare_mask, uint8_t(compare_mask));
218}
219
221
222/* -------------------------------------------------------------------- */
225
231
237
239{
241 return state.stencil_write_mask;
242}
243
249
255
257{
259 return state.line_width;
260}
261
263{
265 return bool(state.line_smooth);
266}
267
268void GPU_scissor_get(int coords[4])
269{
271}
272
273void GPU_viewport_size_get_f(float coords[4])
274{
275 int viewport[4];
276 Context::get()->active_fb->viewport_get(viewport);
277 for (int i = 0; i < 4; i++) {
278 coords[i] = viewport[i];
279 }
280}
281
282void GPU_viewport_size_get_i(int coords[4])
283{
285}
286
288{
290 return (state.write_mask & GPU_WRITE_DEPTH) != 0;
291}
292
294{
295 /* TODO(fclem): this used to be a userdef option. */
296 return true;
297}
298
300
301/* -------------------------------------------------------------------- */
304
306{
307 Context::get()->flush();
308}
309
311{
312 Context::get()->finish();
313}
314
319
321
322/* -------------------------------------------------------------------- */
329
331{
332 Context *ctx = Context::get();
333 if (!(ctx && ctx->state_manager)) {
334 return;
335 }
336 StateManager &state_manager = *(Context::get()->state_manager);
337 if (state_manager.use_bgl == false) {
338 /* Expected by many addons (see #80169, #81289).
339 * This will reset the blend function. */
341
342 /* Equivalent of setting the depth func `glDepthFunc(GL_LEQUAL)`
343 * Needed since Python scripts may enable depth test.
344 * Without this block the depth test function is undefined. */
345 {
346 eGPUDepthTest depth_test_real = GPU_depth_test_get();
347 eGPUDepthTest depth_test_temp = GPU_DEPTH_LESS_EQUAL;
348 if (depth_test_real != depth_test_temp) {
349 GPU_depth_test(depth_test_temp);
350 state_manager.apply_state();
351 GPU_depth_test(depth_test_real);
352 }
353 }
354
355 state_manager.apply_state();
356 state_manager.use_bgl = true;
357 }
358}
359
361{
362 Context *ctx = Context::get();
363 if (!(ctx && ctx->state_manager)) {
364 return;
365 }
366 StateManager &state_manager = *ctx->state_manager;
367 if (state_manager.use_bgl == true) {
368 state_manager.use_bgl = false;
369 /* Resync state tracking. */
370 state_manager.force_state();
371 }
372}
373
375{
377}
378
380
381/* -------------------------------------------------------------------- */
384
389
391{
392 Fence *fence = GPUBackend::get()->fence_alloc();
393 return wrap(fence);
394}
395
396void GPU_fence_free(GPUFence *fence)
397{
398 delete unwrap(fence);
399}
400
401void GPU_fence_signal(GPUFence *fence)
402{
403 unwrap(fence)->signal();
404}
405
406void GPU_fence_wait(GPUFence *fence)
407{
408 unwrap(fence)->wait();
409}
410
412
413/* -------------------------------------------------------------------- */
416
418{
419 /* Set default state. */
420 state.write_mask = GPU_WRITE_COLOR;
421 state.blend = GPU_BLEND_NONE;
422 state.culling_test = GPU_CULL_NONE;
423 state.depth_test = GPU_DEPTH_NONE;
424 state.stencil_test = GPU_STENCIL_NONE;
425 state.stencil_op = GPU_STENCIL_OP_NONE;
426 state.provoking_vert = GPU_VERTEX_LAST;
427 state.logic_op_xor = false;
428 state.invert_facing = false;
429 state.shadow_bias = false;
430 state.clip_distances = 0;
431 state.clip_control = false;
432 state.polygon_smooth = false;
433 state.line_smooth = false;
434
435 mutable_state.depth_range[0] = 0.0f;
436 mutable_state.depth_range[1] = 1.0f;
437 mutable_state.point_size = -1.0f; /* Negative is not using point size. */
438 mutable_state.line_width = 1.0f;
439 mutable_state.stencil_write_mask = 0x00;
440 mutable_state.stencil_compare_mask = 0x00;
441 mutable_state.stencil_reference = 0x00;
442}
443
MINLINE float max_ff(float a, float b)
MINLINE void copy_v2_fl2(float v[2], float x, float y)
unsigned int uint
#define SET_FLAG_FROM_TEST(value, test, flag)
eGPUBlend
Definition GPU_state.hh:84
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
eGPUWriteMask
Definition GPU_state.hh:16
@ GPU_WRITE_RED
Definition GPU_state.hh:18
@ GPU_WRITE_GREEN
Definition GPU_state.hh:19
@ GPU_WRITE_BLUE
Definition GPU_state.hh:20
@ GPU_WRITE_DEPTH
Definition GPU_state.hh:22
@ GPU_WRITE_COLOR
Definition GPU_state.hh:24
@ GPU_WRITE_ALPHA
Definition GPU_state.hh:21
eGPUProvokingVertex
Definition GPU_state.hh:141
@ GPU_VERTEX_LAST
Definition GPU_state.hh:142
eGPUFaceCullTest
Definition GPU_state.hh:135
@ GPU_CULL_NONE
Definition GPU_state.hh:136
eGPUBarrier
Definition GPU_state.hh:29
eGPUStencilOp
Definition GPU_state.hh:127
@ GPU_STENCIL_OP_NONE
Definition GPU_state.hh:128
eGPUDepthTest
Definition GPU_state.hh:110
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
eGPUStencilTest
Definition GPU_state.hh:120
@ GPU_STENCIL_NONE
Definition GPU_state.hh:121
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static Context * get()
virtual void finish()=0
virtual void flush()=0
void viewport_set(const int viewport[4])
void scissor_set(const int scissor[4])
void scissor_get(int r_scissor[4]) const
void viewport_get(int r_viewport[4]) const
static GPUBackend * get()
virtual Fence * fence_alloc()=0
virtual void issue_barrier(eGPUBarrier barrier_bits)=0
virtual void apply_state()=0
virtual void force_state()=0
#define fabsf(x)
void GPU_memory_barrier(eGPUBarrier barrier)
Definition gpu_state.cc:385
void GPU_program_point_size(bool enable)
Definition gpu_state.cc:180
void GPU_face_culling(eGPUFaceCullTest culling)
Definition gpu_state.cc:47
eGPUFaceCullTest GPU_face_culling_get()
Definition gpu_state.cc:52
void GPU_flush()
Definition gpu_state.cc:305
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_write_mask(eGPUWriteMask mask)
Definition gpu_state.cc:93
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
bool GPU_line_smooth_get()
Definition gpu_state.cc:262
void GPU_line_width(float width)
Definition gpu_state.cc:166
eGPUBlend GPU_blend_get()
Definition gpu_state.cc:226
void GPU_finish()
Definition gpu_state.cc:310
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
void GPU_logic_op_xor_set(bool enable)
Definition gpu_state.cc:88
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
eGPUDepthTest GPU_depth_test_get()
Definition gpu_state.cc:244
void GPU_bgl_start()
Definition gpu_state.cc:330
void GPU_stencil_test(eGPUStencilTest test)
Definition gpu_state.cc:73
void GPU_stencil_write_mask_set(uint write_mask)
Definition gpu_state.cc:210
bool GPU_mipmap_enabled()
Definition gpu_state.cc:293
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition gpu_state.cc:98
GPUFence * GPU_fence_create()
Definition gpu_state.cc:390
void GPU_depth_range(float near, float far)
Definition gpu_state.cc:159
void GPU_viewport_size_get_i(int coords[4])
Definition gpu_state.cc:282
eGPUWriteMask GPU_write_mask_get()
Definition gpu_state.cc:232
void GPU_stencil_reference_set(uint reference)
Definition gpu_state.cc:205
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
float GPU_line_width_get()
Definition gpu_state.cc:256
void GPU_stencil_compare_mask_set(uint compare_mask)
Definition gpu_state.cc:215
eGPUStencilTest GPU_stencil_test_get()
Definition gpu_state.cc:250
#define SET_MUTABLE_STATE(_state, _value)
Definition gpu_state.cc:36
void GPU_front_facing(bool invert)
Definition gpu_state.cc:58
void GPU_viewport(int x, int y, int width, int height)
Definition gpu_state.cc:199
void GPU_fence_wait(GPUFence *fence)
Definition gpu_state.cc:406
#define PIXELSIZE
Definition gpu_state.cc:11
void GPU_point_size(float size)
Definition gpu_state.cc:172
uint GPU_stencil_mask_get()
Definition gpu_state.cc:238
void GPU_bgl_end()
Definition gpu_state.cc:360
bool GPU_bgl_get()
Definition gpu_state.cc:374
void GPU_state_set(eGPUWriteMask write_mask, eGPUBlend blend, eGPUFaceCullTest culling_test, eGPUDepthTest depth_test, eGPUStencilTest stencil_test, eGPUStencilOp stencil_op, eGPUProvokingVertex provoking_vert)
Definition gpu_state.cc:129
#define SET_IMMUTABLE_STATE(_state, _value)
Definition gpu_state.cc:35
void GPU_fence_signal(GPUFence *fence)
Definition gpu_state.cc:401
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:273
void GPU_apply_state()
Definition gpu_state.cc:315
bool GPU_depth_mask_get()
Definition gpu_state.cc:287
void GPU_clip_control_unit_range(bool enable)
Definition gpu_state.cc:148
void GPU_scissor_get(int coords[4])
Definition gpu_state.cc:268
void GPU_clip_distances(int distances_enabled)
Definition gpu_state.cc:124
void GPU_fence_free(GPUFence *fence)
Definition gpu_state.cc:396
void GPU_provoking_vertex(eGPUProvokingVertex vert)
Definition gpu_state.cc:63
void GPU_polygon_smooth(bool enable)
Definition gpu_state.cc:83
void GPU_shadow_offset(bool enable)
Definition gpu_state.cc:119
CCL_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
Definition invert.h:11
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static ulong state[N]
static Context * unwrap(GPUContext *ctx)
static GPUContext * wrap(Context *ctx)
i
Definition text_draw.cc:230
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)