diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 2d44b60cbb..91c34e2e14 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1306,6 +1306,10 @@ To reduce loading times after the project has been launched at least once, you can use [code]Asynchronous + Cache[/code]. This also causes the ubershaders to be cached into storage so they can be ready faster next time they are used (provided the platform provides support for it). [b]Note:[/b] Asynchronous compilation is currently only supported for spatial (3D) and particle materials/shaders. CanvasItem (2D) shaders will not use asynchronous compilation even if this setting is set to [code]Asynchronous[/code] or [code]Asynchronous + Cache[/code]. + + An override for [code]rendering/gles3/shaders/shader_compilation_mode[/code], so asynchronous compilation can be disabled for mobile. + You may want to do that since mobile GPUs generally won't support ubershaders due to their complexity. + Max buffer size for blend shapes. Any blend shape bigger than this will not work. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 3fb2b0674d..cbaaa44070 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1846,7 +1846,14 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform GIProbeInstance *gipi = gi_probe_instance_owner.getptr(ridp[0]); float bias_scale = e->instance->baked_light ? 1 : 0; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10); + // Normally, lightmapping uses the same texturing units than the GI probes; however, in the case of the ubershader + // that's not a good idea because some hardware/drivers (Android/Intel) may fail to render if a single texturing unit + // is used through multiple kinds of samplers in the same shader. + if (state.scene_shader.is_version_ubershader()) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 12); + } else { + glActiveTexture(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); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds); @@ -1858,7 +1865,11 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform if (gi_probe_count > 1) { GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 11); + if (state.scene_shader.is_version_ubershader()) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 13); + } else { + glActiveTexture(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); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index c500a778d2..32c52bf8e2 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -123,7 +123,7 @@ bool ShaderGLES3::_bind(bool p_binding_fallback) { #ifdef DEBUG_ENABLED if (ready) { - if (VS::get_singleton()->is_force_shader_fallbacks_enabled() && !must_be_ready_now) { + if (VS::get_singleton()->is_force_shader_fallbacks_enabled() && !must_be_ready_now && get_ubershader_flags_uniform() != -1) { ready = false; } } @@ -160,7 +160,7 @@ bool ShaderGLES3::_bind_ubershader() { ERR_FAIL_COND_V(conditionals_uniform == -1, false); #endif new_conditional_version.version &= ~VersionKey::UBERSHADER_FLAG; - glUniform1i(conditionals_uniform, new_conditional_version.version); + glUniform1ui(conditionals_uniform, new_conditional_version.version); return bound; } @@ -454,11 +454,11 @@ static CharString _prepare_ubershader_chunk(const CharString &p_chunk) { } else if (l.begins_with("#ifdef")) { Vector pieces = l.split_spaces(); CRASH_COND(pieces.size() != 2); - s += "if ((ubershader_flags & FLAG_" + pieces[1] + ") != 0) {\n"; + s += "if ((ubershader_flags & FLAG_" + pieces[1] + ") != 0u) {\n"; } else if (l.begins_with("#ifndef")) { Vector pieces = l.split_spaces(); CRASH_COND(pieces.size() != 2); - s += "if ((ubershader_flags & FLAG_" + pieces[1] + ") == 0) {\n"; + s += "if ((ubershader_flags & FLAG_" + pieces[1] + ") == 0u) {\n"; } else { CRASH_NOW_MSG("The shader template is using too complex syntax in a line marked with ubershader-runtime."); } @@ -532,7 +532,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version(bool &r_async_forbidden) if (build_ubershader) { strings_common.push_back("#define IS_UBERSHADER\n"); for (int i = 0; i < conditional_count; i++) { - String s = vformat("#define FLAG_%s (1 << %d)\n", String(conditional_defines[i]).strip_edges().trim_prefix("#define "), i); + String s = vformat("#define FLAG_%s (1u << %du)\n", String(conditional_defines[i]).strip_edges().trim_prefix("#define "), i); CharString cs = s.ascii(); flag_macros.push_back(cs); strings_common.push_back(cs.ptr()); diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 58d6e41d6b..74d47f2adb 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -399,6 +399,7 @@ public: void free_custom_shader(uint32_t p_code_id); uint32_t get_version() const { return new_conditional_version.version; } + bool is_version_ubershader() const { return (new_conditional_version.version & VersionKey::UBERSHADER_FLAG); } _FORCE_INLINE_ bool is_version_valid() const { return version && version->compile_status == Version::COMPILE_STATUS_OK; } virtual void init() = 0; diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index 570e54e56d..8863962ff0 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -2,7 +2,7 @@ [vertex] #if defined(IS_UBERSHADER) -uniform highp int ubershader_flags; +uniform highp uint ubershader_flags; #endif layout(location = 0) in highp vec4 color; @@ -222,7 +222,7 @@ VERTEX_SHADER_CODE [fragment] #if defined(IS_UBERSHADER) -uniform highp int ubershader_flags; +uniform highp uint ubershader_flags; #endif // any code here is never executed, stuff is filled just so it works diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index bf3c16c3c4..df9a4bd4ee 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -2,7 +2,7 @@ [vertex] #if defined(IS_UBERSHADER) -uniform highp int ubershader_flags; +uniform highp uint ubershader_flags; #endif #define M_PI 3.14159265359 @@ -645,7 +645,7 @@ VERTEX_SHADER_CODE [fragment] #if defined(IS_UBERSHADER) -uniform highp int ubershader_flags; +uniform highp uint ubershader_flags; // These are more performant and make the ubershaderification simpler #define VCT_QUALITY_HIGH #define USE_LIGHTMAP_FILTER_BICUBIC @@ -1649,7 +1649,12 @@ uniform mediump vec4[12] lightmap_captures; #ifdef USE_GI_PROBES //ubershader-skip +#if !defined(IS_UBERSHADER) uniform mediump sampler3D gi_probe1; //texunit:-10 +#else +uniform mediump sampler3D gi_probe1_uber; //texunit:-12 +#define gi_probe1 gi_probe1_uber +#endif uniform highp mat4 gi_probe_xform1; uniform highp vec3 gi_probe_bounds1; uniform highp vec3 gi_probe_cell_size1; @@ -1658,7 +1663,12 @@ uniform highp float gi_probe_bias1; uniform highp float gi_probe_normal_bias1; uniform bool gi_probe_blend_ambient1; +#if !defined(IS_UBERSHADER) uniform mediump sampler3D gi_probe2; //texunit:-11 +#else +uniform mediump sampler3D gi_probe2_uber; //texunit:-13 +#define gi_probe2 gi_probe2_uber +#endif uniform highp mat4 gi_probe_xform2; uniform highp vec3 gi_probe_bounds2; uniform highp vec3 gi_probe_cell_size2; diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 22eb92374f..ccbd27d879 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2733,6 +2733,7 @@ VisualServer::VisualServer() { #endif GLOBAL_DEF("rendering/gles3/shaders/shader_compilation_mode", 0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/gles3/shaders/shader_compilation_mode", PropertyInfo(Variant::INT, "rendering/gles3/shaders/shader_compilation_mode", PROPERTY_HINT_ENUM, "Synchronous,Asynchronous,Asynchronous + Cache")); + GLOBAL_DEF("rendering/gles3/shaders/shader_compilation_mode.mobile", 0); GLOBAL_DEF("rendering/gles3/shaders/max_simultaneous_compiles", 2); ProjectSettings::get_singleton()->set_custom_property_info("rendering/gles3/shaders/max_simultaneous_compiles", PropertyInfo(Variant::INT, "rendering/gles3/shaders/max_simultaneous_compiles", PROPERTY_HINT_RANGE, "1,8,1")); GLOBAL_DEF("rendering/gles3/shaders/max_simultaneous_compiles.mobile", 1);