소스 검색

Merge pull request #80481 from lawnjelly/clay_unbind_textures

[3.x] Unbind texture slots when changing framebuffer
Rémi Verschelde 2 년 전
부모
커밋
dcb097c7a1

+ 13 - 13
drivers/gles2/rasterizer_canvas_base_gles2.cpp

@@ -99,7 +99,7 @@ void RasterizerCanvasBaseGLES2::canvas_begin() {
 
 	reset_canvas();
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 	glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
@@ -191,7 +191,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture
 			state.current_tex = RID();
 			state.current_tex_ptr = nullptr;
 
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 			glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 		} else {
@@ -205,7 +205,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture
 				texture->render_target->used_in_frame = true;
 			}
 
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 			glBindTexture(GL_TEXTURE_2D, texture->tex_id);
 
 			state.current_tex = p_texture;
@@ -217,7 +217,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture
 		state.current_tex = RID();
 		state.current_tex_ptr = nullptr;
 
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 	}
 
@@ -230,7 +230,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture
 
 		if (!normal_map) {
 			state.current_normal = RID();
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 			glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
 			state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false);
 
@@ -241,7 +241,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture
 
 			normal_map = normal_map->get_ptr();
 
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 			glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
 			state.current_normal = p_normal_map;
 			state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, true);
@@ -249,7 +249,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture
 
 	} else {
 		state.current_normal = RID();
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
 		state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false);
 	}
@@ -272,7 +272,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac
 		draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h),
 				Rect2(0, 0, (float)black_margin[MARGIN_LEFT] / sz.x, (float)(window_h) / sz.y));
 	} else if (black_margin[MARGIN_LEFT]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, 1, 1));
@@ -284,7 +284,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac
 		draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h),
 				Rect2(0, 0, (float)black_margin[MARGIN_RIGHT] / sz.x, (float)window_h / sz.y));
 	} else if (black_margin[MARGIN_RIGHT]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, 1, 1));
@@ -298,7 +298,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac
 				Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[MARGIN_TOP] / sz.y));
 
 	} else if (black_margin[MARGIN_TOP]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, 1, 1));
@@ -312,7 +312,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac
 				Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[MARGIN_BOTTOM] / sz.y));
 
 	} else if (black_margin[MARGIN_BOTTOM]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, 1, 1));
@@ -364,7 +364,7 @@ void RasterizerCanvasBaseGLES2::_set_uniforms() {
 
 		if (state.using_shadow) {
 			RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer);
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
 			glBindTexture(GL_TEXTURE_2D, cls->distance);
 			state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache);
 			state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color);
@@ -723,7 +723,7 @@ void RasterizerCanvasBaseGLES2::_copy_screen(const Rect2 &p_rect) {
 	storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, !state.using_transparent_rt);
 
 	glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo);
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 
 	storage->shaders.copy.bind();

+ 12 - 13
drivers/gles2/rasterizer_canvas_gles2.cpp

@@ -1233,7 +1233,7 @@ void RasterizerCanvasGLES2::canvas_render_items_implementation(Item *p_item_list
 	state.current_normal = RID();
 	state.canvas_texscreen_used = false;
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 	if (bdata.settings_use_batching) {
@@ -1621,7 +1621,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 		}
 
 		if (skeleton) {
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 			glBindTexture(GL_TEXTURE_2D, skeleton->tex_id);
 			state.using_skeleton = true;
 		} else {
@@ -1656,7 +1656,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 				}
 
 				if (storage->frame.current_rt->copy_screen_effect.color) {
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 					glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color);
 				}
 			}
@@ -1676,7 +1676,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 			ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw();
 
 			for (int i = 0; i < tc; i++) {
-				glActiveTexture(GL_TEXTURE0 + i);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i);
 
 				RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second);
 
@@ -1856,7 +1856,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 				_set_uniforms();
 				state.canvas_shader.use_material((void *)material_ptr);
 
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
 				RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture);
 				if (!t) {
 					glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
@@ -1866,9 +1866,8 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 					glBindTexture(t->target, t->tex_id);
 				}
 
-				glActiveTexture(GL_TEXTURE0);
-				_legacy_canvas_item_render_commands(p_ci, nullptr, reclip, material_ptr); //redraw using light
-
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
+				_legacy_canvas_item_render_commands(p_ci, nullptr, reclip, material_ptr); //redraw using lights
 				state.using_light = nullptr;
 			}
 
@@ -1985,7 +1984,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
 		}
 
 		if (skeleton) {
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 			glBindTexture(GL_TEXTURE_2D, skeleton->tex_id);
 			state.using_skeleton = true;
 		} else {
@@ -2021,7 +2020,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
 				}
 
 				if (storage->frame.current_rt->copy_screen_effect.color) {
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 					glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color);
 				}
 			}
@@ -2041,7 +2040,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
 			ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw();
 
 			for (int i = 0; i < tc; i++) {
-				glActiveTexture(GL_TEXTURE0 + i);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i);
 
 				RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second);
 
@@ -2239,7 +2238,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
 				_set_uniforms();
 				state.canvas_shader.use_material((void *)material_ptr);
 
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
 				RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture);
 				if (!t) {
 					glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
@@ -2249,7 +2248,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
 					glBindTexture(t->target, t->tex_id);
 				}
 
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 				// redraw using light.
 				// if there is no clip item, we can consider scissoring to the intersection area between the light and the item

+ 6 - 3
drivers/gles2/rasterizer_gles2.cpp

@@ -317,6 +317,9 @@ void RasterizerGLES2::set_current_render_target(RID p_render_target) {
 		glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
 		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 	}
+
+	// Unbind texture slots.
+	storage->gl_wrapper.reset();
 }
 
 void RasterizerGLES2::restore_render_target(bool p_3d_was_drawn) {
@@ -379,7 +382,7 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
 	}
 
 	RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(texture);
-	glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 	glBindTexture(GL_TEXTURE_2D, t->tex_id);
 	canvas->draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1));
 	glBindTexture(GL_TEXTURE_2D, 0);
@@ -409,7 +412,7 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
 	canvas->canvas_begin();
 	glDisable(GL_BLEND);
 	glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
-	glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 	if (rt->external.fbo != 0) {
 		glBindTexture(GL_TEXTURE_2D, rt->external.color);
 	} else {
@@ -438,7 +441,7 @@ void RasterizerGLES2::output_lens_distorted_to_screen(RID p_render_target, const
 	glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 
 	// output our texture
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, rt->color);
 
 	canvas->draw_lens_distortion_rect(p_screen_rect, p_k1, p_k2, p_eye_center, p_oversample);

+ 43 - 43
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -189,7 +189,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
 		}
 
 		// create a depth texture
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 		if (storage->config.use_rgba_3d_shadows) {
 			//maximum compatibility, renderbuffer and RGBA shadow
@@ -609,7 +609,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
 		GLenum format = GL_RGB;
 		GLenum type = GL_UNSIGNED_BYTE;
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 		glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth);
 		glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_buffer_internalformat, size, size);
@@ -672,7 +672,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
 		}
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
 	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to
 
@@ -684,7 +684,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
 	}
 	//do filtering
 	//vdc cache
-	glActiveTexture(GL_TEXTURE1);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 	glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex);
 
 	// now render to the framebuffer, mipmap level for mipmap level
@@ -700,12 +700,12 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
 
 	//blur
 	while (size >= 1) {
-		glActiveTexture(GL_TEXTURE3);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE3);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.mipmap_blur_color);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, storage->resources.mipmap_blur_color, 0);
 		glViewport(0, 0, size, size);
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 		for (int i = 0; i < 6; i++) {
 			storage->bind_quad_array();
@@ -724,12 +724,12 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
 	}
 
 	// restore ranges
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 	glBindTexture(GL_TEXTURE_2D, 0);
-	glActiveTexture(GL_TEXTURE3); //back to panorama
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE3); //back to panorama
 	glBindTexture(GL_TEXTURE_2D, 0);
-	glActiveTexture(GL_TEXTURE1);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 	glBindTexture(GL_TEXTURE_2D, 0);
 	glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 
@@ -1257,7 +1257,7 @@ void RasterizerSceneGLES2::_copy_texture_to_buffer(GLuint p_texture, GLuint p_bu
 	glDepthFunc(GL_LEQUAL);
 	glColorMask(1, 1, 1, 1);
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, p_texture);
 
 	glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
@@ -1370,12 +1370,12 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
 	state.scene_shader.set_custom_shader(p_material->shader->custom_code_id);
 
 	if (p_material->shader->spatial.uses_screen_texture && storage->frame.current_rt) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color);
 	}
 
 	if (p_material->shader->spatial.uses_depth_texture && storage->frame.current_rt) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 	}
 
@@ -1410,7 +1410,7 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
 	state.current_main_tex = 0;
 
 	for (int i = 0; i < tc; i++) {
-		glActiveTexture(GL_TEXTURE0 + i);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i);
 
 		RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second);
 
@@ -1524,7 +1524,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
 			if (p_skeleton) {
 				if (!storage->config.use_skeleton_software) {
 					//use float texture workflow
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 					glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id);
 				} else {
 					//use transform buffer workflow
@@ -1832,11 +1832,11 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
 						t->render_target->used_in_frame = true;
 					}
 
-					glActiveTexture(GL_TEXTURE0);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 					glBindTexture(t->target, t->tex_id);
 					restore_tex = true;
 				} else if (restore_tex) {
-					glActiveTexture(GL_TEXTURE0);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 					glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
 					restore_tex = false;
 				}
@@ -1894,7 +1894,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
 			}
 
 			if (restore_tex) {
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 				glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
 				restore_tex = false;
 			}
@@ -1944,7 +1944,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
 			state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, p_light->light_ptr->directional_blend_splits);
 			if (!state.render_no_shadows && p_light->light_ptr->shadow) {
 				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 				if (storage->config.use_rgba_3d_shadows) {
 					glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
 				} else {
@@ -1959,7 +1959,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
 			state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true);
 			if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
 				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 				if (storage->config.use_rgba_3d_shadows) {
 					glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
 				} else {
@@ -1973,7 +1973,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
 			state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true);
 			if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
 				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 				if (storage->config.use_rgba_3d_shadows) {
 					glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
 				} else {
@@ -2261,7 +2261,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 	bool use_radiance_map = false;
 	if (!p_shadow && p_base_env) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 		glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env);
 		use_radiance_map = true;
 		state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, true); //since prev unshaded is false, this needs to be true if exists
@@ -2448,11 +2448,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 				state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != nullptr);
 				state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != nullptr);
 				if (refprobe_1 != nullptr && refprobe_1 != prev_refprobe_1) {
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
 					glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap);
 				}
 				if (refprobe_2 != nullptr && refprobe_2 != prev_refprobe_2) {
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
 					glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap);
 				}
 				rebind = true;
@@ -2480,7 +2480,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 			if (lightmap != prev_lightmap) {
 				state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, lightmap != nullptr);
 				if (lightmap != nullptr) {
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 					glBindTexture(GL_TEXTURE_2D, lightmap->tex_id);
 				}
 				rebind = true;
@@ -2690,7 +2690,7 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C
 
 	tex = tex->get_ptr(); //resolve for proxies
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(tex->target, tex->tex_id);
 
 	glDepthMask(GL_TRUE);
@@ -2889,10 +2889,10 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 		if (storage->frame.current_rt->mip_maps[0].color) {
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
@@ -2909,7 +2909,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 
 		storage->_copy_screen();
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(0, 1));
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level
@@ -2925,7 +2925,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 	if (env && env->dof_blur_near_enabled) {
 		//convert texture to RGBA format if not already
 		if (!storage->frame.current_rt->used_dof_blur_near) {
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
 		}
@@ -2954,10 +2954,10 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		if (storage->frame.current_rt->mip_maps[0].color) {
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
 		} else {
@@ -2984,7 +2984,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level
@@ -3008,7 +3008,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 
 	if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) {
 		//these needed to disable filtering, reenamble
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		if (storage->frame.current_rt->mip_maps[0].color) {
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
@@ -3061,7 +3061,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_STRENGTH, env->glow_strength);
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LUMINANCE_CAP, env->glow_hdr_luminance_cap);
 
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 			if (storage->frame.current_rt->mip_maps[0].color) {
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
@@ -3086,7 +3086,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LOD, storage->frame.current_rt->mip_maps[0].color ? float(i) : 0.0);
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_STRENGTH, env->glow_strength);
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 			if (storage->frame.current_rt->mip_maps[0].color) {
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[1].color);
@@ -3108,7 +3108,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	if (storage->frame.current_rt->mip_maps[0].color) {
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
 	} else {
@@ -3147,7 +3147,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 						}
 					}
 				}
-				glActiveTexture(GL_TEXTURE2);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
 			} else {
 				state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_MULTI_TEXTURE_GLOW, true);
@@ -3155,7 +3155,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 				for (int i = 0; i < (max_glow_level + 1); i++) {
 					if (glow_mask & (1 << i)) {
 						active_glow_level++;
-						glActiveTexture(GL_TEXTURE1 + active_glow_level);
+						WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1 + active_glow_level);
 						glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[i + 1].color);
 						if (active_glow_level == 1) {
 							state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL1, true);
@@ -3194,7 +3194,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
 		RasterizerStorageGLES2::Texture *tex = storage->texture_owner.getornull(env->color_correction);
 		if (tex) {
 			state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_COLOR_CORRECTION, true);
-			glActiveTexture(GL_TEXTURE1);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 			glBindTexture(tex->target, tex->tex_id);
 		}
 	}
@@ -3614,7 +3614,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
 #ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW
 	ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
 	if (shadow_atlas) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
 
 		glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4);
@@ -3633,7 +3633,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
 
 #ifdef GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW
 	if (true) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
 
 		glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4);
@@ -3881,7 +3881,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 		glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
 		state.cube_to_dp_shader.bind();
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_CUBE_MAP, shadow_cubemaps[current_cubemap].cubemap);
 
 		glDisable(GL_CULL_FACE);
@@ -4064,7 +4064,7 @@ void RasterizerSceneGLES2::initialize() {
 
 		int cube_size = max_shadow_cubemap_sampler_size;
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 		while (cube_size >= 32) {
 			ShadowCubeMap cube;

+ 40 - 25
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -120,6 +120,20 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT
 #define GL_MAX_SAMPLES 0x8D57
 #endif //!GLES_OVER_GL
 
+void RasterizerStorageGLES2::GLWrapper::initialize(int p_max_texture_image_units) {
+	texture_unit_table.create(p_max_texture_image_units);
+}
+
+void RasterizerStorageGLES2::GLWrapper::reset() {
+	for (uint32_t i = 0; i < texture_units_bound.size(); i++) {
+		::glActiveTexture(GL_TEXTURE0 + texture_units_bound[i]);
+		glBindTexture(GL_TEXTURE_2D, 0);
+	}
+
+	texture_units_bound.clear();
+	texture_unit_table.blank();
+}
+
 void RasterizerStorageGLES2::bind_quad_array() const {
 	glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
 	glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, nullptr);
@@ -599,7 +613,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
 		texture->compressed = compressed;
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	if (p_type == VS::TEXTURE_TYPE_EXTERNAL) {
@@ -669,7 +683,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 	PoolVector<uint8_t>::Read read = img->get_data().read();
 	ERR_FAIL_COND(!read.ptr());
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	texture->ignore_mipmaps = compressed && !img->has_mipmaps();
@@ -798,7 +812,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
 	data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
 	PoolVector<uint8_t>::Write wb = data.write();
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 	glBindTexture(texture->target, texture->tex_id);
 
@@ -860,7 +874,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
 	glDisable(GL_BLEND);
 	glDepthFunc(GL_LEQUAL);
 	glColorMask(1, 1, 1, 1);
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, texture->tex_id);
 
 	glViewport(0, 0, texture->alloc_width, texture->alloc_height);
@@ -902,7 +916,7 @@ void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags)
 
 	texture->flags = p_flags;
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) {
@@ -990,7 +1004,7 @@ void RasterizerStorageGLES2::texture_bind(RID p_texture, uint32_t p_texture_no)
 
 	ERR_FAIL_COND(!texture);
 
-	glActiveTexture(GL_TEXTURE0 + p_texture_no);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0 + p_texture_no);
 	glBindTexture(texture->target, texture->tex_id);
 }
 
@@ -1180,7 +1194,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 		}
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1188,7 +1202,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //need this for proper sampling
 
-	glActiveTexture(GL_TEXTURE1);
+	gl_wrapper.gl_active_texture(GL_TEXTURE1);
 	glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex);
 
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1197,7 +1211,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
 	// New cubemap that will hold the mipmaps with different roughness values
-	glActiveTexture(GL_TEXTURE2);
+	gl_wrapper.gl_active_texture(GL_TEXTURE2);
 	glGenTextures(1, &sky->radiance);
 	glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance);
 
@@ -1237,7 +1251,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 	// third, render to the framebuffer using separate textures, then copy to mipmaps
 	while (size >= 1) {
 		//make framebuffer size the texture size, need to use a separate texture for compatibility
-		glActiveTexture(GL_TEXTURE3);
+		gl_wrapper.gl_active_texture(GL_TEXTURE3);
 		glBindTexture(GL_TEXTURE_2D, resources.mipmap_blur_color);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resources.mipmap_blur_color, 0);
@@ -1251,7 +1265,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 		glViewport(0, 0, size, size);
 		bind_quad_array();
 
-		glActiveTexture(GL_TEXTURE2); //back to panorama
+		gl_wrapper.gl_active_texture(GL_TEXTURE2); //back to panorama
 
 		for (int i = 0; i < 6; i++) {
 			shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
@@ -1277,7 +1291,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 	shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false);
 
 	// restore ranges
-	glActiveTexture(GL_TEXTURE2); //back to panorama
+	gl_wrapper.gl_active_texture(GL_TEXTURE2); //back to panorama
 
 	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -1285,18 +1299,18 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
 	glBindTexture(GL_TEXTURE_2D, 0);
-	glActiveTexture(GL_TEXTURE3); //back to panorama
+	gl_wrapper.gl_active_texture(GL_TEXTURE3); //back to panorama
 	glBindTexture(GL_TEXTURE_2D, 0);
-	glActiveTexture(GL_TEXTURE1);
+	gl_wrapper.gl_active_texture(GL_TEXTURE1);
 	glBindTexture(GL_TEXTURE_2D, 0);
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, 0);
 
 	//reset flags on Sky Texture that may have changed
 	texture_set_flags(sky->panorama, texture->flags);
 
 	// Framebuffer did its job. thank mr framebuffer
-	glActiveTexture(GL_TEXTURE0); //back to panorama
+	gl_wrapper.gl_active_texture(GL_TEXTURE0); //back to panorama
 	glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 }
 
@@ -3653,7 +3667,7 @@ void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool
 	skeleton->use_2d = p_2d_skeleton;
 
 	if (!config.use_skeleton_software) {
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, skeleton->tex_id);
 
 #ifdef GLES_OVER_GL
@@ -4171,7 +4185,7 @@ void RasterizerStorageGLES2::update_dirty_skeletons() {
 		return;
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 	while (skeleton_update_list.first()) {
 		Skeleton *skeleton = skeleton_update_list.first()->self();
@@ -5793,7 +5807,7 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
 	cls->size = p_width;
 	cls->height = 16;
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 	glGenFramebuffers(1, &cls->fbo);
 	glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
@@ -6493,6 +6507,7 @@ void RasterizerStorageGLES2::initialize() {
 
 	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units);
 	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
+	gl_wrapper.initialize(config.max_texture_image_units);
 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
 	glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &config.max_cubemap_texture_size);
 	glGetIntegerv(GL_MAX_VIEWPORT_DIMS, config.max_viewport_dimensions);
@@ -6546,7 +6561,7 @@ void RasterizerStorageGLES2::initialize() {
 		for (int i = 0; i < 8 * 8 * 3; i++) {
 			whitetexdata[i] = 255;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.white_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -6558,7 +6573,7 @@ void RasterizerStorageGLES2::initialize() {
 		for (int i = 0; i < 8 * 8 * 3; i++) {
 			blacktexdata[i] = 0;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.black_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, blacktexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -6570,7 +6585,7 @@ void RasterizerStorageGLES2::initialize() {
 		for (int i = 0; i < 8 * 8 * 4; i++) {
 			transparenttexdata[i] = 0;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.transparent_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, transparenttexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -6584,7 +6599,7 @@ void RasterizerStorageGLES2::initialize() {
 			normaltexdata[i + 1] = 128;
 			normaltexdata[i + 2] = 255;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.normal_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, normaltexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -6598,7 +6613,7 @@ void RasterizerStorageGLES2::initialize() {
 			anisotexdata[i + 1] = 128;
 			anisotexdata[i + 2] = 0;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.aniso_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -6621,7 +6636,7 @@ void RasterizerStorageGLES2::initialize() {
 	if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere
 		glGenTextures(1, &resources.radical_inverse_vdc_cache_tex);
 
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex);
 
 		uint8_t radical_inverse[512];

+ 24 - 0
drivers/gles2/rasterizer_storage_gles2.h

@@ -31,6 +31,7 @@
 #ifndef RASTERIZER_STORAGE_GLES2_H
 #define RASTERIZER_STORAGE_GLES2_H
 
+#include "core/bitfield_dynamic.h"
 #include "core/pool_vector.h"
 #include "core/self_list.h"
 #include "drivers/gles_common/rasterizer_asserts.h"
@@ -45,6 +46,8 @@
 class RasterizerCanvasGLES2;
 class RasterizerSceneGLES2;
 
+#define WRAPPED_GL_ACTIVE_TEXTURE storage->gl_wrapper.gl_active_texture
+
 class RasterizerStorageGLES2 : public RasterizerStorage {
 public:
 	RasterizerCanvasGLES2 *canvas;
@@ -1347,6 +1350,27 @@ public:
 
 	} frame;
 
+	struct GLWrapper {
+		mutable BitFieldDynamic texture_unit_table;
+		mutable LocalVector<uint32_t> texture_units_bound;
+
+		void gl_active_texture(GLenum p_texture) const {
+			::glActiveTexture(p_texture);
+
+			p_texture -= GL_TEXTURE0;
+
+			// Check for below zero and above max in one check.
+			ERR_FAIL_COND((unsigned int)p_texture >= texture_unit_table.get_num_bits());
+
+			// Set if the first occurrence in the table.
+			if (texture_unit_table.check_and_set(p_texture)) {
+				texture_units_bound.push_back(p_texture);
+			}
+		}
+		void initialize(int p_max_texture_image_units);
+		void reset();
+	} gl_wrapper;
+
 	void initialize();
 	void finalize();
 

+ 15 - 15
drivers/gles3/rasterizer_canvas_base_gles3.cpp

@@ -221,7 +221,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasBaseGLES3::_bind_canvas_texture
 		if (!texture) {
 			state.current_tex = RID();
 			state.current_tex_ptr = nullptr;
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 		} else {
@@ -235,7 +235,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasBaseGLES3::_bind_canvas_texture
 				texture->render_target->used_in_frame = true;
 			}
 
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			glBindTexture(GL_TEXTURE_2D, texture->tex_id);
 			state.current_tex = p_texture;
 			state.current_tex_ptr = texture;
@@ -244,7 +244,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasBaseGLES3::_bind_canvas_texture
 		}
 
 	} else {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 		state.current_tex = RID();
 		state.current_tex_ptr = nullptr;
@@ -259,7 +259,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasBaseGLES3::_bind_canvas_texture
 
 		if (!normal_map) {
 			state.current_normal = RID();
-			glActiveTexture(GL_TEXTURE1);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 			glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
 			state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false);
 
@@ -270,7 +270,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasBaseGLES3::_bind_canvas_texture
 
 			normal_map = normal_map->get_ptr();
 
-			glActiveTexture(GL_TEXTURE1);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 			glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
 			state.current_normal = p_normal_map;
 			state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, true);
@@ -278,7 +278,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasBaseGLES3::_bind_canvas_texture
 
 	} else {
 		state.current_normal = RID();
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
 		state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false);
 	}
@@ -734,7 +734,7 @@ void RasterizerCanvasBaseGLES3::_copy_texscreen(const Rect2 &p_rect) {
 	}
 
 	glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 
 	storage->shaders.copy.bind();
@@ -752,7 +752,7 @@ void RasterizerCanvasBaseGLES3::_copy_texscreen(const Rect2 &p_rect) {
 		scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
 		scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
 		scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section);
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo);
 
@@ -766,7 +766,7 @@ void RasterizerCanvasBaseGLES3::_copy_texscreen(const Rect2 &p_rect) {
 		scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
 		scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
 		scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section);
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger
 
@@ -954,11 +954,11 @@ void RasterizerCanvasBaseGLES3::reset_canvas() {
 
 	//use for reading from screen
 	if (storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING]) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 	glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
@@ -1047,7 +1047,7 @@ void RasterizerCanvasBaseGLES3::draw_window_margins(int *black_margin, RID *blac
 		draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h),
 				Rect2(0, 0, (float)black_margin[MARGIN_LEFT] / sz.x, (float)(window_h) / sz.y));
 	} else if (black_margin[MARGIN_LEFT]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, 1, 1));
@@ -1059,7 +1059,7 @@ void RasterizerCanvasBaseGLES3::draw_window_margins(int *black_margin, RID *blac
 		draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h),
 				Rect2(0, 0, (float)black_margin[MARGIN_RIGHT] / sz.x, (float)window_h / sz.y));
 	} else if (black_margin[MARGIN_RIGHT]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, 1, 1));
@@ -1073,7 +1073,7 @@ void RasterizerCanvasBaseGLES3::draw_window_margins(int *black_margin, RID *blac
 				Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[MARGIN_TOP] / sz.y));
 
 	} else if (black_margin[MARGIN_TOP]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, 1, 1));
@@ -1087,7 +1087,7 @@ void RasterizerCanvasBaseGLES3::draw_window_margins(int *black_margin, RID *blac
 				Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[MARGIN_BOTTOM] / sz.y));
 
 	} else if (black_margin[MARGIN_BOTTOM]) {
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
 
 		draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, 1, 1));

+ 12 - 12
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -134,7 +134,7 @@ void RasterizerCanvasGLES3::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 		}
 
 		if (skeleton) {
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 			glBindTexture(GL_TEXTURE_2D, skeleton->texture);
 			state.using_skeleton = true;
 		} else {
@@ -186,7 +186,7 @@ void RasterizerCanvasGLES3::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 			ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw();
 
 			for (int i = 0; i < tc; i++) {
-				glActiveTexture(GL_TEXTURE2 + i);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2 + i);
 
 				RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]);
 				if (!t) {
@@ -403,7 +403,7 @@ void RasterizerCanvasGLES3::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 
 				if (has_shadow) {
 					RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer);
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 					glBindTexture(GL_TEXTURE_2D, cls->distance);
 
 					/*canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_MATRIX,light->shadow_matrix_cache);
@@ -411,7 +411,7 @@ void RasterizerCanvasGLES3::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 					canvas_shader.set_uniform(CanvasShaderGLES3::LIGHT_SHADOW_COLOR,light->shadow_color);*/
 				}
 
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 				RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(light->texture);
 				if (!t) {
 					glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
@@ -421,7 +421,7 @@ void RasterizerCanvasGLES3::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
 					glBindTexture(t->target, t->tex_id);
 				}
 
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 				_legacy_canvas_item_render_commands(p_ci, r_ris.current_clip, reclip, nullptr); //redraw using light
 			}
 
@@ -1220,7 +1220,7 @@ void RasterizerCanvasGLES3::render_joined_item(const BItemJoined &p_bij, RenderI
 		}
 
 		if (skeleton) {
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 			glBindTexture(GL_TEXTURE_2D, skeleton->texture);
 			state.using_skeleton = true;
 		} else {
@@ -1273,7 +1273,7 @@ void RasterizerCanvasGLES3::render_joined_item(const BItemJoined &p_bij, RenderI
 			ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw();
 
 			for (int i = 0; i < tc; i++) {
-				glActiveTexture(GL_TEXTURE2 + i);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2 + i);
 
 				RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]);
 				if (!t) {
@@ -1514,7 +1514,7 @@ void RasterizerCanvasGLES3::render_joined_item(const BItemJoined &p_bij, RenderI
 
 				if (has_shadow) {
 					RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer);
-					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 					glBindTexture(GL_TEXTURE_2D, cls->distance);
 
 					/*canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_MATRIX,light->shadow_matrix_cache);
@@ -1522,7 +1522,7 @@ void RasterizerCanvasGLES3::render_joined_item(const BItemJoined &p_bij, RenderI
 					canvas_shader.set_uniform(CanvasShaderGLES3::LIGHT_SHADOW_COLOR,light->shadow_color);*/
 				}
 
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 				RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(light->texture);
 				if (!t) {
 					glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
@@ -1532,7 +1532,7 @@ void RasterizerCanvasGLES3::render_joined_item(const BItemJoined &p_bij, RenderI
 					glBindTexture(t->target, t->tex_id);
 				}
 
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 				// redraw using light.
 				// if there is no clip item, we can consider scissoring to the intersection area between the light and the item
@@ -1903,7 +1903,7 @@ void RasterizerCanvasGLES3::canvas_render_items_implementation(Item *p_item_list
 	state.current_tex = RID();
 	state.current_tex_ptr = nullptr;
 	state.current_normal = RID();
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 	//	state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false);
@@ -1911,7 +1911,7 @@ void RasterizerCanvasGLES3::canvas_render_items_implementation(Item *p_item_list
 	//	state.current_tex_ptr = NULL;
 	//	state.current_normal = RID();
 	//	state.canvas_texscreen_used = false;
-	//	glActiveTexture(GL_TEXTURE0);
+	//	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	//	glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 	if (bdata.settings_use_batching) {

+ 6 - 3
drivers/gles3/rasterizer_gles3.cpp

@@ -248,6 +248,9 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target) {
 		glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
 		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
 	}
+
+	// Unbind texture slots.
+	storage->gl_wrapper.reset();
 }
 
 void RasterizerGLES3::restore_render_target(bool p_3d_was_drawn) {
@@ -316,7 +319,7 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
 	}
 
 	RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(texture);
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, t->tex_id);
 	canvas->draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1));
 	glBindTexture(GL_TEXTURE_2D, 0);
@@ -354,7 +357,7 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re
 		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
 
 		// output our texture
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		if (rt->external.fbo != 0) {
 			glBindTexture(GL_TEXTURE_2D, rt->external.color);
 		} else {
@@ -394,7 +397,7 @@ void RasterizerGLES3::output_lens_distorted_to_screen(RID p_render_target, const
 	glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
 
 	// output our texture
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, rt->color);
 
 	canvas->draw_lens_distortion_rect(p_screen_rect, p_k1, p_k2, p_eye_center, p_oversample);

+ 76 - 76
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -166,7 +166,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) {
 		glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
 
 		// Create a texture for storing the depth
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glGenTextures(1, &shadow_atlas->depth);
 		glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadow_atlas->size, shadow_atlas->size, 0,
@@ -525,7 +525,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size
 		GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
 
 		// Create a texture for storing the color
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glGenTextures(1, &reflection_atlas->color);
 		glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
 
@@ -736,7 +736,7 @@ bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_inst
 	}
 
 	glDisable(GL_BLEND);
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_CUBE_MAP, reflection_cubemaps[cubemap_index].cubemap);
 	glDisable(GL_CULL_FACE);
 
@@ -1152,7 +1152,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
 	state.current_main_tex = 0;
 
 	for (int i = 0; i < tc; i++) {
-		glActiveTexture(GL_TEXTURE0 + i);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i);
 
 		GLenum target = GL_TEXTURE_2D;
 		GLuint tex = 0;
@@ -1590,12 +1590,12 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
 						t->render_target->used_in_frame = true;
 					}
 
-					glActiveTexture(GL_TEXTURE0);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 					glBindTexture(t->target, t->tex_id);
 					restore_tex = true;
 
 				} else if (restore_tex) {
-					glActiveTexture(GL_TEXTURE0);
+					WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 					glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
 					restore_tex = false;
 				}
@@ -1658,7 +1658,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
 			}
 
 			if (restore_tex) {
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 				glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
 				restore_tex = false;
 			}
@@ -1863,9 +1863,9 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
 		// a conditioned one, the fact that async compilation is enabled is enough for us to switch to the alternative
 		// arrangement of texturing units.
 		if (storage->config.async_compilation_enabled) {
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 12);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 12);
 		} else {
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 10);
 		}
 		glBindTexture(GL_TEXTURE_3D, gipi->tex_cache);
 		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
@@ -1879,9 +1879,9 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
 			GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]);
 
 			if (storage->config.async_compilation_enabled) {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 13);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 13);
 			} else {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 11);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 11);
 			}
 			glBindTexture(GL_TEXTURE_3D, gipi2->tex_cache);
 			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform);
@@ -1904,10 +1904,10 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
 
 		if (lightmap && capture) {
 			if (e->instance->lightmap_slice == -1) {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 10);
 				glBindTexture(GL_TEXTURE_2D, lightmap->tex_id);
 			} else {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 11);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 11);
 				glBindTexture(GL_TEXTURE_2D_ARRAY, lightmap->tex_id);
 				state.scene_shader.set_uniform(SceneShaderGLES3::LIGHTMAP_LAYER, e->instance->lightmap_slice);
 			}
@@ -1952,13 +1952,13 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 
 		if (p_sky != nullptr) {
 			if (storage->config.use_texture_array_environment) {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
 				glBindTexture(GL_TEXTURE_2D_ARRAY, p_sky->radiance);
 			} else {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 				glBindTexture(GL_TEXTURE_2D, p_sky->radiance);
 			}
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
 			glBindTexture(GL_TEXTURE_2D, p_sky->irradiance);
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, true);
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, storage->config.use_texture_array_environment);
@@ -2162,7 +2162,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 			}
 
 			if (skeleton) {
-				glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
 				glBindTexture(GL_TEXTURE_2D, skeleton->texture);
 			}
 		}
@@ -2448,7 +2448,7 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
 	RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_sky->panorama);
 
 	ERR_FAIL_COND(!tex);
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 	tex = tex->get_ptr(); //resolve for proxies
 
@@ -2658,7 +2658,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
 		state.ubo_data.shadow_directional_pixel_size[0] = 1.0 / directional_shadow.size;
 		state.ubo_data.shadow_directional_pixel_size[1] = 1.0 / directional_shadow.size;
 
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
 		glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
@@ -3109,7 +3109,7 @@ void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
 	glDepthFunc(GL_LEQUAL);
 	glColorMask(1, 1, 1, 1);
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, p_texture);
 
 	glViewport(0, 0, storage->frame.current_rt->width * 0.5, storage->frame.current_rt->height * 0.5);
@@ -3220,7 +3220,7 @@ void RasterizerSceneGLES3::_blur_effect_buffer() {
 		state.effect_blur_shader.bind();
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo);
 		_copy_screen(true);
@@ -3231,7 +3231,7 @@ void RasterizerSceneGLES3::_blur_effect_buffer() {
 		state.effect_blur_shader.bind();
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger
 		_copy_screen(true);
@@ -3256,7 +3256,7 @@ void RasterizerSceneGLES3::_bind_depth_texture() {
 	if (!state.bound_depth_texture) {
 		ERR_FAIL_COND(!state.prepared_depth_texture);
 		//bind depth for read
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 9);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 		state.bound_depth_texture = true;
 	}
@@ -3304,7 +3304,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 			ss[0] >>= 1;
 			ss[1] >>= 1;
 
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			if (i == 0) {
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 			} else {
@@ -3357,11 +3357,11 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		state.ssao_shader.set_uniform(SsaoShaderGLES3::PROJ_SCALE, pixels_per_meter);
 		state.ssao_shader.set_uniform(SsaoShaderGLES3::BIAS, env->ssao_bias);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.linear_depth);
-		glActiveTexture(GL_TEXTURE2);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
 
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first
@@ -3385,11 +3385,11 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 				glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS), 1, axis);
 				glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::SCREEN_SIZE), 1, ss);
 
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[i]);
-				glActiveTexture(GL_TEXTURE1);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
-				glActiveTexture(GL_TEXTURE2);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
 				glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[1 - i]);
 				if (i == 0) {
@@ -3407,9 +3407,9 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE, true);
 		state.effect_blur_shader.bind();
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR, env->ssao_color);
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); //previous level, since mipmaps[0] starts one level bigger
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
 		_copy_screen(true);
@@ -3452,15 +3452,15 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 		state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(1, 0));
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //disable filter (fixes bugs on AMD)
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]);
-		glActiveTexture(GL_TEXTURE2);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
 
@@ -3468,7 +3468,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 
 		_copy_screen(true);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 		state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(0, 1));
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
@@ -3507,11 +3507,11 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE, env->ssr_fade_out);
 		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CURVE_FADE_IN, env->ssr_fade_in);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
-		glActiveTexture(GL_TEXTURE2);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
 
@@ -3537,10 +3537,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 	state.resolve_shader.bind();
 	state.resolve_shader.set_uniform(ResolveShaderGLES3::PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 	if (env->ssr_enabled) {
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
 	}
 
@@ -3570,7 +3570,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 	}
 
 	glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 
 	_copy_screen(true);
@@ -3610,7 +3610,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		} else {
 			glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 		}
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]);
@@ -3661,10 +3661,10 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, composite_from);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -3675,7 +3675,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 
 		_copy_screen(true);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(0, 1));
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
@@ -3718,10 +3718,10 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, composite_from);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -3744,7 +3744,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
 		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
@@ -3756,7 +3756,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 			glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
 
 		} else {
-			glActiveTexture(GL_TEXTURE2);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse);
 		}
 
@@ -3779,7 +3779,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 
 	if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) {
 		//these needed to disable filtering, reenamble
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
@@ -3803,7 +3803,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 
 		glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE), 1, ss);
 		glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE), 1, ds);
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, composite_from);
 
 		glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[0].fbo);
@@ -3819,7 +3819,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		int s_size = exposure_shrink_size / 3;
 		for (int i = 1; i < exposure_shrink.size() - 1; i++) {
 			glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[i].fbo);
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			glBindTexture(GL_TEXTURE_2D, exposure_shrink[i - 1].color);
 
 			_copy_screen();
@@ -3843,9 +3843,9 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 
 		glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[exposure_shrink.size() - 1].fbo);
 		glViewport(0, 0, 1, 1);
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, exposure_shrink[exposure_shrink.size() - 2].color);
-		glActiveTexture(GL_TEXTURE1);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color); //read from previous
 
 		state.exposure_shader.set_uniform(ExposureShaderGLES3::EXPOSURE_ADJUST, env->auto_exposure_speed * (tick_diff / 1000000.0));
@@ -3904,7 +3904,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength);
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LUMINANCE_CAP, env->glow_hdr_luminance_cap);
 
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			if (i == 0) {
 				glBindTexture(GL_TEXTURE_2D, composite_from);
 
@@ -3913,7 +3913,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 					state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey);
 				}
 
-				glActiveTexture(GL_TEXTURE1);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color);
 
 				state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_BLOOM, env->glow_bloom);
@@ -3935,7 +3935,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
 			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength);
-			glActiveTexture(GL_TEXTURE0);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
 			glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger
 			_copy_screen();
@@ -3951,7 +3951,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, composite_from);
 	if (env) {
 		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_FILMIC);
@@ -3997,7 +3997,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN, env->glow_blend_mode == VS::GLOW_BLEND_MODE_SCREEN);
 		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT, env->glow_blend_mode == VS::GLOW_BLEND_MODE_SOFTLIGHT);
 		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE, env->glow_blend_mode == VS::GLOW_BLEND_MODE_REPLACE);
-		glActiveTexture(GL_TEXTURE2);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 	}
 
@@ -4006,7 +4006,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(env->color_correction);
 		if (tex) {
 			state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, true);
-			glActiveTexture(GL_TEXTURE3);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE3);
 			glBindTexture(tex->target, tex->tex_id);
 		}
 	}
@@ -4029,7 +4029,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		}
 
 		if (env->auto_exposure) {
-			glActiveTexture(GL_TEXTURE1);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1);
 			glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color);
 			state.tonemap_shader.set_uniform(TonemapShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey);
 		}
@@ -4115,7 +4115,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_SHADOW, use_shadows);
 
 	if (use_shadows) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
 		glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
@@ -4124,14 +4124,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 	} else {
 		if (storage->config.async_compilation_enabled) {
 			// Avoid GL UB message id 131222 caused by shadow samplers not properly set up in the ubershader
-			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+			WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
 			glBindTexture(GL_TEXTURE_2D, storage->resources.depth_tex);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
 		}
 	}
 
 	if (reflection_atlas && reflection_atlas->size) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
 		glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
 	}
 
@@ -4385,7 +4385,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 				glDisable(GL_DEPTH_TEST);
 				glDisable(GL_CULL_FACE);
 
-				glActiveTexture(GL_TEXTURE0);
+				WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 				glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
 
 				storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
@@ -4560,7 +4560,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 	}
 
 	if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) {
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 	}
 
@@ -4632,7 +4632,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 		//_copy_texture_to_front_buffer(shadow_atlas->depth);
 		storage->canvas->canvas_begin();
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
 		storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
@@ -4642,7 +4642,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 		//_copy_texture_to_front_buffer(shadow_atlas->depth);
 		storage->canvas->canvas_begin();
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color);
 		//glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color);
 		storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1));
@@ -4652,7 +4652,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 		//_copy_texture_to_front_buffer(shadow_atlas->depth);
 		storage->canvas->canvas_begin();
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
 		storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
 	}
@@ -4661,7 +4661,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 		//_copy_texture_to_front_buffer(shadow_atlas->depth);
 		storage->canvas->canvas_begin();
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
 		storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
@@ -4671,7 +4671,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 		//_copy_texture_to_front_buffer(shadow_atlas->depth);
 		storage->canvas->canvas_begin();
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, env_radiance_tex);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -4885,7 +4885,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 
 	if (storage->config.async_compilation_enabled) {
 		// Avoid GL UB message id 131222 caused by shadow samplers not properly set up in the ubershader
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.depth_tex);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
 	}
@@ -4910,7 +4910,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 		glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
 		state.cube_to_dp_shader.bind();
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_CUBE_MAP, shadow_cubemaps[current_cubemap].cubemap);
 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_NONE);
 		glDisable(GL_CULL_FACE);
@@ -5102,7 +5102,7 @@ void RasterizerSceneGLES3::initialize() {
 
 	int cube_size = max_shadow_cubemap_sampler_size;
 
-	glActiveTexture(GL_TEXTURE0);
+	WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 	while (cube_size >= 32) {
 		ShadowCubeMap cube;
@@ -5193,7 +5193,7 @@ void RasterizerSceneGLES3::initialize() {
 
 		int rcube_size = max_reflection_cubemap_sampler_size;
 
-		glActiveTexture(GL_TEXTURE0);
+		WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
 
 		bool use_float = true;
 

+ 51 - 36
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -138,6 +138,20 @@ void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat,
 
 GLuint RasterizerStorageGLES3::system_fbo = 0;
 
+void RasterizerStorageGLES3::GLWrapper::initialize(int p_max_texture_image_units) {
+	texture_unit_table.create(p_max_texture_image_units);
+}
+
+void RasterizerStorageGLES3::GLWrapper::reset() {
+	for (uint32_t i = 0; i < texture_units_bound.size(); i++) {
+		::glActiveTexture(GL_TEXTURE0 + texture_units_bound[i]);
+		glBindTexture(GL_TEXTURE_2D, 0);
+	}
+
+	texture_units_bound.clear();
+	texture_unit_table.blank();
+}
+
 Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const {
 	r_compressed = false;
 	r_gl_format = 0;
@@ -655,7 +669,7 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
 		texture->mipmaps = 1;
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	if (p_type == VS::TEXTURE_TYPE_EXTERNAL) {
@@ -759,7 +773,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 	PoolVector<uint8_t>::Read read = img->get_data().read();
 	ERR_FAIL_COND(!read.ptr());
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	texture->ignore_mipmaps = compressed && !img->has_mipmaps();
@@ -970,7 +984,7 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
 
 	PoolVector<uint8_t>::Read read = img->get_data().read();
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	int src_data_size = img->get_data().size();
@@ -1067,7 +1081,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
 			glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo);
 
 			// back color attachment with memory, then set properties
-			glActiveTexture(GL_TEXTURE0);
+			gl_wrapper.gl_active_texture(GL_TEXTURE0);
 			glBindTexture(GL_TEXTURE_2D, tmp_color_attachment);
 			// TODO support HDR properly
 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
@@ -1087,7 +1101,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
 			glColorMask(1, 1, 1, 1);
 
 			// use volume tex for reading
-			glActiveTexture(GL_TEXTURE0);
+			gl_wrapper.gl_active_texture(GL_TEXTURE0);
 			glBindTexture(texture->target, texture->tex_id);
 
 			glViewport(0, 0, texture->alloc_width, texture->alloc_height);
@@ -1161,7 +1175,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
 	data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
 	PoolVector<uint8_t>::Write wb = data.write();
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 	glBindTexture(texture->target, texture->tex_id);
 
@@ -1248,7 +1262,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
 	glDisable(GL_BLEND);
 	glDepthFunc(GL_LEQUAL);
 	glColorMask(1, 1, 1, 1);
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, texture->tex_id);
 
 	glViewport(0, 0, texture->alloc_width, texture->alloc_height);
@@ -1296,7 +1310,7 @@ void RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags)
 
 	texture->flags = p_flags;
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) {
@@ -1390,7 +1404,7 @@ void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no)
 
 	ERR_FAIL_COND(!texture);
 
-	glActiveTexture(GL_TEXTURE0 + p_texture_no);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0 + p_texture_no);
 	glBindTexture(texture->target, texture->tex_id);
 }
 uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const {
@@ -1511,7 +1525,7 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_
 	glDisable(GL_SCISSOR_TEST);
 	glDisable(GL_BLEND);
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
 	if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) {
@@ -1525,7 +1539,7 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_
 #endif
 	}
 
-	glActiveTexture(GL_TEXTURE1);
+	gl_wrapper.gl_active_texture(GL_TEXTURE1);
 	GLuint new_cubemap;
 	glGenTextures(1, &new_cubemap);
 	glBindTexture(GL_TEXTURE_CUBE_MAP, new_cubemap);
@@ -1709,7 +1723,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 	glDisable(GL_SCISSOR_TEST);
 	glDisable(GL_BLEND);
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 	glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
 #ifdef GLES_OVER_GL
@@ -1741,7 +1755,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 
 	{
 		//Irradiance map
-		glActiveTexture(GL_TEXTURE1);
+		gl_wrapper.gl_active_texture(GL_TEXTURE1);
 		glGenTextures(1, &sky->irradiance);
 		glBindTexture(GL_TEXTURE_2D, sky->irradiance);
 
@@ -1811,7 +1825,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 			glBindVertexArray(0);
 		}
 		glGenerateMipmap(GL_TEXTURE_2D);
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, tmp_tex);
 		glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
 
@@ -1831,7 +1845,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 		shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, false);
 
 		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(texture->target, texture->tex_id);
 		glDeleteFramebuffers(1, &tmp_fb);
 		glDeleteFramebuffers(1, &tmp_fb2);
@@ -1840,7 +1854,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 
 	// Now compute radiance
 
-	glActiveTexture(GL_TEXTURE1);
+	gl_wrapper.gl_active_texture(GL_TEXTURE1);
 	glGenTextures(1, &sky->radiance);
 
 	if (config.use_texture_array_environment) {
@@ -1898,7 +1912,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false);
 				shaders.cubemap_filter.bind();
-				glActiveTexture(GL_TEXTURE0);
+				gl_wrapper.gl_active_texture(GL_TEXTURE0);
 				glBindTexture(texture->target, texture->tex_id);
 				shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4));
 			} else {
@@ -1906,7 +1920,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, true);
 				shaders.cubemap_filter.bind();
-				glActiveTexture(GL_TEXTURE0);
+				gl_wrapper.gl_active_texture(GL_TEXTURE0);
 				glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
 				shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_ARRAY_INDEX, j - 1); //read from previous to ensure better blur
 			}
@@ -1936,7 +1950,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 		shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false);
 
 		//restore ranges
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
 
 		glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
@@ -2029,7 +2043,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, false);
 				shaders.cubemap_filter.bind();
-				glActiveTexture(GL_TEXTURE0);
+				gl_wrapper.gl_active_texture(GL_TEXTURE0);
 				glBindTexture(texture->target, texture->tex_id);
 				shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4));
 			} else {
@@ -2037,7 +2051,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
 				shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, true);
 				shaders.cubemap_filter.bind();
-				glActiveTexture(GL_TEXTURE0);
+				gl_wrapper.gl_active_texture(GL_TEXTURE0);
 				glBindTexture(GL_TEXTURE_2D, sky->radiance);
 				shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, float(lod - 1)); //read from previous to ensure better blur
 			}
@@ -5195,7 +5209,7 @@ void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton, int p_bones, bool
 		height++;
 	}
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, skeleton->texture);
 
 	if (skeleton->use_2d) {
@@ -5388,7 +5402,7 @@ void RasterizerStorageGLES3::update_dirty_skeletons() {
 	}
 
 	// TODO : Is this update necessary for 2D software skinning?
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 	while (skeleton_update_list.first()) {
 		Skeleton *skeleton = skeleton_update_list.first()->self();
@@ -6033,7 +6047,7 @@ RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width, int p_heig
 	gipd->depth = p_depth;
 	gipd->compression = GI_PROBE_UNCOMPRESSED;
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glGenTextures(1, &gipd->tex_id);
 	glBindTexture(GL_TEXTURE_3D, gipd->tex_id);
 
@@ -6090,7 +6104,7 @@ void RasterizerStorageGLES3::gi_probe_dynamic_data_update(RID p_gi_probe_data, i
 		}
 	}
 */
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_3D, gipd->tex_id);
 	glTexSubImage3D(GL_TEXTURE_3D, p_mipmap, 0, 0, p_depth_slice, gipd->width >> p_mipmap, gipd->height >> p_mipmap, p_slice_count, GL_RGBA, GL_UNSIGNED_BYTE, p_data);
 	//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
@@ -6649,7 +6663,7 @@ void RasterizerStorageGLES3::update_particles() {
 			ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = material->shader->texture_hints.ptrw();
 
 			for (int i = 0; i < tc; i++) {
-				glActiveTexture(GL_TEXTURE0 + i);
+				gl_wrapper.gl_active_texture(GL_TEXTURE0 + i);
 
 				GLenum target;
 				GLuint tex;
@@ -7022,7 +7036,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
 	{
 		/* FRONT FBO */
 
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 		glGenFramebuffers(1, &rt->fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
@@ -7590,7 +7604,7 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
 	cls->size = p_width;
 	cls->height = 16;
 
-	glActiveTexture(GL_TEXTURE0);
+	gl_wrapper.gl_active_texture(GL_TEXTURE0);
 
 	glGenFramebuffers(1, &cls->fbo);
 	glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
@@ -8290,7 +8304,7 @@ void RasterizerStorageGLES3::initialize() {
 		for (int i = 0; i < 8 * 8 * 3; i++) {
 			whitetexdata[i] = 255;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.white_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -8302,7 +8316,7 @@ void RasterizerStorageGLES3::initialize() {
 		for (int i = 0; i < 8 * 8 * 3; i++) {
 			blacktexdata[i] = 0;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.black_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, blacktexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -8314,7 +8328,7 @@ void RasterizerStorageGLES3::initialize() {
 		for (int i = 0; i < 8 * 8 * 4; i++) {
 			transparenttexdata[i] = 0;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.transparent_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, transparenttexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -8328,7 +8342,7 @@ void RasterizerStorageGLES3::initialize() {
 			normaltexdata[i + 1] = 128;
 			normaltexdata[i + 2] = 255;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.normal_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, normaltexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -8342,7 +8356,7 @@ void RasterizerStorageGLES3::initialize() {
 			anisotexdata[i + 1] = 128;
 			anisotexdata[i + 2] = 0;
 		}
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.aniso_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
@@ -8351,14 +8365,14 @@ void RasterizerStorageGLES3::initialize() {
 		glGenTextures(1, &resources.depth_tex);
 		unsigned char depthtexdata[8 * 8 * 2] = {};
 
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, resources.depth_tex);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 8, 8, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthtexdata);
 		glBindTexture(GL_TEXTURE_2D, 0);
 
 		// Opaque white color for 3D texture.
 		glGenTextures(1, &resources.white_tex_3d);
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(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);
 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
@@ -8366,7 +8380,7 @@ void RasterizerStorageGLES3::initialize() {
 
 		// Opaque white color for texture array.
 		glGenTextures(1, &resources.white_tex_array);
-		glActiveTexture(GL_TEXTURE0);
+		gl_wrapper.gl_active_texture(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, nullptr);
 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
@@ -8375,6 +8389,7 @@ void RasterizerStorageGLES3::initialize() {
 	}
 
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
+	gl_wrapper.initialize(config.max_texture_image_units);
 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
 	glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &config.max_cubemap_texture_size);
 

+ 24 - 1
drivers/gles3/rasterizer_storage_gles3.h

@@ -31,6 +31,7 @@
 #ifndef RASTERIZER_STORAGE_GLES3_H
 #define RASTERIZER_STORAGE_GLES3_H
 
+#include "core/bitfield_dynamic.h"
 #include "core/self_list.h"
 #include "drivers/gles_common/rasterizer_asserts.h"
 #include "servers/visual/rasterizer.h"
@@ -56,6 +57,8 @@ class RasterizerSceneGLES3;
 
 void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type);
 
+#define WRAPPED_GL_ACTIVE_TEXTURE storage->gl_wrapper.gl_active_texture
+
 class RasterizerStorageGLES3 : public RasterizerStorage {
 public:
 	RasterizerCanvasGLES3 *canvas;
@@ -1501,9 +1504,29 @@ public:
 		float time[4];
 		float delta;
 		uint64_t count;
-
 	} frame;
 
+	struct GLWrapper {
+		mutable BitFieldDynamic texture_unit_table;
+		mutable LocalVector<uint32_t> texture_units_bound;
+
+		void gl_active_texture(GLenum p_texture) const {
+			::glActiveTexture(p_texture);
+
+			p_texture -= GL_TEXTURE0;
+
+			// Check for below zero and above max in one check.
+			ERR_FAIL_COND((unsigned int)p_texture >= texture_unit_table.get_num_bits());
+
+			// Set if the first occurrence in the table.
+			if (texture_unit_table.check_and_set(p_texture)) {
+				texture_units_bound.push_back(p_texture);
+			}
+		}
+		void initialize(int p_max_texture_image_units);
+		void reset();
+	} gl_wrapper;
+
 	void initialize();
 	void finalize();