From 4cbc967f50586e5dd80e8eb8fd519ba1a1c87191 Mon Sep 17 00:00:00 2001
From: clayjohn <claynjohn@gmail.com>
Date: Fri, 12 Jul 2024 15:44:06 -0700
Subject: [PATCH] Use a spec constant to control whether the MultiMesh branch
 is used in the vertex shader.

This works around a bug on the Quest3 and slightly improves performance on all mobile devices at the cost of increased pipeline count.
---
 .../forward_mobile/render_forward_mobile.cpp           |  4 ++++
 .../renderer_rd/forward_mobile/render_forward_mobile.h |  1 +
 .../shaders/forward_mobile/scene_forward_mobile.glsl   | 10 ++++++----
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index af190207db75..c03dd96062fe 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -2058,6 +2058,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
 
 		uint32_t base_spec_constants = p_params->spec_constant_base_flags;
 
+		if (bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH)) {
+			base_spec_constants |= 1 << SPEC_CONSTANT_IS_MULTIMESH;
+		}
+
 		SceneState::PushConstant push_constant;
 		push_constant.base_index = i + p_params->element_offset;
 
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index b0fe5524499c..34260bd701fb 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -81,6 +81,7 @@ class RenderForwardMobile : public RendererSceneRenderRD {
 		SPEC_CONSTANT_DISABLE_DECALS = 13,
 		SPEC_CONSTANT_DISABLE_FOG = 14,
 		SPEC_CONSTANT_USE_DEPTH_FOG = 16,
+		SPEC_CONSTANT_IS_MULTIMESH = 17,
 
 	};
 
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 1637326b48c4..a64b2e10ea08 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -76,6 +76,10 @@ void axis_angle_to_tbn(vec3 axis, float angle, out vec3 tangent, out vec3 binorm
 	normal = omc_axis.zzz * axis + vec3(-s_axis.y, s_axis.x, c);
 }
 
+/* Spec Constants */
+
+layout(constant_id = 17) const bool sc_is_multimesh = false;
+
 /* Varyings */
 
 layout(location = 0) highp out vec3 vertex_interp;
@@ -178,8 +182,6 @@ void main() {
 	color_interp = color_attrib;
 #endif
 
-	bool is_multimesh = bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
-
 	mat4 model_matrix = instances.data[draw_call.instance_index].transform;
 	mat4 inv_view_matrix = scene_data.inv_view_matrix;
 #ifdef USE_DOUBLE_PRECISION
@@ -203,7 +205,7 @@ void main() {
 	mat4 matrix;
 	mat4 read_model_matrix = model_matrix;
 
-	if (is_multimesh) {
+	if (sc_is_multimesh) {
 		//multimesh, instances are for it
 
 #ifdef USE_PARTICLE_TRAILS
@@ -399,7 +401,7 @@ void main() {
 	// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
 	// We add the result to the vertex and ignore the final lost precision.
 	vec3 model_origin = model_matrix[3].xyz;
-	if (is_multimesh) {
+	if (sc_is_multimesh) {
 		vertex = mat3(matrix) * vertex;
 		model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
 	}