Blender V4.5
gl_texture.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 <string>
10
11#include "BLI_assert.h"
12#include "BLI_string.h"
13
14#include "DNA_userdef_types.h"
15
16#include "GPU_capabilities.hh"
17#include "GPU_framebuffer.hh"
18#include "GPU_platform.hh"
19
20#include "GPU_vertex_buffer.hh" /* TODO: should be `gl_vertex_buffer.hh`. */
21#include "gl_backend.hh"
22#include "gl_debug.hh"
23#include "gl_state.hh"
24
25#include "gl_texture.hh"
26
27namespace blender::gpu {
28
29/* -------------------------------------------------------------------- */
32
33GLTexture::GLTexture(const char *name) : Texture(name)
34{
35 BLI_assert(GLContext::get() != nullptr);
36
37 glGenTextures(1, &tex_id_);
38}
39
41{
42 if (framebuffer_) {
43 GPU_framebuffer_free(wrap(framebuffer_));
44 }
46 if (ctx != nullptr && is_bound_) {
47 /* This avoid errors when the texture is still inside the bound texture array. */
48 ctx->state_manager->texture_unbind(this);
49 ctx->state_manager->image_unbind(this);
50 }
51 GLContext::tex_free(tex_id_);
52}
53
55{
57 /* MacOS + Radeon Pro fails to blit depth on GPU_DEPTH24_STENCIL8
58 * but works on GPU_DEPTH32F_STENCIL8. */
60 }
61
62 target_ = to_gl_target(type_);
63
64 /* We need to bind once to define the texture type. */
66
67 if (!this->proxy_check(0)) {
68 return false;
69 }
70
71 GLenum internal_format = to_gl_internal_format(format_);
72 const bool is_cubemap = bool(type_ == GPU_TEXTURE_CUBE);
73 const int dimensions = (is_cubemap) ? 2 : this->dimensions_count();
74
75 switch (dimensions) {
76 default:
77 case 1:
78 glTexStorage1D(target_, mipmaps_, internal_format, w_);
79 break;
80 case 2:
81 glTexStorage2D(target_, mipmaps_, internal_format, w_, h_);
82 break;
83 case 3:
84 glTexStorage3D(target_, mipmaps_, internal_format, w_, h_, d_);
85 break;
86 }
87 this->mip_range_set(0, mipmaps_ - 1);
88
89 /* Avoid issue with formats not supporting filtering. Nearest by default. */
91 glTextureParameteri(tex_id_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
92 }
93 else {
94 glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
95 }
96
97 debug::object_label(GL_TEXTURE, tex_id_, name_);
98 return true;
99}
100
102{
103 GLVertBuf *gl_vbo = static_cast<GLVertBuf *>(vbo);
104 target_ = to_gl_target(type_);
105
106 /* We need to bind once to define the texture type. */
108
109 GLenum internal_format = to_gl_internal_format(format_);
110
112 glTextureBuffer(tex_id_, internal_format, gl_vbo->vbo_id_);
113 }
114 else {
115 glTexBuffer(target_, internal_format, gl_vbo->vbo_id_);
116 }
117
118 debug::object_label(GL_TEXTURE, tex_id_, name_);
119
120 return true;
121}
122
123bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset, bool use_stencil)
124{
125 const GLTexture *gl_src = static_cast<const GLTexture *>(unwrap(src));
126 GLenum internal_format = to_gl_internal_format(format_);
127 target_ = to_gl_target(type_);
128
129 glTextureView(tex_id_,
130 target_,
131 gl_src->tex_id_,
132 internal_format,
133 mip_offset,
134 mipmaps_,
135 layer_offset,
136 this->layer_count());
137
138 debug::object_label(GL_TEXTURE, tex_id_, name_);
139
140 /* Stencil view support. */
142 stencil_texture_mode_set(use_stencil);
143 }
144
145 return true;
146}
147
149
150/* -------------------------------------------------------------------- */
153
154void GLTexture::update_sub_direct_state_access(
155 int mip, int offset[3], int extent[3], GLenum format, GLenum type, const void *data)
156{
158 size_t size = ((extent[0] + 3) / 4) * ((extent[1] + 3) / 4) * to_block_size(format_);
159 switch (this->dimensions_count()) {
160 default:
161 case 1:
162 glCompressedTextureSubImage1D(tex_id_, mip, offset[0], extent[0], format, size, data);
163 break;
164 case 2:
165 glCompressedTextureSubImage2D(
166 tex_id_, mip, UNPACK2(offset), UNPACK2(extent), format, size, data);
167 break;
168 case 3:
169 glCompressedTextureSubImage3D(
170 tex_id_, mip, UNPACK3(offset), UNPACK3(extent), format, size, data);
171 break;
172 }
173 }
174 else {
175 switch (this->dimensions_count()) {
176 default:
177 case 1:
178 glTextureSubImage1D(tex_id_, mip, offset[0], extent[0], format, type, data);
179 break;
180 case 2:
181 glTextureSubImage2D(tex_id_, mip, UNPACK2(offset), UNPACK2(extent), format, type, data);
182 break;
183 case 3:
184 glTextureSubImage3D(tex_id_, mip, UNPACK3(offset), UNPACK3(extent), format, type, data);
185 break;
186 }
187 }
188
189 has_pixels_ = true;
190}
191
193 int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data)
194{
196 BLI_assert(data != nullptr);
197
198 if (mip >= mipmaps_) {
199 debug::raise_gl_error("Updating a miplvl on a texture too small to have this many levels.");
200 return;
201 }
202
203 const int dimensions = this->dimensions_count();
204 GLenum gl_format = to_gl_data_format(format_);
205 GLenum gl_type = to_gl(type);
206
207 /* Some drivers have issues with cubemap & glTextureSubImage3D even if it is correct. */
209 this->update_sub_direct_state_access(mip, offset, extent, gl_format, gl_type, data);
210 return;
211 }
212
214 if (type_ == GPU_TEXTURE_CUBE) {
215 for (int i = 0; i < extent[2]; i++) {
216 GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset[2] + i;
217 glTexSubImage2D(target, mip, UNPACK2(offset), UNPACK2(extent), gl_format, gl_type, data);
218 }
219 }
221 size_t size = ((extent[0] + 3) / 4) * ((extent[1] + 3) / 4) * to_block_size(format_);
222 switch (dimensions) {
223 default:
224 case 1:
225 glCompressedTexSubImage1D(target_, mip, offset[0], extent[0], gl_format, size, data);
226 break;
227 case 2:
228 glCompressedTexSubImage2D(
229 target_, mip, UNPACK2(offset), UNPACK2(extent), gl_format, size, data);
230 break;
231 case 3:
232 glCompressedTexSubImage3D(
233 target_, mip, UNPACK3(offset), UNPACK3(extent), gl_format, size, data);
234 break;
235 }
236 }
237 else {
238 switch (dimensions) {
239 default:
240 case 1:
241 glTexSubImage1D(target_, mip, offset[0], extent[0], gl_format, gl_type, data);
242 break;
243 case 2:
244 glTexSubImage2D(target_, mip, UNPACK2(offset), UNPACK2(extent), gl_format, gl_type, data);
245 break;
246 case 3:
247 glTexSubImage3D(target_, mip, UNPACK3(offset), UNPACK3(extent), gl_format, gl_type, data);
248 break;
249 }
250 }
251
252 has_pixels_ = true;
253}
254
255void GLTexture::update_sub(int offset[3],
256 int extent[3],
258 GPUPixelBuffer *pixbuf)
259{
260 /* Update texture from pixel buffer. */
262 BLI_assert(pixbuf != nullptr);
263
264 const int dimensions = this->dimensions_count();
265 GLenum gl_format = to_gl_data_format(format_);
266 GLenum gl_type = to_gl(format);
267
268 /* Temporarily Bind texture. */
270
271 /* Bind pixel buffer for source data. */
272 GLint pix_buf_handle = (GLint)GPU_pixel_buffer_get_native_handle(pixbuf).handle;
273 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pix_buf_handle);
274
275 switch (dimensions) {
276 default:
277 case 1:
278 glTexSubImage1D(target_, 0, offset[0], extent[0], gl_format, gl_type, nullptr);
279 break;
280 case 2:
281 glTexSubImage2D(target_, 0, UNPACK2(offset), UNPACK2(extent), gl_format, gl_type, nullptr);
282 break;
283 case 3:
284 glTexSubImage3D(target_, 0, UNPACK3(offset), UNPACK3(extent), gl_format, gl_type, nullptr);
285 break;
286 }
287
288 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
289}
290
292{
293 /* Allow users to provide mipmaps stored in compressed textures.
294 * Skip generating mipmaps to avoid overriding the existing ones. */
296 return;
297 }
298
299 /* Some drivers have bugs when using #glGenerateMipmap with depth textures (see #56789).
300 * In this case we just create a complete texture with mipmaps manually without
301 * down-sampling. You must initialize the texture levels using other methods like
302 * #GPU_framebuffer_recursive_downsample(). */
304 return;
305 }
306
308 /* Broken glGenerateMipmap, don't call it and render without mipmaps.
309 * If no top level pixels have been filled in, the levels will get filled by
310 * other means and there is no need to disable mipmapping. */
311 if (has_pixels_) {
312 this->mip_range_set(0, 0);
313 }
314 return;
315 }
316
317 /* Down-sample from mip 0 using implementation. */
319 glGenerateTextureMipmap(tex_id_);
320 }
321 else {
323 glGenerateMipmap(target_);
324 }
325}
326
327void GLTexture::clear(eGPUDataFormat data_format, const void *data)
328{
330
331 /* Note: do not use glClearTexImage, even if it is available (via
332 * extension or GL 4.4). It causes GL framebuffer binding to be
333 * way slower at least on some drivers (e.g. Win10 / NV RTX 3080,
334 * but also reportedly others), as if glClearTexImage causes
335 * "pixel data" to exist which is then uploaded CPU -> GPU at bind
336 * time. */
337
338 GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
339
340 FrameBuffer *fb = this->framebuffer_get();
341 fb->bind(true);
342 fb->clear_attachment(this->attachment_type(0), data_format, data);
343
344 GPU_framebuffer_bind(prev_fb);
345}
346
348{
349 GLTexture *dst = static_cast<GLTexture *>(dst_);
350 GLTexture *src = this;
351
352 BLI_assert((dst->w_ == src->w_) && (dst->h_ == src->h_) && (dst->d_ == src->d_));
353 BLI_assert(dst->format_ == src->format_);
354 BLI_assert(dst->type_ == src->type_);
355
356 int mip = 0;
357 /* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
358 int extent[3] = {1, 1, 1};
359 this->mip_size_get(mip, extent);
360 glCopyImageSubData(
361 src->tex_id_, target_, mip, 0, 0, 0, dst->tex_id_, target_, mip, 0, 0, 0, UNPACK3(extent));
362
363 has_pixels_ = true;
364}
365
366void *GLTexture::read(int mip, eGPUDataFormat type)
367{
369 BLI_assert(mip <= mipmaps_ || mip == 0);
371
372 /* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
373 int extent[3] = {1, 1, 1};
374 this->mip_size_get(mip, extent);
375
376 size_t sample_len = extent[0] * extent[1] * extent[2];
377 size_t sample_size = to_bytesize(format_, type);
378 size_t texture_size = sample_len * sample_size;
379
380 /* AMD Pro driver have a bug that write 8 bytes past buffer size
381 * if the texture is big. (see #66573) */
382 void *data = MEM_mallocN(texture_size + 8, "GPU_texture_read");
383
384 GLenum gl_format = to_gl_data_format(format_);
385 GLenum gl_type = to_gl(type);
386
388 glGetTextureImage(tex_id_, mip, gl_format, gl_type, texture_size, data);
389 }
390 else {
392 if (type_ == GPU_TEXTURE_CUBE) {
393 size_t cube_face_size = texture_size / 6;
394 char *pdata = (char *)data;
395 for (int i = 0; i < 6; i++, pdata += cube_face_size) {
396 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, mip, gl_format, gl_type, pdata);
397 }
398 }
399 else {
400 glGetTexImage(target_, mip, gl_format, gl_type, data);
401 }
402 }
403 return data;
404}
405
407
408/* -------------------------------------------------------------------- */
411
412void GLTexture::swizzle_set(const char swizzle[4])
413{
414 GLint gl_swizzle[4] = {(GLint)swizzle_to_gl(swizzle[0]),
415 (GLint)swizzle_to_gl(swizzle[1]),
416 (GLint)swizzle_to_gl(swizzle[2]),
417 (GLint)swizzle_to_gl(swizzle[3])};
419 glTextureParameteriv(tex_id_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
420 }
421 else {
423 glTexParameteriv(target_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
424 }
425}
426
427void GLTexture::stencil_texture_mode_set(bool use_stencil)
428{
430 GLint value = use_stencil ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
432 glTextureParameteri(tex_id_, GL_DEPTH_STENCIL_TEXTURE_MODE, value);
433 }
434 else {
436 glTexParameteri(target_, GL_DEPTH_STENCIL_TEXTURE_MODE, value);
437 }
438}
439
441{
443 mip_min_ = min;
444 mip_max_ = max;
446 glTextureParameteri(tex_id_, GL_TEXTURE_BASE_LEVEL, min);
447 glTextureParameteri(tex_id_, GL_TEXTURE_MAX_LEVEL, max);
448 }
449 else {
451 glTexParameteri(target_, GL_TEXTURE_BASE_LEVEL, min);
452 glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, max);
453 }
454}
455
456FrameBuffer *GLTexture::framebuffer_get()
457{
458 if (framebuffer_) {
459 return framebuffer_;
460 }
462 framebuffer_ = unwrap(GPU_framebuffer_create(name_));
463 framebuffer_->attachment_set(this->attachment_type(0), GPU_ATTACHMENT_TEXTURE(wrap(this)));
464 has_pixels_ = true;
465 return framebuffer_;
466}
467
469
470/* -------------------------------------------------------------------- */
473
475static inline GLenum to_gl(GPUSamplerExtendMode extend_mode)
476{
477 switch (extend_mode) {
479 return GL_CLAMP_TO_EDGE;
481 return GL_REPEAT;
483 return GL_MIRRORED_REPEAT;
485 return GL_CLAMP_TO_BORDER;
486 default:
488 return GL_CLAMP_TO_EDGE;
489 }
490}
491
492GLuint GLTexture::samplers_state_cache_[GPU_SAMPLER_EXTEND_MODES_COUNT]
495GLuint GLTexture::custom_samplers_state_cache_[GPU_SAMPLER_CUSTOM_TYPES_COUNT] = {};
496
498{
499 glGenSamplers(samplers_state_cache_count_, &samplers_state_cache_[0][0][0]);
500
501 for (int extend_yz_i = 0; extend_yz_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_yz_i++) {
502 const GPUSamplerExtendMode extend_yz = static_cast<GPUSamplerExtendMode>(extend_yz_i);
503 const GLenum extend_t = to_gl(extend_yz);
504
505 for (int extend_x_i = 0; extend_x_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_x_i++) {
506 const GPUSamplerExtendMode extend_x = static_cast<GPUSamplerExtendMode>(extend_x_i);
507 const GLenum extend_s = to_gl(extend_x);
508
509 for (int filtering_i = 0; filtering_i < GPU_SAMPLER_FILTERING_TYPES_COUNT; filtering_i++) {
510 const GPUSamplerFiltering filtering = GPUSamplerFiltering(filtering_i);
511
512 const GLenum mag_filter = (filtering & GPU_SAMPLER_FILTERING_LINEAR) ? GL_LINEAR :
513 GL_NEAREST;
514 const GLenum linear_min_filter = (filtering & GPU_SAMPLER_FILTERING_MIPMAP) ?
515 GL_LINEAR_MIPMAP_LINEAR :
516 GL_LINEAR;
517 const GLenum nearest_min_filter = (filtering & GPU_SAMPLER_FILTERING_MIPMAP) ?
518 GL_NEAREST_MIPMAP_LINEAR :
519 GL_NEAREST;
520 const GLenum min_filter = (filtering & GPU_SAMPLER_FILTERING_LINEAR) ? linear_min_filter :
521 nearest_min_filter;
522
523 GLuint sampler = samplers_state_cache_[extend_yz_i][extend_x_i][filtering_i];
524 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, extend_s);
525 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, extend_t);
526 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, extend_t);
527 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, min_filter);
528 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, mag_filter);
529
530 /* Other states are left to default:
531 * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
532 * - GL_TEXTURE_MIN_LOD is -1000.
533 * - GL_TEXTURE_MAX_LOD is 1000.
534 * - GL_TEXTURE_LOD_BIAS is 0.0f.
535 */
536
537 const GPUSamplerState sampler_state = {filtering, extend_x, extend_yz};
538 const std::string sampler_name = sampler_state.to_string();
539 debug::object_label(GL_SAMPLER, sampler, sampler_name.c_str());
540 }
541 }
542 }
544
545 glGenSamplers(GPU_SAMPLER_CUSTOM_TYPES_COUNT, custom_samplers_state_cache_);
546
547 /* Compare sampler for depth textures. */
548 GLuint compare_sampler = custom_samplers_state_cache_[GPU_SAMPLER_CUSTOM_COMPARE];
549 glSamplerParameteri(compare_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
550 glSamplerParameteri(compare_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
551 glSamplerParameteri(compare_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
552 glSamplerParameteri(compare_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
553 glSamplerParameteri(compare_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
554 glSamplerParameteri(compare_sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
555 glSamplerParameteri(compare_sampler, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
556
557 debug::object_label(GL_SAMPLER, compare_sampler, "compare");
558
559 /* Custom sampler for icons. The icon texture is sampled within the shader using a -0.5f LOD
560 * bias. */
561 GLuint icon_sampler = custom_samplers_state_cache_[GPU_SAMPLER_CUSTOM_ICON];
562 glSamplerParameteri(icon_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
563 glSamplerParameteri(icon_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
564
565 debug::object_label(GL_SAMPLER, icon_sampler, "icons");
566}
567
569{
571 return;
572 }
573
574 float max_anisotropy = 1.0f;
575 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
576
577 const float anisotropic_filter = min_ff(max_anisotropy, U.anisotropic_filter);
578
579 for (int extend_yz_i = 0; extend_yz_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_yz_i++) {
580 for (int extend_x_i = 0; extend_x_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_x_i++) {
581 for (int filtering_i = 0; filtering_i < GPU_SAMPLER_FILTERING_TYPES_COUNT; filtering_i++) {
582 const GPUSamplerFiltering filtering = GPUSamplerFiltering(filtering_i);
583
584 if ((filtering & GPU_SAMPLER_FILTERING_ANISOTROPIC) &&
585 (filtering & GPU_SAMPLER_FILTERING_MIPMAP))
586 {
587 glSamplerParameterf(samplers_state_cache_[extend_yz_i][extend_x_i][filtering_i],
588 GL_TEXTURE_MAX_ANISOTROPY_EXT,
589 anisotropic_filter);
590 }
591 }
592 }
593 }
594}
595
597{
598 glDeleteSamplers(samplers_state_cache_count_, &samplers_state_cache_[0][0][0]);
599 glDeleteSamplers(GPU_SAMPLER_CUSTOM_TYPES_COUNT, custom_samplers_state_cache_);
600}
601
603{
604 /* Internal sampler states are signal values and do not correspond to actual samplers. */
606
608 return custom_samplers_state_cache_[sampler_state.custom_type];
609 }
610
611 return samplers_state_cache_[sampler_state.extend_yz][sampler_state.extend_x]
612 [sampler_state.filtering];
613}
614
616
617/* -------------------------------------------------------------------- */
622
623bool GLTexture::proxy_check(int mip)
624{
625 /* NOTE: This only checks if this mipmap is valid / supported.
626 * TODO(fclem): make the check cover the whole mipmap chain. */
627
628 /* Manual validation first, since some implementation have issues with proxy creation. */
629 int max_size = GPU_max_texture_size();
630 int max_3d_size = GPU_max_texture_3d_size();
631 int max_cube_size = GLContext::max_cubemap_size;
632 int size[3] = {1, 1, 1};
633 this->mip_size_get(mip, size);
634
635 if (type_ & GPU_TEXTURE_ARRAY) {
636 if (this->layer_count() > GPU_max_texture_layers()) {
637 return false;
638 }
639 }
640
641 if (type_ == GPU_TEXTURE_3D) {
642 if (size[0] > max_3d_size || size[1] > max_3d_size || size[2] > max_3d_size) {
643 return false;
644 }
645 }
646 else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_2D) {
647 if (size[0] > max_size || size[1] > max_size) {
648 return false;
649 }
650 }
651 else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_1D) {
652 if (size[0] > max_size) {
653 return false;
654 }
655 }
656 else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_CUBE) {
657 if (size[0] > max_cube_size) {
658 return false;
659 }
660 }
661
664 {
665 /* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check.
666 * (see #55888, #56185, #59351).
667 * Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue,
668 * it just states that the OGL implementation can support the texture.
669 * So we already manually check the maximum size and maximum number of layers.
670 * Same thing happens on Nvidia/macOS 10.15 (#78175). */
671 return true;
672 }
673
674 GLenum gl_proxy = to_gl_proxy(type_);
675 GLenum internal_format = to_gl_internal_format(format_);
676 GLenum gl_format = to_gl_data_format(format_);
677 GLenum gl_type = to_gl(to_data_format(format_));
678 /* Small exception. */
679 int dimensions = (type_ == GPU_TEXTURE_CUBE) ? 2 : this->dimensions_count();
680
682 size_t img_size = ((size[0] + 3) / 4) * ((size[1] + 3) / 4) * to_block_size(format_);
683 switch (dimensions) {
684 default:
685 case 1:
686 glCompressedTexImage1D(gl_proxy, mip, size[0], 0, gl_format, img_size, nullptr);
687 break;
688 case 2:
689 glCompressedTexImage2D(gl_proxy, mip, UNPACK2(size), 0, gl_format, img_size, nullptr);
690 break;
691 case 3:
692 glCompressedTexImage3D(gl_proxy, mip, UNPACK3(size), 0, gl_format, img_size, nullptr);
693 break;
694 }
695 }
696 else {
697 switch (dimensions) {
698 default:
699 case 1:
700 glTexImage1D(gl_proxy, mip, internal_format, size[0], 0, gl_format, gl_type, nullptr);
701 break;
702 case 2:
703 glTexImage2D(
704 gl_proxy, mip, internal_format, UNPACK2(size), 0, gl_format, gl_type, nullptr);
705 break;
706 case 3:
707 glTexImage3D(
708 gl_proxy, mip, internal_format, UNPACK3(size), 0, gl_format, gl_type, nullptr);
709 break;
710 }
711 }
712
713 int width = 0;
714 glGetTexLevelParameteriv(gl_proxy, 0, GL_TEXTURE_WIDTH, &width);
715 return (width > 0);
716}
717
719
721{
722 /* Recursive down sample workaround break this check.
723 * See #recursive_downsample() for more information. */
725 return;
726 }
727 /* Do not check if using compute shader. */
728 GLShader *sh = dynamic_cast<GLShader *>(Context::get()->shader);
729 if (sh && sh->is_compute()) {
730 return;
731 }
733 for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
734 if (fb_[i] == fb) {
736 GPUAttachment attachment = fb->attachments_[type];
737 /* Check for when texture is used with texture barrier. */
738 GPUAttachment attachment_read = fb->tmp_detached_[type];
739 if (attachment.mip <= mip_max_ && attachment.mip >= mip_min_ &&
740 attachment_read.tex == nullptr)
741 {
742 char msg[256];
743 SNPRINTF(msg,
744 "Feedback loop: Trying to bind a texture (%s) with mip range %d-%d but mip %d is "
745 "attached to the active framebuffer (%s)",
746 name_,
747 mip_min_,
748 mip_max_,
749 attachment.mip,
750 fb->name_);
752 }
753 return;
754 }
755 }
756}
757
759{
760 /* TODO(fclem): Legacy. Should be removed at some point. */
761
762 return tex_id_;
763}
764
765/* -------------------------------------------------------------------- */
768
770{
771 glGenBuffers(1, &gl_id_);
772 BLI_assert(gl_id_);
773
774 if (!gl_id_) {
775 return;
776 }
777
778 /* Ensure size is non-zero for pixel buffer backing storage creation. */
779 size = max_ii(size, 32);
780
781 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_id_);
782 glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_DYNAMIC_DRAW);
783 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
784}
785
787{
788 if (!gl_id_) {
789 return;
790 }
791 glDeleteBuffers(1, &gl_id_);
792}
793
795{
796 if (!gl_id_) {
797 BLI_assert(false);
798 return nullptr;
799 }
800
801 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_id_);
802 void *ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
804 return ptr;
805}
806
808{
809 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
810 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
811}
812
814{
815 GPUPixelBufferNativeHandle native_handle;
816 native_handle.handle = int64_t(gl_id_);
817 native_handle.size = size_;
818 return native_handle;
819}
820
822{
823 return size_;
824}
825
827} // namespace blender::gpu
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
unsigned int uint
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define UNPACK3(a)
#define ELEM(...)
int GPU_max_texture_3d_size()
int GPU_max_texture_layers()
bool GPU_depth_blitting_workaround()
bool GPU_mip_render_workaround()
int GPU_max_texture_size()
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
#define GPU_ATTACHMENT_TEXTURE(_texture)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
@ GPU_DRIVER_ANY
@ GPU_DRIVER_OFFICIAL
@ GPU_OS_WIN
@ GPU_OS_UNIX
@ GPU_DEVICE_ATI
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
@ GPU_SAMPLER_CUSTOM_ICON
@ GPU_SAMPLER_CUSTOM_COMPARE
GPUPixelBufferNativeHandle GPU_pixel_buffer_get_native_handle(GPUPixelBuffer *pixel_buf)
@ GPU_SAMPLER_STATE_TYPE_CUSTOM
@ GPU_SAMPLER_STATE_TYPE_INTERNAL
static const int GPU_SAMPLER_FILTERING_TYPES_COUNT
eGPUDataFormat
GPUSamplerExtendMode
@ GPU_SAMPLER_EXTEND_MODE_MIRRORED_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
@ GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER
#define GPU_SAMPLER_CUSTOM_TYPES_COUNT
@ GPU_DEPTH32F_STENCIL8
@ GPU_DEPTH24_STENCIL8
GPUSamplerFiltering
@ GPU_SAMPLER_FILTERING_MIPMAP
@ GPU_SAMPLER_FILTERING_ANISOTROPIC
@ GPU_SAMPLER_FILTERING_LINEAR
#define GPU_SAMPLER_EXTEND_MODES_COUNT
#define U
BMesh const char void * data
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static Context * get()
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment)
static bool stencil_texturing_support
Definition gl_context.hh:62
static GLStateManager * state_manager_active_get()
static bool direct_state_access_support
Definition gl_context.hh:53
static GLContext * get()
static void tex_free(GLuint tex_id)
static bool texture_filter_anisotropic_support
Definition gl_context.hh:64
static GLint max_cubemap_size
Definition gl_context.hh:44
static bool generate_mipmap_workaround
Definition gl_context.hh:70
GPUPixelBufferNativeHandle get_native_handle() override
size_t get_size() override
bool is_compute() const
Definition gl_shader.hh:161
void texture_bind_temp(GLTexture *tex)
Definition gl_state.cc:488
GLTexture(const char *name)
Definition gl_texture.cc:33
void copy_to(Texture *dst) override
void mip_range_set(int min, int max) override
friend class GLFrameBuffer
Definition gl_texture.hh:22
static void samplers_init()
static GLuint get_sampler(const GPUSamplerState &sampler_state)
static void samplers_update()
uint gl_bindcode_get() const override
void * read(int mip, eGPUDataFormat type) override
static void samplers_free()
bool init_internal() override
Definition gl_texture.cc:54
void generate_mipmap() override
void update_sub(int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data) override
void clear(eGPUDataFormat format, const void *data) override
void swizzle_set(const char swizzle_mask[4]) override
virtual void texture_unbind(Texture *tex)=0
virtual void image_unbind(Texture *tex)=0
eGPUTextureFormatFlag format_flag_
char name_[DEBUG_NAME_LEN]
FrameBuffer * fb_[GPU_TEX_MAX_FBO_ATTACHED]
GPUAttachmentType fb_attachment_[GPU_TEX_MAX_FBO_ATTACHED]
GPUAttachmentType attachment_type(int slot) const
void mip_size_get(int mip, int r_size[3]) const
Texture(const char *name)
#define this
BLI_INLINE float fb(float length, float L)
format
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void raise_gl_error(const char *info)
Definition gl_debug.cc:276
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:329
static Context * unwrap(GPUContext *ctx)
GLenum to_gl_target(eGPUTextureType type)
size_t to_block_size(eGPUTextureFormat data_type)
static GPUContext * wrap(Context *ctx)
GLenum to_gl_internal_format(eGPUTextureFormat format)
constexpr bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
int to_bytesize(const DataFormat format)
GLenum to_gl_proxy(eGPUTextureType type)
GLenum to_gl_data_format(eGPUTextureFormat format)
GLenum swizzle_to_gl(const char swizzle)
constexpr DataFormat to_data_format(TextureFormat format)
static GLenum to_gl(const GPUAttachmentType type)
#define min(a, b)
Definition sort.cc:36
GPUTexture * tex
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
PointerRNA * ptr
Definition wm_files.cc:4227