Add support for 3D textures to GLES2

This commit is contained in:
clayjohn 2020-01-14 23:53:13 -08:00
parent 8eef6d280b
commit 68915ce20d
8 changed files with 256 additions and 39 deletions

View file

@ -53,6 +53,11 @@
#endif
#endif
#if !defined(GLES_OVER_GL)
#define GL_TEXTURE_2D_ARRAY 0x8C1A
#define GL_TEXTURE_3D 0x806F
#endif
static const GLenum _cube_side_enum[6] = {
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
@ -1343,6 +1348,7 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
const Pair<StringName, RID> *textures = p_material->textures.ptr();
const ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptr();
const ShaderLanguage::DataType *texture_types = p_material->shader->texture_types.ptr();
state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
@ -1356,22 +1362,66 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
if (!t) {
switch (texture_hints[i]) {
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
GLenum target = GL_TEXTURE_2D;
GLuint tex = 0;
switch (texture_types[i]) {
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D:
case ShaderLanguage::TYPE_SAMPLER2D: {
switch (texture_hints[i]) {
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
tex = storage->resources.black_tex;
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
tex = storage->resources.aniso_tex;
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
tex = storage->resources.normal_tex;
} break;
default: {
tex = storage->resources.white_tex;
} break;
}
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex);
case ShaderLanguage::TYPE_SAMPLERCUBE: {
// TODO
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D:
case ShaderLanguage::TYPE_SAMPLER3D: {
target = GL_TEXTURE_3D;
tex = storage->resources.white_tex_3d;
//switch (texture_hints[i]) {
// TODO
//}
} break;
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
target = GL_TEXTURE_2D_ARRAY;
tex = storage->resources.white_tex_array;
//switch (texture_hints[i]) {
// TODO
//}
} break;
default: {
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} break;
}
}
glBindTexture(target, tex);
continue;
}

View file

@ -103,6 +103,13 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT
PFNGLTEXIMAGE3DOESPROC glTexImage3DOES;
PFNGLTEXSUBIMAGE3DOESPROC glTexSubImage3DOES;
PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glCompressedTexSubImage3DOES;
#define glTexImage3D glTexImage3DOES
#define glTexSubImage3D glTexSubImage3DOES
#define glCompressedTexSubImage3D glCompressedTexSubImage3DOES
#elif defined(UWP_ENABLED)
#include <GLES2/gl2ext.h>
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleANGLE
@ -113,6 +120,11 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT
#define GL_MAX_SAMPLES 0x8D57
#endif //!GLES_OVER_GL
#if !defined(GLES_OVER_GL)
#define GL_TEXTURE_2D_ARRAY 0x8C1A
#define GL_TEXTURE_3D 0x806F
#endif
void RasterizerStorageGLES2::bind_quad_array() const {
glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
@ -566,11 +578,23 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6);
} break;
case VS::TEXTURE_TYPE_2D_ARRAY:
case VS::TEXTURE_TYPE_2D_ARRAY: {
if (config.texture_array_supported) {
texture->target = GL_TEXTURE_2D_ARRAY;
texture->images.resize(p_depth_3d);
} else {
WARN_PRINT_ONCE("Texture Arrays not supported on this hardware.");
return;
}
} break;
case VS::TEXTURE_TYPE_3D: {
texture->target = GL_TEXTURE_3D;
ERR_PRINT("3D textures and Texture Arrays are not supported in GLES2. Please switch to the GLES3 backend.");
return;
if (config.texture_3d_supported) {
texture->target = GL_TEXTURE_3D;
texture->images.resize(p_depth_3d);
} else {
WARN_PRINT_ONCE("3D textures not supported on this hardware.");
return;
}
} break;
default: {
ERR_PRINT("Unknown texture type!");
@ -615,7 +639,42 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED)
if ((p_type == VS::TEXTURE_TYPE_3D && config.texture_3d_supported) || (p_type == VS::TEXTURE_TYPE_2D_ARRAY && config.texture_array_supported)) {
int width = p_width;
int height = p_height;
int depth = p_depth_3d;
int mipmaps = 0;
while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) {
width = MAX(1, width);
height = MAX(1, height);
depth = MAX(1, depth);
glTexImage3D(texture->target, mipmaps, internal_format, width, height, depth, 0, format, type, NULL);
width /= 2;
height /= 2;
if (p_type == VS::TEXTURE_TYPE_3D) {
depth /= 2;
}
mipmaps++;
if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS))
break;
}
#ifdef GLES_OVER_GL
glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
#endif
} else
#endif
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//prealloc if video
glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
}
@ -627,8 +686,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
Texture *texture = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!texture);
if (texture->target == GL_TEXTURE_3D) {
// Target is set to a 3D texture or array texture, exit early to avoid spamming errors
if ((texture->type == VS::TEXTURE_TYPE_2D_ARRAY && !config.texture_array_supported) || (texture->type == VS::TEXTURE_TYPE_3D && !config.texture_3d_supported)) {
return;
}
ERR_FAIL_COND(!texture->active);
@ -673,7 +731,23 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
}
}
GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
GLenum blit_target = GL_TEXTURE_2D;
switch (texture->type) {
case VS::TEXTURE_TYPE_2D: {
blit_target = GL_TEXTURE_2D;
} break;
case VS::TEXTURE_TYPE_CUBEMAP: {
ERR_FAIL_INDEX(p_layer, 6);
blit_target = _cube_side_enum[p_layer];
} break;
case VS::TEXTURE_TYPE_2D_ARRAY: {
blit_target = GL_TEXTURE_2D_ARRAY;
} break;
case VS::TEXTURE_TYPE_3D: {
blit_target = GL_TEXTURE_3D;
} break;
}
texture->data_size = img->get_data().size();
PoolVector<uint8_t>::Read read = img->get_data().read();
@ -730,23 +804,41 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
int size, ofs;
img->get_mipmap_offset_and_size(i, ofs, size);
if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
if (compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
if (compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
int bw = w;
int bh = h;
int bw = w;
int bh = h;
glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
} else {
glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
} else {
glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
}
}
}
#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED)
else {
if (texture->compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
int bw = w;
int bh = h;
glCompressedTexSubImage3D(blit_target, i, 0, 0, p_layer, bw, bh, 1, internal_format, size, &read[ofs]);
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage3D(blit_target, i, 0, 0, p_layer, w, h, 1, format, type, &read[ofs]);
}
}
#endif
tsize += size;
@ -1492,6 +1584,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
p_shader->texture_count = gen_code.texture_uniforms.size();
p_shader->texture_hints = gen_code.texture_hints;
p_shader->texture_types = gen_code.texture_types;
p_shader->uses_vertex_time = gen_code.uses_vertex_time;
p_shader->uses_fragment_time = gen_code.uses_fragment_time;
@ -1639,11 +1732,19 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
case ShaderLanguage::TYPE_SAMPLER2DARRAY:
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "TextureArray";
} break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D: {
// Not implemented in GLES2
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture3D";
} break;
}
@ -5795,6 +5896,8 @@ void RasterizerStorageGLES2::initialize() {
config.depth_type = GL_UNSIGNED_INT;
#ifdef GLES_OVER_GL
config.texture_3d_supported = true;
config.texture_array_supported = config.extensions.has("GL_EXT_texture_array");
config.float_texture_supported = true;
config.s3tc_supported = true;
config.pvrtc_supported = false;
@ -5802,6 +5905,8 @@ void RasterizerStorageGLES2::initialize() {
config.support_npot_repeat_mipmap = true;
config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
#else
config.texture_3d_supported = config.extensions.has("GL_OES_texture_3D");
config.texture_array_supported = false;
config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
@ -5840,6 +5945,9 @@ void RasterizerStorageGLES2::initialize() {
void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY);
glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT");
glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT");
glTexImage3DOES = (PFNGLTEXIMAGE3DOESPROC)dlsym(gles2_lib, "glTexImage3DOES");
glTexSubImage3DOES = (PFNGLTEXSUBIMAGE3DOESPROC)dlsym(gles2_lib, "glTexSubImage3DOES");
glCompressedTexSubImage3DOES = (PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC)dlsym(gles2_lib, "glCompressedTexSubImage3DOES");
#endif
#endif
@ -6062,6 +6170,26 @@ void RasterizerStorageGLES2::initialize() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED)
glGenTextures(1, &resources.white_tex_3d);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, resources.white_tex_3d);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
#ifdef GLES_OVER_GL
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
#endif
glGenTextures(1, &resources.white_tex_array);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, resources.white_tex_array);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 8, 8, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0);
#endif
}
// skeleton buffer

View file

@ -71,6 +71,8 @@ public:
Set<String> extensions;
bool texture_3d_supported;
bool texture_array_supported;
bool float_texture_supported;
bool s3tc_supported;
bool etc1_supported;
@ -109,6 +111,8 @@ public:
GLuint black_tex;
GLuint normal_tex;
GLuint aniso_tex;
GLuint white_tex_3d;
GLuint white_tex_array;
GLuint mipmap_blur_fbo;
GLuint mipmap_blur_color;
@ -414,6 +418,7 @@ public:
Map<StringName, RID> default_textures;
Vector<ShaderLanguage::DataType> texture_types;
Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
bool valid;

View file

@ -305,6 +305,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
r_gen_code.texture_hints.resize(max_texture_uniforms);
r_gen_code.texture_types.resize(max_texture_uniforms);
r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms);
@ -332,6 +333,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (SL::is_sampler_type(E->get().type)) {
r_gen_code.texture_uniforms.write[E->get().texture_order] = E->key();
r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint;
r_gen_code.texture_types.write[E->get().texture_order] = E->get().type;
} else {
r_gen_code.uniforms.write[E->get().order] = E->key();
}
@ -660,6 +662,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += "texture2D";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
code += "textureCube";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER3D) {
code += "texture3D";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2DARRAY) {
code += "texture2DArray";
}
} else if (var_node->name == "textureLod") {
@ -669,6 +675,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += "texture2DLod";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
code += "textureCubeLod";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER3D) {
code += "texture3DLod";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2DARRAY) {
code += "texture2DArrayLod";
}
} else if (var_node->name == "mix") {
@ -869,6 +879,7 @@ Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code,
r_gen_code.uniforms.clear();
r_gen_code.texture_uniforms.clear();
r_gen_code.texture_hints.clear();
r_gen_code.texture_types.clear();
r_gen_code.vertex = String();
r_gen_code.vertex_global = String();
r_gen_code.fragment = String();

View file

@ -54,6 +54,7 @@ public:
Vector<CharString> custom_defines;
Vector<StringName> uniforms;
Vector<StringName> texture_uniforms;
Vector<ShaderLanguage::DataType> texture_types;
Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
String vertex_global;

View file

@ -10,6 +10,12 @@ precision highp float;
precision highp int;
#endif
#ifndef USE_GLES_OVER_GL
#extension GL_OES_texture_3D : enable
#else
#extension GL_EXT_texture_array : enable
#endif
uniform highp mat4 projection_matrix;
/* clang-format on */
@ -229,6 +235,12 @@ VERTEX_SHADER_CODE
/* clang-format off */
[fragment]
#ifndef USE_GLES_OVER_GL
#extension GL_OES_texture_3D : enable
#else
#extension GL_EXT_texture_array : enable
#endif
// texture2DLodEXT and textureCubeLodEXT are fragment shader specific.
// Do not copy these defines in the vertex section.
#ifndef USE_GLES_OVER_GL

View file

@ -10,6 +10,12 @@ precision highp float;
precision highp int;
#endif
#ifndef USE_GLES_OVER_GL
#extension GL_OES_texture_3D : enable
#else
#extension GL_EXT_texture_array : enable
#endif
/* clang-format on */
#include "stdlib.glsl"
/* clang-format off */
@ -672,6 +678,12 @@ VERTEX_SHADER_CODE
/* clang-format off */
[fragment]
#ifndef USE_GLES_OVER_GL
#extension GL_OES_texture_3D : enable
#else
#extension GL_EXT_texture_array : enable
#endif
// texture2DLodEXT and textureCubeLodEXT are fragment shader specific.
// Do not copy these defines in the vertex section.
#ifndef USE_GLES_OVER_GL

View file

@ -1967,14 +1967,14 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
@ -2004,10 +2004,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
@ -4698,10 +4698,8 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
case TYPE_UVEC4:
case TYPE_ISAMPLER2D:
case TYPE_USAMPLER2D:
case TYPE_SAMPLER3D:
case TYPE_ISAMPLER3D:
case TYPE_USAMPLER3D:
case TYPE_SAMPLER2DARRAY:
case TYPE_USAMPLER2DARRAY:
case TYPE_ISAMPLER2DARRAY:
invalid_type = true;