summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp4
-rw-r--r--drivers/gles3/shader_gles3.cpp15
-rw-r--r--drivers/gles3/shader_gles3.h10
-rw-r--r--drivers/gles3/shaders/canvas.glsl12
-rw-r--r--drivers/gles3/storage/material_storage.cpp123
-rw-r--r--drivers/gles3/storage/texture_storage.cpp55
-rw-r--r--drivers/gles3/storage/texture_storage.h2
7 files changed, 139 insertions, 82 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 19f2cfd47d..5d3e8ad39d 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -175,7 +175,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state.light_uniforms[index].color[i] = l->color[i];
}
- state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate
+ state.light_uniforms[index].color[3] *= l->energy; //use alpha for energy, so base color can go separate
if (state.shadow_fb != 0) {
state.light_uniforms[index].shadow_pixel_size = (1.0 / state.shadow_texture_size) * (1.0 + l->shadow_smooth);
@@ -238,7 +238,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state.light_uniforms[index].color[i] = l->color[i];
}
- state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate
+ state.light_uniforms[index].color[3] *= l->energy; //use alpha for energy, so base color can go separate
if (state.shadow_fb != 0) {
state.light_uniforms[index].shadow_pixel_size = (1.0 / state.shadow_texture_size) * (1.0 + l->shadow_smooth);
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index abf13fe5ab..29e9ada72b 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -268,10 +268,17 @@ void ShaderGLES3::_get_uniform_locations(Version::Specialization &spec, Version
}
}
// textures
- for (int i = 0; i < p_version->texture_uniforms.size(); i++) {
- String native_uniform_name = _mkid(p_version->texture_uniforms[i]);
+ int texture_index = 0;
+ for (uint32_t i = 0; i < p_version->texture_uniforms.size(); i++) {
+ String native_uniform_name = _mkid(p_version->texture_uniforms[i].name);
GLint location = glGetUniformLocation(spec.id, (native_uniform_name).ascii().get_data());
- glUniform1i(location, i + base_texture_index);
+ Vector<int32_t> texture_uniform_bindings;
+ int texture_count = p_version->texture_uniforms[i].array_size;
+ for (int j = 0; j < texture_count; j++) {
+ texture_uniform_bindings.append(texture_index + base_texture_index);
+ texture_index++;
+ }
+ glUniform1iv(location, texture_uniform_bindings.size(), texture_uniform_bindings.ptr());
}
glUseProgram(0);
@@ -674,7 +681,7 @@ void ShaderGLES3::_initialize_version(Version *p_version) {
_save_to_cache(p_version);
}
-void ShaderGLES3::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const Vector<StringName> &p_texture_uniforms, bool p_initialize) {
+void ShaderGLES3::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const LocalVector<ShaderGLES3::TextureUniformData> &p_texture_uniforms, bool p_initialize) {
Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_COND(!version);
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 565434bb36..c095c41e79 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -54,6 +54,12 @@
#include <stdio.h>
class ShaderGLES3 {
+public:
+ struct TextureUniformData {
+ StringName name;
+ int array_size;
+ };
+
protected:
struct TexUnitPair {
const char *name;
@@ -85,7 +91,7 @@ private:
// Specializations use #ifdefs to toggle behavior on and off for performance, on supporting hardware, they will compile a version with everything enabled, and then compile more copies to improve performance
// Use specializations to enable and disabled advanced features, use variants to toggle behavior when different data may be used (e.g. using a samplerArray vs a sampler, or doing a depth prepass vs a color pass)
struct Version {
- Vector<StringName> texture_uniforms;
+ LocalVector<TextureUniformData> texture_uniforms;
CharString uniforms;
CharString vertex_globals;
CharString fragment_globals;
@@ -242,7 +248,7 @@ protected:
public:
RID version_create();
- void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const Vector<StringName> &p_texture_uniforms, bool p_initialize = false);
+ void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const LocalVector<ShaderGLES3::TextureUniformData> &p_texture_uniforms, bool p_initialize = false);
bool version_is_valid(RID p_version);
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index ae3892fb61..e47e3ae9a3 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -648,7 +648,7 @@ void main() {
vec4 base_color = color;
#ifdef MODE_LIGHT_ONLY
- color = vec4(0.0);
+ float light_only_alpha = 0.0;
#elif !defined(MODE_UNSHADED)
color *= canvas_modulation;
#endif
@@ -691,6 +691,9 @@ void main() {
}
light_blend_compute(light_base, light_color, color.rgb);
+#ifdef MODE_LIGHT_ONLY
+ light_only_alpha += light_color.a;
+#endif
}
// Positional Lights
@@ -788,8 +791,15 @@ void main() {
}
light_blend_compute(light_base, light_color, color.rgb);
+#ifdef MODE_LIGHT_ONLY
+ light_only_alpha += light_color.a;
+#endif
}
#endif
+#ifdef MODE_LIGHT_ONLY
+ color.a *= light_only_alpha;
+#endif
+
frag_color = color;
}
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index db74708214..d92c1b94ae 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -2950,6 +2950,18 @@ void MaterialStorage::material_update_dependency(RID p_material, DependencyTrack
}
}
+LocalVector<ShaderGLES3::TextureUniformData> get_texture_uniform_data(const Vector<ShaderCompiler::GeneratedCode::Texture> &texture_uniforms) {
+ LocalVector<ShaderGLES3::TextureUniformData> texture_uniform_data;
+ for (int i = 0; i < texture_uniforms.size(); i++) {
+ int num_textures = texture_uniforms[i].array_size;
+ if (num_textures == 0) {
+ num_textures = 1;
+ }
+ texture_uniform_data.push_back({ texture_uniforms[i].name, num_textures });
+ }
+ return texture_uniform_data;
+}
+
/* Canvas Shader Data */
void CanvasShaderData::set_code(const String &p_code) {
@@ -3017,12 +3029,9 @@ void CanvasShaderData::set_code(const String &p_code) {
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
- Vector<StringName> texture_uniform_names;
- for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
- texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
- }
+ LocalVector<ShaderGLES3::TextureUniformData> texture_uniform_data = get_texture_uniform_data(gen_code.texture_uniforms);
- MaterialStorage::get_singleton()->shaders.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ MaterialStorage::get_singleton()->shaders.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_data);
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.canvas_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -3065,23 +3074,38 @@ void CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p
update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
}
+static void bind_uniforms_generic(const Vector<RID> &p_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, int texture_offset = 0, const RS::CanvasItemTextureFilter *filter_mapping = filter_from_uniform, const RS::CanvasItemTextureRepeat *repeat_mapping = repeat_from_uniform) {
+ const RID *textures = p_textures.ptr();
+ const ShaderCompiler::GeneratedCode::Texture *texture_uniforms = p_texture_uniforms.ptr();
+ int texture_uniform_index = 0;
+ int texture_uniform_count = 0;
+ for (int ti = 0; ti < p_textures.size(); ti++) {
+ ERR_FAIL_COND_MSG(texture_uniform_index >= p_texture_uniforms.size(), "texture_uniform_index out of bounds");
+ GLES3::Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
+ const ShaderCompiler::GeneratedCode::Texture &texture_uniform = texture_uniforms[texture_uniform_index];
+ if (texture) {
+ glActiveTexture(GL_TEXTURE0 + texture_offset + ti);
+ glBindTexture(target_from_type[texture_uniform.type], texture->tex_id);
+ if (texture->render_target) {
+ texture->render_target->used_in_frame = true;
+ }
+
+ texture->gl_set_filter(filter_mapping[int(texture_uniform.filter)]);
+ texture->gl_set_repeat(repeat_mapping[int(texture_uniform.repeat)]);
+ }
+ texture_uniform_count++;
+ if (texture_uniform_count >= texture_uniform.array_size) {
+ texture_uniform_index++;
+ texture_uniform_count = 0;
+ }
+ }
+}
+
void CanvasMaterialData::bind_uniforms() {
// Bind Material Uniforms
glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_LOCATION, uniform_buffer);
- RID *textures = texture_cache.ptrw();
- ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
- for (int ti = 0; ti < texture_cache.size(); ti++) {
- Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
- glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture
- glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
- if (texture->render_target) {
- texture->render_target->used_in_frame = true;
- }
-
- texture->gl_set_filter(filter_from_uniform_canvas[int(texture_uniforms[ti].filter)]);
- texture->gl_set_repeat(repeat_from_uniform_canvas[int(texture_uniforms[ti].repeat)]);
- }
+ bind_uniforms_generic(texture_cache, shader_data->texture_uniforms, 1, filter_from_uniform_canvas, repeat_from_uniform_canvas); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture
}
CanvasMaterialData::~CanvasMaterialData() {
@@ -3172,12 +3196,9 @@ void SkyShaderData::set_code(const String &p_code) {
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
- Vector<StringName> texture_uniform_names;
- for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
- texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
- }
+ LocalVector<ShaderGLES3::TextureUniformData> texture_uniform_data = get_texture_uniform_data(gen_code.texture_uniforms);
- MaterialStorage::get_singleton()->shaders.sky_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ MaterialStorage::get_singleton()->shaders.sky_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_data);
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.sky_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -3235,19 +3256,7 @@ void SkyMaterialData::bind_uniforms() {
// Bind Material Uniforms
glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
- RID *textures = texture_cache.ptrw();
- ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
- for (int ti = 0; ti < texture_cache.size(); ti++) {
- Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
- glActiveTexture(GL_TEXTURE0 + ti);
- glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
- if (texture->render_target) {
- texture->render_target->used_in_frame = true;
- }
-
- texture->gl_set_filter(filter_from_uniform[int(texture_uniforms[ti].filter)]);
- texture->gl_set_repeat(repeat_from_uniform[int(texture_uniforms[ti].repeat)]);
- }
+ bind_uniforms_generic(texture_cache, shader_data->texture_uniforms);
}
////////////////////////////////////////////////////////////////////////////////
@@ -3435,12 +3444,9 @@ void SceneShaderData::set_code(const String &p_code) {
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
- Vector<StringName> texture_uniform_names;
- for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
- texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
- }
+ LocalVector<ShaderGLES3::TextureUniformData> texture_uniform_data = get_texture_uniform_data(gen_code.texture_uniforms);
- MaterialStorage::get_singleton()->shaders.scene_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ MaterialStorage::get_singleton()->shaders.scene_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_data);
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.scene_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -3517,19 +3523,7 @@ void SceneMaterialData::bind_uniforms() {
// Bind Material Uniforms
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
- RID *textures = texture_cache.ptrw();
- ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
- for (int ti = 0; ti < texture_cache.size(); ti++) {
- Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
- glActiveTexture(GL_TEXTURE0 + ti);
- glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
- if (texture->render_target) {
- texture->render_target->used_in_frame = true;
- }
-
- texture->gl_set_filter(filter_from_uniform[int(texture_uniforms[ti].filter)]);
- texture->gl_set_repeat(repeat_from_uniform[int(texture_uniforms[ti].repeat)]);
- }
+ bind_uniforms_generic(texture_cache, shader_data->texture_uniforms);
}
/* Particles SHADER */
@@ -3575,12 +3569,9 @@ void ParticlesShaderData::set_code(const String &p_code) {
}
}
- Vector<StringName> texture_uniform_names;
- for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
- texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
- }
+ LocalVector<ShaderGLES3::TextureUniformData> texture_uniform_data = get_texture_uniform_data(gen_code.texture_uniforms);
- MaterialStorage::get_singleton()->shaders.particles_process_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ MaterialStorage::get_singleton()->shaders.particles_process_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_data);
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.particles_process_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -3631,19 +3622,7 @@ void ParticleProcessMaterialData::bind_uniforms() {
// Bind Material Uniforms
glBindBufferBase(GL_UNIFORM_BUFFER, GLES3::PARTICLES_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
- RID *textures = texture_cache.ptrw();
- ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
- for (int ti = 0; ti < texture_cache.size(); ti++) {
- Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
- glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is reserved for the heightmap texture.
- glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
- if (texture->render_target) {
- texture->render_target->used_in_frame = true;
- }
-
- texture->gl_set_filter(filter_from_uniform[int(texture_uniforms[ti].filter)]);
- texture->gl_set_repeat(repeat_from_uniform[int(texture_uniforms[ti].repeat)]);
- }
+ bind_uniforms_generic(texture_cache, shader_data->texture_uniforms, 1); // Start at GL_TEXTURE1 because texture slot 0 is reserved for the heightmap texture.
}
#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 3fd54e9180..14c2b3166f 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -751,7 +751,53 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
}
void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
- texture_owner.initialize_rid(p_texture, Texture());
+ ERR_FAIL_COND(p_layers.is_empty());
+
+ ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
+ ERR_FAIL_COND_MSG(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY, "Cubemap Arrays are not supported in the GL Compatibility backend.");
+
+ Ref<Image> image = p_layers[0];
+ {
+ int valid_width = 0;
+ int valid_height = 0;
+ bool valid_mipmaps = false;
+ Image::Format valid_format = Image::FORMAT_MAX;
+
+ for (int i = 0; i < p_layers.size(); i++) {
+ ERR_FAIL_COND(p_layers[i]->is_empty());
+
+ if (i == 0) {
+ valid_width = p_layers[i]->get_width();
+ valid_height = p_layers[i]->get_height();
+ valid_format = p_layers[i]->get_format();
+ valid_mipmaps = p_layers[i]->has_mipmaps();
+ } else {
+ ERR_FAIL_COND(p_layers[i]->get_width() != valid_width);
+ ERR_FAIL_COND(p_layers[i]->get_height() != valid_height);
+ ERR_FAIL_COND(p_layers[i]->get_format() != valid_format);
+ ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps);
+ }
+ }
+ }
+
+ Texture texture;
+ texture.width = image->get_width();
+ texture.height = image->get_height();
+ texture.alloc_width = texture.width;
+ texture.alloc_height = texture.height;
+ texture.mipmaps = image->get_mipmap_count() + 1;
+ texture.format = image->get_format();
+ texture.type = Texture::TYPE_LAYERED;
+ texture.layered_type = p_layered_type;
+ texture.target = GL_TEXTURE_2D_ARRAY;
+ texture.layers = p_layers.size();
+ _get_gl_image_and_format(Ref<Image>(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false);
+ texture.active = true;
+ glGenTextures(1, &texture.tex_id);
+ texture_owner.initialize_rid(p_texture, texture);
+ for (int i = 0; i < p_layers.size(); i++) {
+ _texture_set_data(p_texture, p_layers[i], 1, i == 0);
+ }
}
void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
@@ -1148,6 +1194,10 @@ uint64_t TextureStorage::texture_get_native_handle(RID p_texture, bool p_srgb) c
}
void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+ _texture_set_data(p_texture, p_image, p_layer, false);
+}
+
+void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer, bool initialize) {
Texture *texture = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!texture);
@@ -1257,6 +1307,9 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image,
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (texture->target == GL_TEXTURE_2D_ARRAY) {
+ if (initialize) {
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0, format, type, nullptr);
+ }
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 0, format, type, &read[ofs]);
} else {
glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index c6bdd39dbd..2b939aa7fa 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -451,6 +451,8 @@ private:
void _render_target_clear_sdf(RenderTarget *rt);
Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
+ void _texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer, bool initialize);
+
struct RenderTargetSDF {
CanvasSdfShaderGLES3 shader;
RID shader_version;