Blender V5.0
gl_framebuffer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_string.h"
10
11#include "BKE_global.hh"
12
13#include "gl_backend.hh"
14#include "gl_debug.hh"
15#include "gl_state.hh"
16#include "gl_texture.hh"
17
18#include "gl_framebuffer.hh"
19
20namespace blender::gpu {
21
22/* -------------------------------------------------------------------- */
25
27{
28 /* Just-In-Time init. See #GLFrameBuffer::init(). */
29 immutable_ = false;
30 fbo_id_ = 0;
31}
32
34 const char *name, GLContext *ctx, GLenum target, GLuint fbo, int w, int h)
36{
37 context_ = ctx;
38 state_manager_ = static_cast<GLStateManager *>(ctx->state_manager);
39 immutable_ = true;
40 fbo_id_ = fbo;
41 gl_attachments_[0] = target;
43 /* Never update an internal frame-buffer. */
44 dirty_attachments_ = false;
45 width_ = w;
46 height_ = h;
47 srgb_ = false;
48
49 viewport_[0][0] = scissor_[0] = 0;
50 viewport_[0][1] = scissor_[1] = 0;
51 viewport_[0][2] = scissor_[2] = w;
52 viewport_[0][3] = scissor_[3] = h;
53
54 if (fbo_id_) {
55 debug::object_label(GL_FRAMEBUFFER, fbo_id_, name_);
56 }
57}
58
60{
61 if (context_ == nullptr) {
62 return;
63 }
64
65 /* Context might be partially freed. This happens when destroying the window frame-buffers. */
66 if (context_ == Context::get()) {
67 glDeleteFramebuffers(1, &fbo_id_);
68 }
69 else {
70 context_->fbo_free(fbo_id_);
71 }
72 /* Restore default frame-buffer if this frame-buffer was bound. */
73 if (context_->active_fb == this && context_->back_left != this) {
74 /* If this assert triggers it means the frame-buffer is being freed while in use by another
75 * context which, by the way, is TOTALLY UNSAFE! */
76 BLI_assert(context_ == Context::get());
78 }
79}
80
81void GLFrameBuffer::init()
82{
83 context_ = GLContext::get();
84 state_manager_ = static_cast<GLStateManager *>(context_->state_manager);
85 glGenFramebuffers(1, &fbo_id_);
86 /* Binding before setting the label is needed on some drivers.
87 * This is not an issue since we call this function only before binding. */
88 glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_);
89
90 debug::object_label(GL_FRAMEBUFFER, fbo_id_, name_);
91}
92
94
95/* -------------------------------------------------------------------- */
98
99bool GLFrameBuffer::check(char err_out[256])
100{
101 this->bind(true);
102
103 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
104
105#define FORMAT_STATUS(X) \
106 case X: { \
107 err = #X; \
108 break; \
109 }
110
111 const char *err;
112 switch (status) {
113 FORMAT_STATUS(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
114 FORMAT_STATUS(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
115 FORMAT_STATUS(GL_FRAMEBUFFER_UNSUPPORTED);
116 FORMAT_STATUS(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
117 FORMAT_STATUS(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
118 FORMAT_STATUS(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
119 FORMAT_STATUS(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS);
120 FORMAT_STATUS(GL_FRAMEBUFFER_UNDEFINED);
121 case GL_FRAMEBUFFER_COMPLETE:
122 return true;
123 default:
124 err = "unknown";
125 break;
126 }
127
128#undef FORMAT_STATUS
129
130 const char *format = "gpu::FrameBuffer: %s status %s\n";
131
132 if (err_out) {
133 BLI_snprintf(err_out, 256, format, this->name_, err);
134 }
135 else {
136 fprintf(stderr, format, this->name_, err);
137 }
138
139 return false;
140}
141
142void GLFrameBuffer::update_attachments()
143{
144 /* Default frame-buffers cannot have attachments. */
145 BLI_assert(immutable_ == false);
146
147 /* First color texture OR the depth texture if no color is attached.
148 * Used to determine frame-buffer color-space and dimensions. */
149 GPUAttachmentType first_attachment = GPU_FB_MAX_ATTACHMENT;
150 /* NOTE: Inverse iteration to get the first color texture. */
151 for (GPUAttachmentType type = GPU_FB_MAX_ATTACHMENT - 1; type >= 0; --type) {
152 GPUAttachment &attach = attachments_[type];
153 GLenum gl_attachment = to_gl(type);
154
155 if (type >= GPU_FB_COLOR_ATTACHMENT0) {
156 gl_attachments_[type - GPU_FB_COLOR_ATTACHMENT0] = (attach.tex) ? gl_attachment : GL_NONE;
157 first_attachment = (attach.tex) ? type : first_attachment;
158 }
159 else if (first_attachment == GPU_FB_MAX_ATTACHMENT) {
160 /* Only use depth texture to get information if there is no color attachment. */
161 first_attachment = (attach.tex) ? type : first_attachment;
162 }
163
164 if (attach.tex == nullptr) {
165 glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
166 continue;
167 }
168 GLuint gl_tex = static_cast<GLTexture *>(attach.tex)->tex_id_;
169 if (attach.layer > -1 && GPU_texture_is_cube(attach.tex) && !GPU_texture_is_array(attach.tex))
170 {
171 /* Could be avoided if ARB_direct_state_access is required. In this case
172 * #glFramebufferTextureLayer would bind the correct face. */
173 GLenum gl_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach.layer;
174 glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attachment, gl_target, gl_tex, attach.mip);
175 }
176 else if (attach.layer > -1) {
177 glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, gl_tex, attach.mip, attach.layer);
178 }
179 else {
180 /* The whole texture level is attached. The frame-buffer is potentially layered. */
181 glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, gl_tex, attach.mip);
182 }
183 /* We found one depth buffer type. Stop here, otherwise we would
184 * override it by setting GPU_FB_DEPTH_ATTACHMENT */
186 break;
187 }
188 }
189
191 /* Fill normally un-occupied slots to avoid rendering artifacts on some hardware. */
192 GLuint gl_tex = 0;
193 /* NOTE: Inverse iteration to get the first color texture. */
194 for (int i = ARRAY_SIZE(gl_attachments_) - 1; i >= 0; --i) {
196 GPUAttachment &attach = attachments_[type];
197 if (attach.tex != nullptr) {
198 gl_tex = static_cast<GLTexture *>(attach.tex)->tex_id_;
199 }
200 else if (gl_tex != 0) {
201 GLenum gl_attachment = to_gl(type);
202 gl_attachments_[i] = gl_attachment;
203 glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, gl_tex, 0);
204 }
205 }
206 }
207
208 if (first_attachment != GPU_FB_MAX_ATTACHMENT) {
209 GPUAttachment &attach = attachments_[first_attachment];
210 int size[3];
211 GPU_texture_get_mipmap_size(attach.tex, attach.mip, size);
212 this->size_set(size[0], size[1]);
213 srgb_ = (GPU_texture_format(attach.tex) == TextureFormat::SRGBA_8_8_8_8);
214 }
215 else {
216 /* Empty frame-buffer. */
217 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, width_);
218 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, height_);
219 }
220
221 dirty_attachments_ = false;
222
223 glDrawBuffers(ARRAY_SIZE(gl_attachments_), gl_attachments_);
224
225 if (G.debug & G_DEBUG_GPU) {
226 BLI_assert(this->check(nullptr));
227 }
228}
229
231 Span<GPUAttachmentState> color_attachment_states)
232{
233 GPU_depth_mask(depth_attachment_state == GPU_ATTACHMENT_WRITE);
234
235 bool any_read = false;
236 for (auto attachment : color_attachment_states.index_range()) {
237 if (attachment == GPU_ATTACHMENT_READ) {
238 any_read = true;
239 break;
240 }
241 }
242
244 if (any_read) {
245 glFramebufferFetchBarrierEXT();
246 }
247 }
249 if (any_read) {
250 glTextureBarrier();
251 }
252
253 GLenum attachments[GPU_FB_MAX_COLOR_ATTACHMENT] = {GL_NONE};
254 for (int i : color_attachment_states.index_range()) {
256 gpu::Texture *attach_tex = this->attachments_[type].tex;
257 if (color_attachment_states[i] == GPU_ATTACHMENT_READ) {
258 tmp_detached_[type] = this->attachments_[type]; /* Bypass feedback loop check. */
260 }
261 else {
262 tmp_detached_[type] = GPU_ATTACHMENT_NONE;
263 }
264 bool attach_write = color_attachment_states[i] == GPU_ATTACHMENT_WRITE;
265 attachments[i] = (attach_tex && attach_write) ? to_gl(type) : GL_NONE;
266 }
267 /* We have to use `glDrawBuffers` instead of `glColorMaski` because the later is overwritten
268 * by the `GLStateManager`. */
269 /* WATCH(fclem): This modifies the frame-buffer state without setting `dirty_attachments_`. */
270 glDrawBuffers(ARRAY_SIZE(attachments), attachments);
271 }
272 else {
273 /* The only way to have correct visibility without extensions and ensure defined behavior, is
274 * to unbind the textures and update the frame-buffer. This is a slow operation but that's all
275 * we can do to emulate the sub-pass input. */
276 /* TODO(@fclem): Could avoid the frame-buffer reconfiguration by creating multiple
277 * frame-buffers internally. */
278 for (int i : color_attachment_states.index_range()) {
280
281 if (color_attachment_states[i] == GPU_ATTACHMENT_WRITE) {
282 if (tmp_detached_[type].tex != nullptr) {
283 /* Re-attach previous read attachments. */
284 this->attachment_set(type, tmp_detached_[type]);
285 tmp_detached_[type] = GPU_ATTACHMENT_NONE;
286 }
287 }
288 else if (color_attachment_states[i] == GPU_ATTACHMENT_READ) {
289 tmp_detached_[type] = this->attachments_[type];
290 tmp_detached_[type].tex->detach_from(this);
291 GPU_texture_bind_ex(tmp_detached_[type].tex, GPUSamplerState::default_sampler(), i);
292 }
293 }
294 if (dirty_attachments_) {
295 this->update_attachments();
296 }
297 }
298}
299
301{
302 BLI_assert(context_->active_fb == this);
303
304 /* TODO(fclem): Add support for other ops. */
306 if (tmp_detached_[type].tex != nullptr) {
307 /* #GPULoadStore is used to define the frame-buffer before it is used for rendering.
308 * Binding back unattached attachment makes its state undefined. This is described by the
309 * documentation and the user-land code should specify a sub-pass at the start of the drawing
310 * to explicitly set attachment state. */
312 /* NOOP. */
313 }
315 /* Reset default attachment state. */
316 for (int i : IndexRange(ARRAY_SIZE(tmp_detached_))) {
317 tmp_detached_[i] = GPU_ATTACHMENT_NONE;
318 }
319 glDrawBuffers(ARRAY_SIZE(gl_attachments_), gl_attachments_);
320 }
321 else {
322 tmp_detached_[type] = GPU_ATTACHMENT_NONE;
323 this->attachment_set(type, tmp_detached_[type]);
324 this->update_attachments();
325 }
326 }
328 }
329}
330
332{
333 if (dirty_state_ == false) {
334 return;
335 }
336
337 if (multi_viewport_ == false) {
338 glViewport(UNPACK4(viewport_[0]));
339 }
340 else {
341 /* Great API you have there! You have to convert to float values for setting int viewport
342 * values. **Audible Facepalm** */
343 float viewports_f[GPU_MAX_VIEWPORTS][4];
344 for (int i = 0; i < GPU_MAX_VIEWPORTS; i++) {
345 for (int j = 0; j < 4; j++) {
346 viewports_f[i][j] = viewport_[i][j];
347 }
348 }
349 glViewportArrayv(0, GPU_MAX_VIEWPORTS, viewports_f[0]);
350 }
351 glScissor(UNPACK4(scissor_));
352
353 if (scissor_test_) {
354 glEnable(GL_SCISSOR_TEST);
355 }
356 else {
357 glDisable(GL_SCISSOR_TEST);
358 }
359
360 dirty_state_ = false;
361}
362
364
365/* -------------------------------------------------------------------- */
368
369void GLFrameBuffer::bind(bool enabled_srgb)
370{
371 if (!immutable_ && fbo_id_ == 0) {
372 this->init();
373 }
374
375 if (context_ != GLContext::get()) {
376 BLI_assert_msg(0, "Trying to use the same frame-buffer in multiple context");
377 return;
378 }
379
380 if (context_->active_fb != this) {
381 glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_);
382 /* Internal frame-buffers have only one color output and needs to be set every time. */
383 if (immutable_ && fbo_id_ == 0) {
384 glDrawBuffer(gl_attachments_[0]);
385 }
386 }
387
389 for (int index : IndexRange(GPU_FB_MAX_ATTACHMENT)) {
390 tmp_detached_[index] = GPU_ATTACHMENT_NONE;
391 }
392 }
393
394 if (dirty_attachments_) {
395 this->update_attachments();
396 this->viewport_reset();
397 this->scissor_reset();
398 }
399
400 if (context_->active_fb != this || enabled_srgb_ != enabled_srgb) {
401 enabled_srgb_ = enabled_srgb;
402 if (enabled_srgb && srgb_) {
403 glEnable(GL_FRAMEBUFFER_SRGB);
404 }
405 else {
406 glDisable(GL_FRAMEBUFFER_SRGB);
407 }
408 Shader::set_framebuffer_srgb_target(enabled_srgb && srgb_);
409 }
410
411 if (context_->active_fb != this) {
412 context_->active_fb = this;
413 state_manager_->active_fb = this;
414 dirty_state_ = true;
415 }
416}
417
419
420/* -------------------------------------------------------------------- */
423
425 const float clear_col[4],
426 float clear_depth,
427 uint clear_stencil)
428{
429 BLI_assert(GLContext::get() == context_);
430 BLI_assert(context_->active_fb == this);
431
432 /* Save and restore the state. */
433 GPUWriteMask write_mask = GPU_write_mask_get();
434 uint stencil_mask = GPU_stencil_mask_get();
435 GPUStencilTest stencil_test = GPU_stencil_test_get();
436
437 if (buffers & GPU_COLOR_BIT) {
438 GPU_color_mask(true, true, true, true);
439 glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
440 }
441 if (buffers & GPU_DEPTH_BIT) {
442 GPU_depth_mask(true);
443 glClearDepth(clear_depth);
444 }
445 if (buffers & GPU_STENCIL_BIT) {
448 glClearStencil(clear_stencil);
449 }
450
451 context_->state_manager->apply_state();
452
453 GLbitfield mask = to_gl(buffers);
454 glClear(mask);
455
457 GPU_write_mask(write_mask);
458 }
459 if (buffers & GPU_STENCIL_BIT) {
460 GPU_stencil_write_mask_set(stencil_mask);
461 GPU_stencil_test(stencil_test);
462 }
463}
464
466 eGPUDataFormat data_format,
467 const void *clear_value)
468{
469 BLI_assert(GLContext::get() == context_);
470 BLI_assert(context_->active_fb == this);
471
472 /* Save and restore the state. */
473 GPUWriteMask write_mask = GPU_write_mask_get();
474 GPU_color_mask(true, true, true, true);
475 bool depth_mask = GPU_depth_mask_get();
476 GPU_depth_mask(true);
477
478 context_->state_manager->apply_state();
479
482 float depth = ((*(uint32_t *)clear_value) & 0x00FFFFFFu) / float(0x00FFFFFFu);
483 int stencil = ((*(uint32_t *)clear_value) >> 24);
484 glClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
485 }
486 else if (type == GPU_FB_DEPTH_ATTACHMENT) {
487 if (data_format == GPU_DATA_FLOAT) {
488 glClearBufferfv(GL_DEPTH, 0, (GLfloat *)clear_value);
489 }
490 else if (data_format == GPU_DATA_UINT) {
491 float depth = *(uint32_t *)clear_value / float(0xFFFFFFFFu);
492 glClearBufferfv(GL_DEPTH, 0, &depth);
493 }
494 else {
495 BLI_assert_msg(0, "Unhandled data format");
496 }
497 }
498 else {
499 int slot = type - GPU_FB_COLOR_ATTACHMENT0;
500 switch (data_format) {
501 case GPU_DATA_FLOAT:
502 glClearBufferfv(GL_COLOR, slot, (GLfloat *)clear_value);
503 break;
504 case GPU_DATA_UINT:
505 glClearBufferuiv(GL_COLOR, slot, (GLuint *)clear_value);
506 break;
507 case GPU_DATA_INT:
508 glClearBufferiv(GL_COLOR, slot, (GLint *)clear_value);
509 break;
510 default:
511 BLI_assert_msg(0, "Unhandled data format");
512 break;
513 }
514 }
515
516 GPU_write_mask(write_mask);
517 GPU_depth_mask(depth_mask);
518}
519
520void GLFrameBuffer::clear_multi(const float (*clear_cols)[4])
521{
522 /* WATCH: This can easily access clear_cols out of bounds it clear_cols is not big enough for
523 * all attachments.
524 * TODO(fclem): fix this insecurity? */
525 int type = GPU_FB_COLOR_ATTACHMENT0;
526 for (int i = 0; type < GPU_FB_MAX_ATTACHMENT; i++, type++) {
527 if (attachments_[type].tex != nullptr) {
529 }
530 }
531}
532
534 eGPUDataFormat data_format,
535 const int area[4],
536 int channel_len,
537 int slot,
538 void *r_data)
539{
540 GLenum format, type, mode;
541 mode = gl_attachments_[slot];
542 type = to_gl(data_format);
543
544 switch (plane) {
545 case GPU_DEPTH_BIT:
546 format = GL_DEPTH_COMPONENT;
548 this->attachments_[GPU_FB_DEPTH_ATTACHMENT].tex != nullptr ||
549 this->attachments_[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != nullptr,
550 "GPUFramebuffer: Error: Trying to read depth without a depth buffer attached.");
551 break;
552 case GPU_COLOR_BIT:
554 mode != GL_NONE,
555 "GPUFramebuffer: Error: Trying to read a color slot without valid attachment.");
556 format = channel_len_to_gl(channel_len);
557 /* TODO: needed for selection buffers to work properly, this should be handled better. */
558 if (format == GL_RED && type == GL_UNSIGNED_INT) {
559 format = GL_RED_INTEGER;
560 }
561 break;
562 case GPU_STENCIL_BIT:
563 fprintf(stderr, "GPUFramebuffer: Error: Trying to read stencil bit. Unsupported.");
564 return;
565 default:
566 fprintf(stderr, "GPUFramebuffer: Error: Trying to read more than one frame-buffer plane.");
567 return;
568 }
569
570 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_id_);
571 glReadBuffer(mode);
572 glReadPixels(UNPACK4(area), format, type, r_data);
573}
574
576 GPUFrameBufferBits planes, int src_slot, FrameBuffer *dst_, int dst_slot, int x, int y)
577{
578 GLFrameBuffer *src = this;
579 GLFrameBuffer *dst = static_cast<GLFrameBuffer *>(dst_);
580
581 /* Frame-buffers must be up to date. This simplify this function. */
582 if (src->dirty_attachments_) {
583 src->bind(true);
584 }
585 if (dst->dirty_attachments_) {
586 dst->bind(true);
587 }
588
589 glBindFramebuffer(GL_READ_FRAMEBUFFER, src->fbo_id_);
590 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->fbo_id_);
591
592 if (planes & GPU_COLOR_BIT) {
593 BLI_assert(src->immutable_ == false || src_slot == 0);
594 BLI_assert(dst->immutable_ == false || dst_slot == 0);
595 BLI_assert(src->gl_attachments_[src_slot] != GL_NONE);
596 BLI_assert(dst->gl_attachments_[dst_slot] != GL_NONE);
597 glReadBuffer(src->gl_attachments_[src_slot]);
598 glDrawBuffer(dst->gl_attachments_[dst_slot]);
599 }
600
601 context_->state_manager->apply_state();
602
603 int w = src->width_;
604 int h = src->height_;
605 GLbitfield mask = to_gl(planes);
606 glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, mask, GL_NEAREST);
607
608 if (!dst->immutable_) {
609 /* Restore the draw buffers. */
610 glDrawBuffers(ARRAY_SIZE(dst->gl_attachments_), dst->gl_attachments_);
611 }
612 /* Ensure previous buffer is restored. */
613 context_->active_fb = dst;
614}
615
617
618} // namespace blender::gpu
@ G_DEBUG_GPU
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
#define UNPACK4(a)
#define ARRAY_SIZE(arr)
@ GPU_LOADACTION_CLEAR
GPUAttachmentState
@ GPU_ATTACHMENT_WRITE
@ GPU_ATTACHMENT_READ
GPUFrameBufferBits
@ GPU_DEPTH_BIT
@ GPU_STENCIL_BIT
@ GPU_COLOR_BIT
void GPU_framebuffer_restore()
static constexpr int GPU_MAX_VIEWPORTS
#define GPU_ATTACHMENT_NONE
GPUStencilTest GPU_stencil_test_get()
Definition gpu_state.cc:250
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
void GPU_stencil_write_mask_set(uint write_mask)
Definition gpu_state.cc:210
void GPU_stencil_test(GPUStencilTest test)
Definition gpu_state.cc:73
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition gpu_state.cc:98
GPUStencilTest
Definition GPU_state.hh:120
@ GPU_STENCIL_ALWAYS
Definition GPU_state.hh:122
GPUWriteMask
Definition GPU_state.hh:16
void GPU_write_mask(GPUWriteMask mask)
Definition gpu_state.cc:93
GPUWriteMask GPU_write_mask_get()
Definition gpu_state.cc:232
uint GPU_stencil_mask_get()
Definition gpu_state.cc:238
bool GPU_depth_mask_get()
Definition gpu_state.cc:287
void GPU_texture_get_mipmap_size(blender::gpu::Texture *texture, int mip_level, int *r_size)
blender::gpu::TextureFormat GPU_texture_format(const blender::gpu::Texture *texture)
eGPUDataFormat
@ GPU_DATA_INT
@ GPU_DATA_UINT
@ GPU_DATA_UINT_24_8_DEPRECATED
@ GPU_DATA_FLOAT
void GPU_texture_bind_ex(blender::gpu::Texture *texture, GPUSamplerState state, int unit)
bool GPU_texture_is_cube(const blender::gpu::Texture *texture)
bool GPU_texture_is_array(const blender::gpu::Texture *texture)
void init()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
static Context * get()
void size_set(int width, int height)
void set_color_attachment_bit(GPUAttachmentType type, bool value)
FrameBuffer(const char *name)
GPUAttachment attachments_[GPU_FB_MAX_ATTACHMENT]
int viewport_[GPU_MAX_VIEWPORTS][4]
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment)
static bool framebuffer_fetch_support
Definition gl_context.hh:63
static GLContext * get()
static bool unused_fb_slot_workaround
Definition gl_context.hh:75
static bool texture_barrier_support
Definition gl_context.hh:69
bool check(char err_out[256]) override
void attachment_set_loadstore_op(GPUAttachmentType type, GPULoadStore ls) override
void clear(GPUFrameBufferBits buffers, const float clear_col[4], float clear_depth, uint clear_stencil) override
void blit_to(GPUFrameBufferBits planes, int src_slot, FrameBuffer *dst, int dst_slot, int dst_offset_x, int dst_offset_y) override
void clear_multi(const float(*clear_cols)[4]) override
void subpass_transition_impl(const GPUAttachmentState depth_attachment_state, Span< GPUAttachmentState > color_attachment_states) override
GLFrameBuffer(const char *name)
void bind(bool enabled_srgb) override
void clear_attachment(GPUAttachmentType type, eGPUDataFormat data_format, const void *clear_value) override
void read(GPUFrameBufferBits planes, eGPUDataFormat format, const int area[4], int channel_len, int slot, void *r_data) override
static void set_framebuffer_srgb_target(int use_srgb_to_linear)
nullptr float
#define FORMAT_STATUS(X)
@ GPU_FB_DEPTH_STENCIL_ATTACHMENT
@ GPU_FB_MAX_ATTACHMENT
@ GPU_FB_COLOR_ATTACHMENT0
@ GPU_FB_DEPTH_ATTACHMENT
#define GPU_FB_MAX_COLOR_ATTACHMENT
format
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define G(x, y, z)
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:329
GLenum channel_len_to_gl(int channel_len)
static GLenum to_gl(const GPUAttachmentType type)
const char * name
const int status
blender::gpu::Texture * tex
GPULoadOp load_action
static constexpr GPUSamplerState default_sampler()
i
Definition text_draw.cc:230
char * buffers[2]