Browse Source

Fix shadow flickering with async shader compilation

This mostly reverts the approach in #62628, which now the problem is better scoped, looks overengineered and instead focuses on the few cases where there's something to take care of.

(cherry picked from commit a2ed82d3b20d931f872e2edc7ddd672544ed7947)
Pedro J. Estébanez 3 years ago
parent
commit
f3adb06938

+ 15 - 1
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -4111,6 +4111,13 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
 		state.ubo_data.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size;
 		state.ubo_data.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size;
 		state.ubo_data.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size;
 		state.ubo_data.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size;
+	} 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);
+			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) {
 	if (reflection_atlas && reflection_atlas->size) {
@@ -4866,6 +4873,13 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 	state.ubo_data.shadow_dual_paraboloid_render_zfar = zfar;
 	state.ubo_data.shadow_dual_paraboloid_render_zfar = zfar;
 	state.ubo_data.opaque_prepass_threshold = 0.1;
 	state.ubo_data.opaque_prepass_threshold = 0.1;
 
 
+	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);
+		glBindTexture(GL_TEXTURE_2D, storage->resources.depth_tex);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+	}
+
 	_setup_environment(nullptr, light_projection, light_transform);
 	_setup_environment(nullptr, light_projection, light_transform);
 
 
 	state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true);
 	state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true);
@@ -5297,7 +5311,7 @@ void RasterizerSceneGLES3::initialize() {
 	glFrontFace(GL_CW);
 	glFrontFace(GL_CW);
 
 
 	if (storage->config.async_compilation_enabled) {
 	if (storage->config.async_compilation_enabled) {
-		state.scene_shader.init_async_compilation(storage->resources.depth_tex);
+		state.scene_shader.init_async_compilation();
 	}
 	}
 }
 }
 
 

+ 1 - 1
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -8354,7 +8354,7 @@ void RasterizerStorageGLES3::initialize() {
 	shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
 	shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
 	shaders.particles.init();
 	shaders.particles.init();
 	if (config.async_compilation_enabled) {
 	if (config.async_compilation_enabled) {
-		shaders.particles.init_async_compilation(resources.depth_tex);
+		shaders.particles.init_async_compilation();
 	}
 	}
 
 
 #ifdef GLES_OVER_GL
 #ifdef GLES_OVER_GL

+ 11 - 30
drivers/gles3/shader_gles3.cpp

@@ -177,45 +177,29 @@ bool ShaderGLES3::is_custom_code_ready_for_render(uint32_t p_code_id) {
 	return true;
 	return true;
 }
 }
 
 
-bool ShaderGLES3::_bind_ubershader() {
+bool ShaderGLES3::_bind_ubershader(bool p_for_warmup) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	ERR_FAIL_COND_V(!is_async_compilation_supported(), false);
 	ERR_FAIL_COND_V(!is_async_compilation_supported(), false);
 	ERR_FAIL_COND_V(get_ubershader_flags_uniform() == -1, false);
 	ERR_FAIL_COND_V(get_ubershader_flags_uniform() == -1, false);
 #endif
 #endif
 	new_conditional_version.version |= VersionKey::UBERSHADER_FLAG;
 	new_conditional_version.version |= VersionKey::UBERSHADER_FLAG;
 	bool bound = _bind(true);
 	bool bound = _bind(true);
+	new_conditional_version.version &= ~VersionKey::UBERSHADER_FLAG;
+	if (p_for_warmup) {
+		// Avoid GL UB message id 131222 caused by shadow samplers not properly set up yet
+		unbind();
+		return bound;
+	}
 	int conditionals_uniform = _get_uniform(get_ubershader_flags_uniform());
 	int conditionals_uniform = _get_uniform(get_ubershader_flags_uniform());
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	ERR_FAIL_COND_V(conditionals_uniform == -1, false);
 	ERR_FAIL_COND_V(conditionals_uniform == -1, false);
 #endif
 #endif
-	new_conditional_version.version &= ~VersionKey::UBERSHADER_FLAG;
 #ifdef DEV_ENABLED
 #ifdef DEV_ENABLED
 	// So far we don't need bit 31 for conditionals. That allows us to use signed integers,
 	// So far we don't need bit 31 for conditionals. That allows us to use signed integers,
 	// which are more compatible across GL driver vendors.
 	// which are more compatible across GL driver vendors.
 	CRASH_COND(new_conditional_version.version >= 0x80000000);
 	CRASH_COND(new_conditional_version.version >= 0x80000000);
 #endif
 #endif
 	glUniform1i(conditionals_uniform, new_conditional_version.version);
 	glUniform1i(conditionals_uniform, new_conditional_version.version);
-
-	// This is done to avoid running into the GL UB message id 131222. Long explanation:
-	// If an ubershader has shadow samplers, they are generally not used if the current material has shadowing disabled,
-	// but that also implies the rasterizer won't do any preparation to the relevant shadow samplers (which won't really exist,
-	// so that's the correct way in a conditioned shader).
-	// However, in the case of the ubershader those shadow samplers are unconditionally declared, although potentially unused and
-	// thus "uninitialized". Sampling in that situation (compare disabled, no depth texture bound) is undefined behavior for GL.
-	// And that's a problem for us because, even if dynamic branching will serve to avoid using the unprepared sampler when shadowing
-	// is not enabled, the GPU may still run the other branch. And it's not just that the results from the sampling are undefined
-	// (that wouldn't be a problem and we could just ignore the warning); the problem is that sampling in that state is fully UB.
-	for (int i = 0; i < shadow_texunit_count; i++) {
-		int unit = shadow_texunits[i];
-		if (unit >= 0) {
-			glActiveTexture(GL_TEXTURE0 + unit);
-		} else {
-			glActiveTexture(GL_TEXTURE0 + max_image_units + unit);
-		}
-		glBindTexture(GL_TEXTURE_2D, depth_tex);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
-	}
-
 	return bound;
 	return bound;
 }
 }
 
 
@@ -1128,7 +1112,7 @@ GLint ShaderGLES3::get_uniform_location(const String &p_name) const {
 	return glGetUniformLocation(version->ids.main, p_name.ascii().get_data());
 	return glGetUniformLocation(version->ids.main, p_name.ascii().get_data());
 }
 }
 
 
-void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const int *p_shadow_texunits, int p_shadow_texunit_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start) {
+void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start) {
 	ERR_FAIL_COND(version);
 	ERR_FAIL_COND(version);
 	conditional_version.key = 0;
 	conditional_version.key = 0;
 	new_conditional_version.key = 0;
 	new_conditional_version.key = 0;
@@ -1140,8 +1124,6 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co
 	fragment_code = p_fragment_code;
 	fragment_code = p_fragment_code;
 	texunit_pairs = p_texunit_pairs;
 	texunit_pairs = p_texunit_pairs;
 	texunit_pair_count = p_texunit_pair_count;
 	texunit_pair_count = p_texunit_pair_count;
-	shadow_texunits = p_shadow_texunits;
-	shadow_texunit_count = p_shadow_texunit_count;
 	vertex_code_start = p_vertex_code_start;
 	vertex_code_start = p_vertex_code_start;
 	fragment_code_start = p_fragment_code_start;
 	fragment_code_start = p_fragment_code_start;
 	attribute_pairs = p_attribute_pairs;
 	attribute_pairs = p_attribute_pairs;
@@ -1232,12 +1214,11 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
 }
 }
 
 
-void ShaderGLES3::init_async_compilation(GLuint p_depth_tex) {
-	depth_tex = p_depth_tex;
+void ShaderGLES3::init_async_compilation() {
 	if (is_async_compilation_supported() && get_ubershader_flags_uniform() != -1) {
 	if (is_async_compilation_supported() && get_ubershader_flags_uniform() != -1) {
 		// Warm up the ubershader for the case of no custom code
 		// Warm up the ubershader for the case of no custom code
 		new_conditional_version.code_version = 0;
 		new_conditional_version.code_version = 0;
-		_bind_ubershader();
+		_bind_ubershader(true);
 	}
 	}
 }
 }
 
 
@@ -1297,7 +1278,7 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String &p_ver
 	if (p_async_mode == ASYNC_MODE_VISIBLE && is_async_compilation_supported() && get_ubershader_flags_uniform() != -1) {
 	if (p_async_mode == ASYNC_MODE_VISIBLE && is_async_compilation_supported() && get_ubershader_flags_uniform() != -1) {
 		// Warm up the ubershader for this custom code
 		// Warm up the ubershader for this custom code
 		new_conditional_version.code_version = p_code_id;
 		new_conditional_version.code_version = p_code_id;
-		_bind_ubershader();
+		_bind_ubershader(true);
 	}
 	}
 }
 }
 
 

+ 3 - 6
drivers/gles3/shader_gles3.h

@@ -96,7 +96,6 @@ private:
 	//@TODO Optimize to a fixed set of shader pools and use a LRU
 	//@TODO Optimize to a fixed set of shader pools and use a LRU
 	int uniform_count;
 	int uniform_count;
 	int texunit_pair_count;
 	int texunit_pair_count;
-	int shadow_texunit_count;
 	int conditional_count;
 	int conditional_count;
 	int ubo_count;
 	int ubo_count;
 	int feedback_count;
 	int feedback_count;
@@ -246,7 +245,6 @@ private:
 	const char **uniform_names;
 	const char **uniform_names;
 	const AttributePair *attribute_pairs;
 	const AttributePair *attribute_pairs;
 	const TexUnitPair *texunit_pairs;
 	const TexUnitPair *texunit_pairs;
-	const int *shadow_texunits;
 	const UBOPair *ubo_pairs;
 	const UBOPair *ubo_pairs;
 	const Feedback *feedbacks;
 	const Feedback *feedbacks;
 	const char *vertex_code;
 	const char *vertex_code;
@@ -280,7 +278,6 @@ private:
 	static ShaderGLES3 *active;
 	static ShaderGLES3 *active;
 
 
 	int max_image_units;
 	int max_image_units;
-	GLuint depth_tex = 0;
 
 
 	_FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) {
 	_FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) {
 		if (p_uniform < 0) {
 		if (p_uniform < 0) {
@@ -372,13 +369,13 @@ private:
 	}
 	}
 
 
 	bool _bind(bool p_binding_fallback);
 	bool _bind(bool p_binding_fallback);
-	bool _bind_ubershader();
+	bool _bind_ubershader(bool p_for_warmrup = false);
 
 
 protected:
 protected:
 	_FORCE_INLINE_ int _get_uniform(int p_which) const;
 	_FORCE_INLINE_ int _get_uniform(int p_which) const;
 	_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
 	_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
 
 
-	void setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const int *p_shadow_texunits, int p_shadow_texunit_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start);
+	void setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start);
 
 
 	ShaderGLES3();
 	ShaderGLES3();
 
 
@@ -407,7 +404,7 @@ public:
 	_FORCE_INLINE_ bool is_version_valid() const { return version && version->compile_status == Version::COMPILE_STATUS_OK; }
 	_FORCE_INLINE_ bool is_version_valid() const { return version && version->compile_status == Version::COMPILE_STATUS_OK; }
 
 
 	virtual void init() = 0;
 	virtual void init() = 0;
-	void init_async_compilation(GLuint p_depth_tex);
+	void init_async_compilation();
 	bool is_async_compilation_supported();
 	bool is_async_compilation_supported();
 	void finish();
 	void finish();
 
 

+ 0 - 16
gles_builders.py

@@ -19,7 +19,6 @@ class LegacyGLHeaderStruct:
         self.enums = {}
         self.enums = {}
         self.texunits = []
         self.texunits = []
         self.texunit_names = []
         self.texunit_names = []
-        self.shadow_texunits = []
         self.ubos = []
         self.ubos = []
         self.ubo_names = []
         self.ubo_names = []
 
 
@@ -107,8 +106,6 @@ def include_file_in_legacygl_header(filename, header_data, depth):
 
 
                 if not x in header_data.texunit_names:
                 if not x in header_data.texunit_names:
                     header_data.texunits += [(x, texunit)]
                     header_data.texunits += [(x, texunit)]
-                    if line.find("sampler2DShadow") != -1:
-                        header_data.shadow_texunits += [texunit]
                     header_data.texunit_names += [x]
                     header_data.texunit_names += [x]
 
 
         elif line.find("uniform") != -1 and line.lower().find("ubo:") != -1:
         elif line.find("uniform") != -1 and line.lower().find("ubo:") != -1:
@@ -486,15 +483,6 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
     else:
     else:
         fd.write("\t\tstatic TexUnitPair *_texunit_pairs=NULL;\n")
         fd.write("\t\tstatic TexUnitPair *_texunit_pairs=NULL;\n")
 
 
-    if not gles2:
-        if header_data.shadow_texunits:
-            fd.write("\t\tstatic int _shadow_texunits[]={")
-            for x in header_data.shadow_texunits:
-                fd.write(str(x) + ',')
-            fd.write("};\n\n")
-        else:
-            fd.write("\t\tstatic int *_shadow_texunits=NULL;\n")
-
     if not gles2 and header_data.ubos:
     if not gles2 and header_data.ubos:
         fd.write("\t\tstatic UBOPair _ubo_pairs[]={\n")
         fd.write("\t\tstatic UBOPair _ubo_pairs[]={\n")
         for x in header_data.ubos:
         for x in header_data.ubos:
@@ -549,8 +537,6 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
                 + str(len(header_data.attributes))
                 + str(len(header_data.attributes))
                 + ", _texunit_pairs,"
                 + ", _texunit_pairs,"
                 + str(len(header_data.texunits))
                 + str(len(header_data.texunits))
-                + ", _shadow_texunits,"
-                + str(len(header_data.shadow_texunits))
                 + ",_ubo_pairs,"
                 + ",_ubo_pairs,"
                 + str(len(header_data.ubos))
                 + str(len(header_data.ubos))
                 + ",_feedbacks,"
                 + ",_feedbacks,"
@@ -580,8 +566,6 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
                 + str(len(header_data.uniforms))
                 + str(len(header_data.uniforms))
                 + ",_texunit_pairs,"
                 + ",_texunit_pairs,"
                 + str(len(header_data.texunits))
                 + str(len(header_data.texunits))
-                + ",_shadow_texunits,"
-                + str(len(header_data.shadow_texunits))
                 + ",_enums,"
                 + ",_enums,"
                 + str(len(header_data.enums))
                 + str(len(header_data.enums))
                 + ",_enum_values,"
                 + ",_enum_values,"