[Bf-blender-cvs] [5f7cc8cf51d] tmp-gltexture: GLTexture: Add back texture proxy check

Clément Foucault noreply at git.blender.org
Fri Sep 4 02:46:55 CEST 2020


Commit: 5f7cc8cf51dc2a2d6ce75576830a5ed79ae33bfc
Author: Clément Foucault
Date:   Fri Sep 4 02:36:56 2020 +0200
Branches: tmp-gltexture
https://developer.blender.org/rB5f7cc8cf51dc2a2d6ce75576830a5ed79ae33bfc

GLTexture: Add back texture proxy check

Cleanup the feature itself:
- Check 3D textures size against the correct limit.
- Add check for compressed textures.

===================================================================

M	source/blender/gpu/GPU_extensions.h
M	source/blender/gpu/intern/gpu_extensions.cc
M	source/blender/gpu/intern/gpu_texture_private.hh
M	source/blender/gpu/opengl/gl_texture.cc
M	source/blender/gpu/opengl/gl_texture.hh

===================================================================

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) {



More information about the Bf-blender-cvs mailing list