Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-09-04 03:36:56 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-09-05 18:49:14 +0300
commitb100b77fda0667d78cac0f219e0f6208d6b8f854 (patch)
treeb33d85d887e43d712fe7797b99ed6b6b150af4d0 /source/blender
parent31c77a14af7cac2bc52ecaffde1bae9775dc47ae (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.h1
-rw-r--r--source/blender/gpu/intern/gpu_extensions.cc7
-rw-r--r--source/blender/gpu/intern/gpu_texture_private.hh13
-rw-r--r--source/blender/gpu/opengl/gl_texture.cc111
-rw-r--r--source/blender/gpu/opengl/gl_texture.hh27
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) {