Blender V4.3
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
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/* -------------------------------------------------------------------- */
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
150/* -------------------------------------------------------------------- */
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);
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
332 int mip = 0;
333 GLenum gl_format = to_gl_data_format(format_);
334 GLenum gl_type = to_gl(data_format);
335 glClearTexImage(tex_id_, mip, gl_format, gl_type, data);
336 }
337 else {
338 /* Fallback for older GL. */
339 GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
340
341 FrameBuffer *fb = this->framebuffer_get();
342 fb->bind(true);
343 fb->clear_attachment(this->attachment_type(0), data_format, data);
344
345 GPU_framebuffer_bind(prev_fb);
346 }
347
348 has_pixels_ = true;
349}
350
352{
353 GLTexture *dst = static_cast<GLTexture *>(dst_);
354 GLTexture *src = this;
355
356 BLI_assert((dst->w_ == src->w_) && (dst->h_ == src->h_) && (dst->d_ == src->d_));
357 BLI_assert(dst->format_ == src->format_);
358 BLI_assert(dst->type_ == src->type_);
359
360 int mip = 0;
361 /* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
362 int extent[3] = {1, 1, 1};
363 this->mip_size_get(mip, extent);
364 glCopyImageSubData(
365 src->tex_id_, target_, mip, 0, 0, 0, dst->tex_id_, target_, mip, 0, 0, 0, UNPACK3(extent));
366
367 has_pixels_ = true;
368}
369
370void *GLTexture::read(int mip, eGPUDataFormat type)
371{
373 BLI_assert(mip <= mipmaps_ || mip == 0);
375
376 /* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
377 int extent[3] = {1, 1, 1};
378 this->mip_size_get(mip, extent);
379
380 size_t sample_len = extent[0] * extent[1] * extent[2];
381 size_t sample_size = to_bytesize(format_, type);
382 size_t texture_size = sample_len * sample_size;
383
384 /* AMD Pro driver have a bug that write 8 bytes past buffer size
385 * if the texture is big. (see #66573) */
386 void *data = MEM_mallocN(texture_size + 8, "GPU_texture_read");
387
388 GLenum gl_format = to_gl_data_format(format_);
389 GLenum gl_type = to_gl(type);
390
392 glGetTextureImage(tex_id_, mip, gl_format, gl_type, texture_size, data);
393 }
394 else {
396 if (type_ == GPU_TEXTURE_CUBE) {
397 size_t cube_face_size = texture_size / 6;
398 char *pdata = (char *)data;
399 for (int i = 0; i < 6; i++, pdata += cube_face_size) {
400 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, mip, gl_format, gl_type, pdata);
401 }
402 }
403 else {
404 glGetTexImage(target_, mip, gl_format, gl_type, data);
405 }
406 }
407 return data;
408}
409
412/* -------------------------------------------------------------------- */
416void GLTexture::swizzle_set(const char swizzle[4])
417{
418 GLint gl_swizzle[4] = {(GLint)swizzle_to_gl(swizzle[0]),
419 (GLint)swizzle_to_gl(swizzle[1]),
420 (GLint)swizzle_to_gl(swizzle[2]),
421 (GLint)swizzle_to_gl(swizzle[3])};
423 glTextureParameteriv(tex_id_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
424 }
425 else {
427 glTexParameteriv(target_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
428 }
429}
430
431void GLTexture::stencil_texture_mode_set(bool use_stencil)
432{
434 GLint value = use_stencil ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
436 glTextureParameteri(tex_id_, GL_DEPTH_STENCIL_TEXTURE_MODE, value);
437 }
438 else {
440 glTexParameteri(target_, GL_DEPTH_STENCIL_TEXTURE_MODE, value);
441 }
442}
443
445{
447 mip_min_ = min;
448 mip_max_ = max;
450 glTextureParameteri(tex_id_, GL_TEXTURE_BASE_LEVEL, min);
451 glTextureParameteri(tex_id_, GL_TEXTURE_MAX_LEVEL, max);
452 }
453 else {
455 glTexParameteri(target_, GL_TEXTURE_BASE_LEVEL, min);
456 glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, max);
457 }
458}
459
460FrameBuffer *GLTexture::framebuffer_get()
461{
462 if (framebuffer_) {
463 return framebuffer_;
464 }
466 framebuffer_ = unwrap(GPU_framebuffer_create(name_));
467 framebuffer_->attachment_set(this->attachment_type(0), GPU_ATTACHMENT_TEXTURE(wrap(this)));
468 has_pixels_ = true;
469 return framebuffer_;
470}
471
474/* -------------------------------------------------------------------- */
479static inline GLenum to_gl(GPUSamplerExtendMode extend_mode)
480{
481 switch (extend_mode) {
483 return GL_CLAMP_TO_EDGE;
485 return GL_REPEAT;
487 return GL_MIRRORED_REPEAT;
489 return GL_CLAMP_TO_BORDER;
490 default:
492 return GL_CLAMP_TO_EDGE;
493 }
494}
495
496GLuint GLTexture::samplers_state_cache_[GPU_SAMPLER_EXTEND_MODES_COUNT]
499GLuint GLTexture::custom_samplers_state_cache_[GPU_SAMPLER_CUSTOM_TYPES_COUNT] = {};
500
502{
503 glGenSamplers(samplers_state_cache_count_, &samplers_state_cache_[0][0][0]);
504
505 for (int extend_yz_i = 0; extend_yz_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_yz_i++) {
506 const GPUSamplerExtendMode extend_yz = static_cast<GPUSamplerExtendMode>(extend_yz_i);
507 const GLenum extend_t = to_gl(extend_yz);
508
509 for (int extend_x_i = 0; extend_x_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_x_i++) {
510 const GPUSamplerExtendMode extend_x = static_cast<GPUSamplerExtendMode>(extend_x_i);
511 const GLenum extend_s = to_gl(extend_x);
512
513 for (int filtering_i = 0; filtering_i < GPU_SAMPLER_FILTERING_TYPES_COUNT; filtering_i++) {
514 const GPUSamplerFiltering filtering = GPUSamplerFiltering(filtering_i);
515
516 const GLenum mag_filter = (filtering & GPU_SAMPLER_FILTERING_LINEAR) ? GL_LINEAR :
517 GL_NEAREST;
518 const GLenum linear_min_filter = (filtering & GPU_SAMPLER_FILTERING_MIPMAP) ?
519 GL_LINEAR_MIPMAP_LINEAR :
520 GL_LINEAR;
521 const GLenum nearest_min_filter = (filtering & GPU_SAMPLER_FILTERING_MIPMAP) ?
522 GL_NEAREST_MIPMAP_LINEAR :
523 GL_NEAREST;
524 const GLenum min_filter = (filtering & GPU_SAMPLER_FILTERING_LINEAR) ? linear_min_filter :
525 nearest_min_filter;
526
527 GLuint sampler = samplers_state_cache_[extend_yz_i][extend_x_i][filtering_i];
528 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, extend_s);
529 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, extend_t);
530 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, extend_t);
531 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, min_filter);
532 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, mag_filter);
533
534 /* Other states are left to default:
535 * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
536 * - GL_TEXTURE_MIN_LOD is -1000.
537 * - GL_TEXTURE_MAX_LOD is 1000.
538 * - GL_TEXTURE_LOD_BIAS is 0.0f.
539 */
540
541 const GPUSamplerState sampler_state = {filtering, extend_x, extend_yz};
542 const std::string sampler_name = sampler_state.to_string();
543 debug::object_label(GL_SAMPLER, sampler, sampler_name.c_str());
544 }
545 }
546 }
548
549 glGenSamplers(GPU_SAMPLER_CUSTOM_TYPES_COUNT, custom_samplers_state_cache_);
550
551 /* Compare sampler for depth textures. */
552 GLuint compare_sampler = custom_samplers_state_cache_[GPU_SAMPLER_CUSTOM_COMPARE];
553 glSamplerParameteri(compare_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
554 glSamplerParameteri(compare_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
555 glSamplerParameteri(compare_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
556 glSamplerParameteri(compare_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
557 glSamplerParameteri(compare_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
558 glSamplerParameteri(compare_sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
559 glSamplerParameteri(compare_sampler, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
560
561 debug::object_label(GL_SAMPLER, compare_sampler, "compare");
562
563 /* Custom sampler for icons. The icon texture is sampled within the shader using a -0.5f LOD
564 * bias. */
565 GLuint icon_sampler = custom_samplers_state_cache_[GPU_SAMPLER_CUSTOM_ICON];
566 glSamplerParameteri(icon_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
567 glSamplerParameteri(icon_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
568
569 debug::object_label(GL_SAMPLER, icon_sampler, "icons");
570}
571
573{
575 return;
576 }
577
578 float max_anisotropy = 1.0f;
579 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
580
581 const float anisotropic_filter = min_ff(max_anisotropy, U.anisotropic_filter);
582
583 for (int extend_yz_i = 0; extend_yz_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_yz_i++) {
584 for (int extend_x_i = 0; extend_x_i < GPU_SAMPLER_EXTEND_MODES_COUNT; extend_x_i++) {
585 for (int filtering_i = 0; filtering_i < GPU_SAMPLER_FILTERING_TYPES_COUNT; filtering_i++) {
586 const GPUSamplerFiltering filtering = GPUSamplerFiltering(filtering_i);
587
588 if ((filtering & GPU_SAMPLER_FILTERING_ANISOTROPIC) &&
589 (filtering & GPU_SAMPLER_FILTERING_MIPMAP))
590 {
591 glSamplerParameterf(samplers_state_cache_[extend_yz_i][extend_x_i][filtering_i],
592 GL_TEXTURE_MAX_ANISOTROPY_EXT,
593 anisotropic_filter);
594 }
595 }
596 }
597 }
598}
599
601{
602 glDeleteSamplers(samplers_state_cache_count_, &samplers_state_cache_[0][0][0]);
603 glDeleteSamplers(GPU_SAMPLER_CUSTOM_TYPES_COUNT, custom_samplers_state_cache_);
604}
605
606GLuint GLTexture::get_sampler(const GPUSamplerState &sampler_state)
607{
608 /* Internal sampler states are signal values and do not correspond to actual samplers. */
610
612 return custom_samplers_state_cache_[sampler_state.custom_type];
613 }
614
615 return samplers_state_cache_[sampler_state.extend_yz][sampler_state.extend_x]
617}
618
621/* -------------------------------------------------------------------- */
627/* NOTE: This only checks if this mipmap is valid / supported.
628 * TODO(fclem): make the check cover the whole mipmap chain. */
629bool GLTexture::proxy_check(int mip)
630{
631 /* Manual validation first, since some implementation have issues with proxy creation. */
632 int max_size = GPU_max_texture_size();
633 int max_3d_size = GPU_max_texture_3d_size();
634 int max_cube_size = GLContext::max_cubemap_size;
635 int size[3] = {1, 1, 1};
636 this->mip_size_get(mip, size);
637
638 if (type_ & GPU_TEXTURE_ARRAY) {
639 if (this->layer_count() > GPU_max_texture_layers()) {
640 return false;
641 }
642 }
643
644 if (type_ == GPU_TEXTURE_3D) {
645 if (size[0] > max_3d_size || size[1] > max_3d_size || size[2] > max_3d_size) {
646 return false;
647 }
648 }
649 else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_2D) {
650 if (size[0] > max_size || size[1] > max_size) {
651 return false;
652 }
653 }
654 else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_1D) {
655 if (size[0] > max_size) {
656 return false;
657 }
658 }
659 else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_CUBE) {
660 if (size[0] > max_cube_size) {
661 return false;
662 }
663 }
664
667 {
668 /* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check.
669 * (see #55888, #56185, #59351).
670 * Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue,
671 * it just states that the OGL implementation can support the texture.
672 * So we already manually check the maximum size and maximum number of layers.
673 * Same thing happens on Nvidia/macOS 10.15 (#78175). */
674 return true;
675 }
676
677 GLenum gl_proxy = to_gl_proxy(type_);
678 GLenum internal_format = to_gl_internal_format(format_);
679 GLenum gl_format = to_gl_data_format(format_);
680 GLenum gl_type = to_gl(to_data_format(format_));
681 /* Small exception. */
682 int dimensions = (type_ == GPU_TEXTURE_CUBE) ? 2 : this->dimensions_count();
683
685 size_t img_size = ((size[0] + 3) / 4) * ((size[1] + 3) / 4) * to_block_size(format_);
686 switch (dimensions) {
687 default:
688 case 1:
689 glCompressedTexImage1D(gl_proxy, mip, size[0], 0, gl_format, img_size, nullptr);
690 break;
691 case 2:
692 glCompressedTexImage2D(gl_proxy, mip, UNPACK2(size), 0, gl_format, img_size, nullptr);
693 break;
694 case 3:
695 glCompressedTexImage3D(gl_proxy, mip, UNPACK3(size), 0, gl_format, img_size, nullptr);
696 break;
697 }
698 }
699 else {
700 switch (dimensions) {
701 default:
702 case 1:
703 glTexImage1D(gl_proxy, mip, internal_format, size[0], 0, gl_format, gl_type, nullptr);
704 break;
705 case 2:
706 glTexImage2D(
707 gl_proxy, mip, internal_format, UNPACK2(size), 0, gl_format, gl_type, nullptr);
708 break;
709 case 3:
710 glTexImage3D(
711 gl_proxy, mip, internal_format, UNPACK3(size), 0, gl_format, gl_type, nullptr);
712 break;
713 }
714 }
715
716 int width = 0;
717 glGetTexLevelParameteriv(gl_proxy, 0, GL_TEXTURE_WIDTH, &width);
718 return (width > 0);
719}
720
724{
725 /* Recursive down sample workaround break this check.
726 * See #recursive_downsample() for more information. */
728 return;
729 }
730 /* Do not check if using compute shader. */
731 GLShader *sh = dynamic_cast<GLShader *>(Context::get()->shader);
732 if (sh && sh->is_compute()) {
733 return;
734 }
736 for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
737 if (fb_[i] == fb) {
739 GPUAttachment attachment = fb->attachments_[type];
740 /* Check for when texture is used with texture barrier. */
741 GPUAttachment attachment_read = fb->tmp_detached_[type];
742 if (attachment.mip <= mip_max_ && attachment.mip >= mip_min_ &&
743 attachment_read.tex == nullptr)
744 {
745 char msg[256];
746 SNPRINTF(msg,
747 "Feedback loop: Trying to bind a texture (%s) with mip range %d-%d but mip %d is "
748 "attached to the active framebuffer (%s)",
749 name_,
750 mip_min_,
751 mip_max_,
752 attachment.mip,
753 fb->name_);
755 }
756 return;
757 }
758 }
759}
760
762{
763 /* TODO(fclem): Legacy. Should be removed at some point. */
764
765 return tex_id_;
766}
767
768/* -------------------------------------------------------------------- */
773{
774 glGenBuffers(1, &gl_id_);
775 BLI_assert(gl_id_);
776
777 if (!gl_id_) {
778 return;
779 }
780
781 /* Ensure size is non-zero for pixel buffer backing storage creation. */
782 size = max_ii(size, 32);
783
784 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_id_);
785 glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_DYNAMIC_DRAW);
786 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
787}
788
790{
791 if (!gl_id_) {
792 return;
793 }
794 glDeleteBuffers(1, &gl_id_);
795}
796
798{
799 if (!gl_id_) {
800 BLI_assert(false);
801 return nullptr;
802 }
803
804 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_id_);
805 void *ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
807 return ptr;
808}
809
811{
812 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
813 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
814}
815
817{
818 return int64_t(gl_id_);
819}
820
822{
823 return size_;
824}
825
827} // namespace blender::gpu
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
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_bind(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_free(GPUFrameBuffer *framebuffer)
@ 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
@ GPU_SAMPLER_STATE_TYPE_CUSTOM
@ GPU_SAMPLER_STATE_TYPE_INTERNAL
int64_t GPU_pixel_buffer_get_native_handle(GPUPixelBuffer *pixel_buf)
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
unsigned int U
Definition btGjkEpa3.h:78
static Context * get()
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment)
static bool stencil_texturing_support
Definition gl_context.hh:61
static GLStateManager * state_manager_active_get()
static bool direct_state_access_support
Definition gl_context.hh:52
static GLContext * get()
static void tex_free(GLuint tex_id)
static bool texture_filter_anisotropic_support
Definition gl_context.hh:63
static bool clear_texture_support
Definition gl_context.hh:50
static GLint max_cubemap_size
Definition gl_context.hh:43
static bool generate_mipmap_workaround
Definition gl_context.hh:69
size_t get_size() override
int64_t get_native_handle() override
bool is_compute() const
Definition gl_shader.hh:203
void texture_bind_temp(GLTexture *tex)
Definition gl_state.cc:465
GLTexture(const char *name)
Definition gl_texture.cc:33
void copy_to(Texture *dst) override
void mip_range_set(int min, int max) override
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
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx sampler(1, ImageType::FLOAT_2D, "matte_tx") .image(0
BLI_INLINE float fb(float length, float L)
format
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void raise_gl_error(const char *info)
Definition gl_debug.cc:291
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:344
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)
size_t to_bytesize(GPUIndexBufType type)
GLenum to_gl_proxy(eGPUTextureType type)
GLenum to_gl_data_format(eGPUTextureFormat format)
eGPUDataFormat to_data_format(eGPUTextureFormat tex_format)
GLenum swizzle_to_gl(const char swizzle)
static GLenum to_gl(const GPUAttachmentType type)
#define min(a, b)
Definition sort.c:32
__int64 int64_t
Definition stdint.h:89
GPUTexture * tex
GPUSamplerCustomType custom_type
GPUSamplerExtendMode extend_yz
GPUSamplerFiltering filtering
std::string to_string() const
GPUSamplerExtendMode extend_x
GPUSamplerStateType type
float max
PointerRNA * ptr
Definition wm_files.cc:4126