GLTexture: Add back texture proxy check
Cleanup the feature itself: - Check 3D textures size against the correct limit. - Add check for compressed textures.
This commit is contained in:
parent
31c77a14af
commit
b100b77fda
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue