diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-09-04 03:36:56 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-09-05 18:49:14 +0300 |
commit | b100b77fda0667d78cac0f219e0f6208d6b8f854 (patch) | |
tree | b33d85d887e43d712fe7797b99ed6b6b150af4d0 /source/blender | |
parent | 31c77a14af7cac2bc52ecaffde1bae9775dc47ae (diff) |
GLTexture: Add back texture proxy check
Cleanup the feature itself:
- Check 3D textures size against the correct limit.
- Add check for compressed textures.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/gpu/GPU_extensions.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.cc | 7 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture_private.hh | 13 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.cc | 111 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.hh | 27 |
5 files changed, 157 insertions, 2 deletions
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 18ac2265cc4..35967ac304f 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -30,6 +30,7 @@ extern "C" { /* GPU extensions support */ int GPU_max_texture_size(void); +int GPU_max_texture_3d_size(void); int GPU_max_texture_layers(void); int GPU_max_textures(void); int GPU_max_textures_vert(void); diff --git a/source/blender/gpu/intern/gpu_extensions.cc b/source/blender/gpu/intern/gpu_extensions.cc index b473e719211..7583d20c362 100644 --- a/source/blender/gpu/intern/gpu_extensions.cc +++ b/source/blender/gpu/intern/gpu_extensions.cc @@ -62,6 +62,7 @@ static struct GPUGlobal { GLint maxtexsize; + GLint maxtex3dsize; GLint maxtexlayers; GLint maxcubemapsize; GLint maxtextures; @@ -137,6 +138,11 @@ int GPU_max_texture_size(void) return GG.maxtexsize; } +int GPU_max_texture_3d_size(void) +{ + return GG.maxtex3dsize; +} + int GPU_max_texture_layers(void) { return GG.maxtexlayers; @@ -249,6 +255,7 @@ void gpu_extensions_init(void) glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GG.maxtex3dsize); glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize); diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 7b5aed9562e..e3872c4d4b5 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -188,6 +188,19 @@ class Texture { return 3; } } + /* Return number of array layer (or face layer) for texture array or 1 for the others. */ + int layer_count(void) const + { + switch (type_) { + case GPU_TEXTURE_1D_ARRAY: + return h_; + case GPU_TEXTURE_2D_ARRAY: + case GPU_TEXTURE_CUBE_ARRAY: + return d_; + default: + return 1; + } + } eGPUTextureFormat format_get(void) const { diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index b9a7347c8ed..f72dd3322b2 100644 --- a/source/blender/gpu/opengl/gl_texture.cc +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -27,6 +27,7 @@ #include "GPU_extensions.h" #include "GPU_framebuffer.h" +#include "GPU_platform.h" #include "gl_backend.hh" #include "gl_debug.hh" @@ -76,7 +77,9 @@ bool GLTexture::init_internal(void) target_ = to_gl_target(type_); - /* TODO(fclem) Proxy check. */ + if (!this->proxy_check(0)) { + return false; + } this->ensure_mipmaps(0); @@ -497,6 +500,112 @@ void GLTexture::samplers_free(void) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Proxy texture + * + * Dummy texture to see if the implementation supports the requested size. + * \{ */ + +/* NOTE: This only checks if this mipmap is valid / supported. + * TODO(fclem) make the check cover the whole mipmap chain. */ +bool GLTexture::proxy_check(int mip) +{ + /* Manual validation first, since some implementation have issues with proxy creation. */ + int max_size = GPU_max_texture_size(); + int max_3d_size = GPU_max_texture_3d_size(); + int max_cube_size = GPU_max_cube_map_size(); + int size[3] = {1, 1, 1}; + this->mip_size_get(mip, size); + + if (type_ & GPU_TEXTURE_ARRAY) { + if (this->layer_count() > GPU_max_texture_layers()) { + return false; + } + } + + if (type_ == GPU_TEXTURE_3D) { + if (size[0] > max_3d_size || size[1] > max_3d_size || size[2] > max_3d_size) { + return false; + } + } + else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_2D) { + if (size[0] > max_size || size[1] > max_size) { + return false; + } + } + else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_1D) { + if (size[0] > max_size) { + return false; + } + } + else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_CUBE) { + if (size[0] > max_cube_size) { + return false; + } + } + + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY) || + GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_OFFICIAL) || + GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL)) { + /* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check. + * (see T55888, T56185, T59351). + * Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue, + * it just states that the OGL implementation can support the texture. + * So we already manually check the maximum size and maximum number of layers. + * Same thing happens on Nvidia/macOS 10.15 (T78175). */ + return true; + } + + if ((type_ == GPU_TEXTURE_CUBE_ARRAY) && + GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) { + /* Special fix for T79703. */ + return true; + } + + GLenum gl_proxy = to_gl_proxy(type_); + GLenum internal_format = to_gl_internal_format(format_); + GLenum gl_format = to_gl_data_format(format_); + GLenum gl_type = to_gl(to_data_format(format_)); + /* Small exception. */ + int dimensions = (type_ == GPU_TEXTURE_CUBE) ? 2 : this->dimensions_count(); + + if (format_flag_ & GPU_FORMAT_COMPRESSED) { + size_t img_size = ((size[0] + 3) / 4) * ((size[1] + 3) / 4) * to_block_size(format_); + switch (dimensions) { + default: + case 1: + glCompressedTexImage1D(gl_proxy, mip, size[0], 0, gl_format, img_size, NULL); + break; + case 2: + glCompressedTexImage2D(gl_proxy, mip, UNPACK2(size), 0, gl_format, img_size, NULL); + break; + case 3: + glCompressedTexImage3D(gl_proxy, mip, UNPACK3(size), 0, gl_format, img_size, NULL); + break; + } + } + else { + switch (dimensions) { + default: + case 1: + glTexImage1D(gl_proxy, mip, internal_format, size[0], 0, gl_format, gl_type, NULL); + break; + case 2: + glTexImage2D(gl_proxy, mip, internal_format, UNPACK2(size), 0, gl_format, gl_type, NULL); + break; + case 3: + glTexImage3D(gl_proxy, mip, internal_format, UNPACK3(size), 0, gl_format, gl_type, NULL); + break; + } + } + + int width = 0; + glGetTexLevelParameteriv(gl_proxy, 0, GL_TEXTURE_WIDTH, &width); + return (width > 0); +} + +/** \} */ + /* TODO(fclem) Legacy. Should be removed at some point. */ uint GLTexture::gl_bindcode_get(void) const { diff --git a/source/blender/gpu/opengl/gl_texture.hh b/source/blender/gpu/opengl/gl_texture.hh index 36da89dad8e..ec1fc114584 100644 --- a/source/blender/gpu/opengl/gl_texture.hh +++ b/source/blender/gpu/opengl/gl_texture.hh @@ -97,7 +97,8 @@ class GLTexture : public Texture { bool init_internal(GPUVertBuf *vbo) override; private: - void ensure_mipmaps(int miplvl); + bool proxy_check(int mip); + void ensure_mipmaps(int mip); GPUFrameBuffer *framebuffer_get(void); MEM_CXX_CLASS_ALLOC_FUNCS("GLTexture") @@ -232,6 +233,30 @@ inline GLenum to_gl_target(eGPUTextureType type) } } +inline GLenum to_gl_proxy(eGPUTextureType type) +{ + switch (type) { + case GPU_TEXTURE_1D: + return GL_PROXY_TEXTURE_1D; + case GPU_TEXTURE_1D_ARRAY: + return GL_PROXY_TEXTURE_1D_ARRAY; + case GPU_TEXTURE_2D: + return GL_PROXY_TEXTURE_2D; + case GPU_TEXTURE_2D_ARRAY: + return GL_PROXY_TEXTURE_2D_ARRAY; + case GPU_TEXTURE_3D: + return GL_PROXY_TEXTURE_3D; + case GPU_TEXTURE_CUBE: + return GL_PROXY_TEXTURE_CUBE_MAP; + case GPU_TEXTURE_CUBE_ARRAY: + return GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB; + case GPU_TEXTURE_BUFFER: + default: + BLI_assert(0); + return GL_TEXTURE_1D; + } +} + inline GLenum swizzle_to_gl(const char swizzle) { switch (swizzle) { |