Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor high quality texture import #72031

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions core/io/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
"ETC2_RGB8A1",
"ETC2_RA_AS_RG",
"FORMAT_DXT5_RA_AS_RG",
"ASTC_4x4",
"ASTC_4x4_HDR",
"ASTC_8x8",
"ASTC_8x8_HDR",
};

SavePNGFunc Image::save_png_func = nullptr;
Expand Down Expand Up @@ -2187,16 +2191,16 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);

if (unlikely(p_data.size() != size)) {
String description_mipmaps;
String description_mipmaps = get_format_name(p_format) + " ";
if (p_use_mipmaps) {
const int num_mipmaps = get_image_required_mipmaps(p_width, p_height, p_format);
if (num_mipmaps != 1) {
description_mipmaps = vformat("with %d mipmaps", num_mipmaps);
description_mipmaps += vformat("with %d mipmaps", num_mipmaps);
} else {
description_mipmaps = "with 1 mipmap";
description_mipmaps += "with 1 mipmap";
}
} else {
description_mipmaps = "without mipmaps";
description_mipmaps += "without mipmaps";
}
const String description = vformat("%dx%dx%d (%s)", p_width, p_height, get_format_pixel_size(p_format), description_mipmaps);
ERR_FAIL_MSG(vformat("Expected Image data size of %s = %d bytes, got %d bytes instead.", description, size, p_data.size()));
Expand Down Expand Up @@ -2618,35 +2622,35 @@ Error Image::decompress() {
return OK;
}

Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality, ASTCFormat p_astc_format) {
Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) {
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality, p_astc_format);
return compress_from_channels(p_mode, detect_used_channels(p_source), p_astc_format);
}

Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality, ASTCFormat p_astc_format) {
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);

switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
_image_compress_bc_func(this, p_lossy_quality, p_channels);
_image_compress_bc_func(this, p_channels);
} break;
case COMPRESS_ETC: {
ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE);
_image_compress_etc1_func(this, p_lossy_quality);
_image_compress_etc1_func(this);
} break;
case COMPRESS_ETC2: {
ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
_image_compress_etc2_func(this, p_lossy_quality, p_channels);
_image_compress_etc2_func(this, p_channels);
} break;
case COMPRESS_BPTC: {
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_bptc_func(this, p_lossy_quality, p_channels);
_image_compress_bptc_func(this, p_channels);
} break;
case COMPRESS_ASTC: {
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_astc_func(this, p_lossy_quality, p_astc_format);
_image_compress_astc_func(this, p_astc_format);
} break;
case COMPRESS_MAX: {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
Expand Down Expand Up @@ -3000,11 +3004,11 @@ ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;

void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_astc_func)(Image *, float, Image::ASTCFormat) = nullptr;
void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
Expand Down Expand Up @@ -3426,8 +3430,8 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);

ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4));
ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality", "astc_format"), &Image::compress_from_channels, DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4));
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(ASTC_FORMAT_4x4));
ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "astc_format"), &Image::compress_from_channels, DEFVAL(ASTC_FORMAT_4x4));
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);

Expand Down Expand Up @@ -3547,11 +3551,11 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8);
}

void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
void Image::set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels)) {
_image_compress_bc_func = p_compress_func;
}

void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels)) {
_image_compress_bptc_func = p_compress_func;
}

Expand Down
18 changes: 9 additions & 9 deletions core/io/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,11 @@ class Image : public Resource {
static ImageMemLoadFunc _tga_mem_loader_func;
static ImageMemLoadFunc _bmp_mem_loader_func;

static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels);
static void (*_image_compress_etc1_func)(Image *, float);
static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels);
static void (*_image_compress_astc_func)(Image *, float, ASTCFormat p_format);
static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_etc1_func)(Image *);
static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format);

static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
Expand Down Expand Up @@ -368,8 +368,8 @@ class Image : public Resource {
COMPRESS_SOURCE_MAX,
};

Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
Error decompress();
bool is_compressed() const;

Expand All @@ -391,8 +391,8 @@ class Image : public Resource {
Rect2i get_used_rect() const;
Ref<Image> get_region(const Rect2i &p_area) const;

static void set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels));
static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels));
static void set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels));
static void set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels));
static String get_format_name(Format p_format);

Error load_png_from_buffer(const Vector<uint8_t> &p_array);
Expand Down
10 changes: 10 additions & 0 deletions core/os/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,16 @@ void OS::add_frame_delay(bool p_can_draw) {
}
}

OS::PreferredTextureFormat OS::get_preferred_texture_format() const {
#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64)
return PREFERRED_TEXTURE_FORMAT_ETC2_ASTC; // By rule, ARM hardware uses ETC texture compression.
#elif defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
return PREFERRED_TEXTURE_FORMAT_S3TC_BPTC; // By rule, X86 hardware prefers S3TC and derivatives.
#else
return PREFERRED_TEXTURE_FORMAT_S3TC_BPTC; // Override in platform if needed.
#endif
}

reduz marked this conversation as resolved.
Show resolved Hide resolved
OS::OS() {
singleton = this;

Expand Down
8 changes: 8 additions & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@ class OS {
virtual Vector<String> get_granted_permissions() const { return Vector<String>(); }

virtual void process_and_drop_events() {}

enum PreferredTextureFormat {
PREFERRED_TEXTURE_FORMAT_S3TC_BPTC,
PREFERRED_TEXTURE_FORMAT_ETC2_ASTC
};

virtual PreferredTextureFormat get_preferred_texture_format() const;

OS();
virtual ~OS();
};
Expand Down
8 changes: 2 additions & 6 deletions doc/classes/Image.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,25 +75,21 @@
<return type="int" enum="Error" />
<param index="0" name="mode" type="int" enum="Image.CompressMode" />
<param index="1" name="source" type="int" enum="Image.CompressSource" default="0" />
<param index="2" name="lossy_quality" type="float" default="0.7" />
<param index="3" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
<param index="2" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
<description>
Compresses the image to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available.
The [param mode] parameter helps to pick the best compression method for DXT and ETC2 formats. It is ignored for ASTC compression.
The [param lossy_quality] parameter is optional for compressors that support it.
For ASTC compression, the [param astc_format] parameter must be supplied.
</description>
</method>
<method name="compress_from_channels">
<return type="int" enum="Error" />
<param index="0" name="mode" type="int" enum="Image.CompressMode" />
<param index="1" name="channels" type="int" enum="Image.UsedChannels" />
<param index="2" name="lossy_quality" type="float" default="0.7" />
<param index="3" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
<param index="2" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
<description>
Compresses the image to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available.
This is an alternative to [method compress] that lets the user supply the channels used in order for the compressor to pick the best DXT and ETC2 formats. For other formats (non DXT or ETC2), this argument is ignored.
The [param lossy_quality] parameter is optional for compressors that support it.
For ASTC compression, the [param astc_format] parameter must be supplied.
</description>
</method>
Expand Down
16 changes: 4 additions & 12 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2285,20 +2285,12 @@
<member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
</member>
<member name="rendering/textures/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the Vulkan renderer.
<member name="rendering/textures/vram_compression/import_etc2_astc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm for lower quality textures and normalmaps and Adaptable Scalable Texture Compression algorithm for high quality textures (in 4x4 block size).
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_etc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression algorithm. This algorithm doesn't support alpha channels in textures.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_etc2" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the Vulkan renderer.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_s3tc" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
<member name="rendering/textures/vram_compression/import_s3tc_bptc" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm (DXT1-5) for lower quality textures and the the BPTC algorithm (BC6H and BC7) for high quality textures. This algorithm is only supported on PC desktop platforms and consoles.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/webp_compression/compression_method" type="int" setter="" getter="" default="2">
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/storage/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ Config::Config() {
}

bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc");
astc_supported = extensions.has("GL_KHR_texture_compression_astc") || extensions.has("GL_OES_texture_compression_astc") || extensions.has("GL_KHR_texture_compression_astc_ldr") || extensions.has("GL_KHR_texture_compression_astc_hdr");
astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_ldr");
astc_layered_supported = extensions.has("GL_KHR_texture_compression_astc_sliced_3d");

#ifdef GLES_OVER_GL
float_texture_supported = true;
etc2_supported = false;
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/storage/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class Config {
bool rgtc_supported = false;
bool bptc_supported = false;
bool etc2_supported = false;
bool astc_supported = false;
bool astc_hdr_supported = false;
bool astc_layered_supported = false;

bool force_vertex_shading = false;

Expand Down
44 changes: 44 additions & 0 deletions drivers/gles3/storage/texture_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,50 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
}
decompress_ra_to_rg = true;
} break;
case Image::FORMAT_ASTC_4x4: {
if (config->astc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_4x4_KHR;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;

} else {
need_decompress = true;
}
} break;
case Image::FORMAT_ASTC_4x4_HDR: {
if (config->astc_hdr_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_4x4_KHR;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;

} else {
need_decompress = true;
}
} break;
case Image::FORMAT_ASTC_8x8: {
if (config->astc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;

} else {
need_decompress = true;
}
} break;
case Image::FORMAT_ASTC_8x8_HDR: {
if (config->astc_hdr_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;

} else {
need_decompress = true;
}
} break;
default: {
ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer");
}
Expand Down
30 changes: 30 additions & 0 deletions drivers/gles3/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,36 @@ namespace GLES3 {
#define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279

#define _EXT_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
#define _EXT_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
#define _EXT_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
#define _EXT_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
#define _EXT_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
#define _EXT_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
#define _EXT_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
#define _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
#define _EXT_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
#define _EXT_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
#define _EXT_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
#define _EXT_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
#define _EXT_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
#define _EXT_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD

#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD

#define _GL_TEXTURE_EXTERNAL_OES 0x8D65

#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/storage/utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ bool Utilities::has_os_feature(const String &p_feature) const {
if (p_feature == "bptc") {
return config->bptc_supported;
}
if (p_feature == "astc") {
return config->astc_supported;
}

if (p_feature == "etc" || p_feature == "etc2") {
return config->etc2_supported;
Expand Down
Loading