Explorar el Código

Merge pull request #74937 from bitsawer/fix_uniform_storage

Fix shader uniform storage conversions and crash
Rémi Verschelde hace 2 años
padre
commit
166643df32

+ 96 - 541
drivers/gles3/storage/material_storage.cpp

@@ -39,32 +39,24 @@
 
 #include "drivers/gles3/rasterizer_canvas_gles3.h"
 #include "drivers/gles3/rasterizer_gles3.h"
+#include "servers/rendering/storage/variant_converters.h"
 
 using namespace GLES3;
 
 ///////////////////////////////////////////////////////////////////////////
 // UBI helper functions
 
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data) {
+static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data) {
 	switch (type) {
 		case ShaderLanguage::TYPE_BOOL: {
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = (r[i] != 0) ? 1 : 0;
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
+				PackedInt32Array ba = value;
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<int32_t>(ba, gui, p_array_size, 4);
 			} else {
 				bool v = value;
 				gui[0] = v ? 1 : 0;
@@ -74,22 +66,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-				int count = 2 * p_array_size;
-
-				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
-					if (i < s) {
-						gui[j] = r[i] ? 1 : 0;
-						gui[j + 1] = r[i + 1] ? 1 : 0;
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
+				PackedInt32Array ba = convert_array_std140<Vector2i, int32_t>(value);
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<Vector2i>(ba, gui, p_array_size, 4);
 			} else {
 				uint32_t v = value;
 				gui[0] = v & 1 ? 1 : 0;
@@ -100,23 +81,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-				int count = 3 * p_array_size;
-
-				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
-					if (i < s) {
-						gui[j] = r[i] ? 1 : 0;
-						gui[j + 1] = r[i + 1] ? 1 : 0;
-						gui[j + 2] = r[i + 2] ? 1 : 0;
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-					}
-					gui[j + 3] = 0; // ignored
+				PackedInt32Array ba = convert_array_std140<Vector3i, int32_t>(value);
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<Vector3i>(ba, gui, p_array_size, 4);
 			} else {
 				uint32_t v = value;
 				gui[0] = (v & 1) ? 1 : 0;
@@ -128,24 +97,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-				int count = 4 * p_array_size;
-
-				for (int i = 0; i < count; i += 4) {
-					if (i < s) {
-						gui[i] = r[i] ? 1 : 0;
-						gui[i + 1] = r[i + 1] ? 1 : 0;
-						gui[i + 2] = r[i + 2] ? 1 : 0;
-						gui[i + 3] = r[i + 3] ? 1 : 0;
-					} else {
-						gui[i] = 0;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-					}
+				PackedInt32Array ba = convert_array_std140<Vector4i, int32_t>(value);
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<Vector4i>(ba, gui, p_array_size, 4);
 			} else {
 				uint32_t v = value;
 				gui[0] = (v & 1) ? 1 : 0;
@@ -158,20 +114,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			int32_t *gui = (int32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				const int *r = iv.ptr();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = value;
+				write_array_std140<int32_t>(iv, gui, p_array_size, 4);
 			} else {
 				int v = value;
 				gui[0] = v;
@@ -179,25 +123,12 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 		} break;
 		case ShaderLanguage::TYPE_IVEC2: {
 			int32_t *gui = (int32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 2 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector2i, int32_t>(value);
+				write_array_std140<Vector2i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector2i v = value;
+				Vector2i v = convert_to_vector<Vector2i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 			}
@@ -206,25 +137,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			int32_t *gui = (int32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 3 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-						gui[j + 2] = r[i + 2];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-					}
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector3i, int32_t>(value);
+				write_array_std140<Vector3i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector3i v = value;
+				Vector3i v = convert_to_vector<Vector3i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -234,26 +150,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			int32_t *gui = (int32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 4 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0; i < count; i += 4) {
-					if (i < s) {
-						gui[i] = r[i];
-						gui[i + 1] = r[i + 1];
-						gui[i + 2] = r[i + 2];
-						gui[i + 3] = r[i + 3];
-					} else {
-						gui[i] = 0;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-					}
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector4i, int32_t>(value);
+				write_array_std140<Vector4i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector4i v = value;
+				Vector4i v = convert_to_vector<Vector4i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -264,20 +164,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				const int *r = iv.ptr();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = value;
+				write_array_std140<uint32_t>(iv, gui, p_array_size, 4);
 			} else {
 				int v = value;
 				gui[0] = v;
@@ -285,25 +173,12 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 		} break;
 		case ShaderLanguage::TYPE_UVEC2: {
 			uint32_t *gui = (uint32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 2 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector2i, int32_t>(value);
+				write_array_std140<Vector2i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector2i v = value;
+				Vector2i v = convert_to_vector<Vector2i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 			}
@@ -312,25 +187,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 3 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-						gui[j + 2] = r[i + 2];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-					}
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector3i, int32_t>(value);
+				write_array_std140<Vector3i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector3i v = value;
+				Vector3i v = convert_to_vector<Vector3i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -340,26 +200,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 4 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0; i < count; i++) {
-					if (i < s) {
-						gui[i] = r[i];
-						gui[i + 1] = r[i + 1];
-						gui[i + 2] = r[i + 2];
-						gui[i + 3] = r[i + 3];
-					} else {
-						gui[i] = 0;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-					}
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector4i, int32_t>(value);
+				write_array_std140<Vector4i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector4i v = value;
+				Vector4i v = convert_to_vector<Vector4i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -371,18 +215,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 
 			if (p_array_size > 0) {
 				const PackedFloat32Array &a = value;
-				int s = a.size();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = a[i];
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				write_array_std140<float>(a, gui, p_array_size, 4);
 			} else {
 				float v = value;
 				gui[0] = v;
@@ -392,22 +225,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			float *gui = (float *)data;
 
 			if (p_array_size > 0) {
-				const PackedVector2Array &a = value;
-				int s = a.size();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = a[i].x;
-						gui[j + 1] = a[i].y;
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedFloat32Array &a = convert_array_std140<Vector2, float>(value);
+				write_array_std140<Vector2>(a, gui, p_array_size, 4);
 			} else {
-				Vector2 v = value;
+				Vector2 v = convert_to_vector<Vector2>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 			}
@@ -416,133 +237,27 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			float *gui = (float *)data;
 
 			if (p_array_size > 0) {
-				if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
-					const PackedColorArray &a = value;
-					int s = a.size();
-
-					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-						if (i < s) {
-							Color color = a[i];
-							gui[j] = color.r;
-							gui[j + 1] = color.g;
-							gui[j + 2] = color.b;
-						} else {
-							gui[j] = 0;
-							gui[j + 1] = 0;
-							gui[j + 2] = 0;
-						}
-						gui[j + 3] = 0; // ignored
-					}
-				} else {
-					const PackedVector3Array &a = value;
-					int s = a.size();
-
-					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-						if (i < s) {
-							gui[j] = a[i].x;
-							gui[j + 1] = a[i].y;
-							gui[j + 2] = a[i].z;
-						} else {
-							gui[j] = 0;
-							gui[j + 1] = 0;
-							gui[j + 2] = 0;
-						}
-						gui[j + 3] = 0; // ignored
-					}
-				}
+				const PackedFloat32Array &a = convert_array_std140<Vector3, float>(value);
+				write_array_std140<Vector3>(a, gui, p_array_size, 4);
 			} else {
-				if (value.get_type() == Variant::COLOR) {
-					Color v = value;
-
-					gui[0] = v.r;
-					gui[1] = v.g;
-					gui[2] = v.b;
-				} else {
-					Vector3 v = value;
-					gui[0] = v.x;
-					gui[1] = v.y;
-					gui[2] = v.z;
-				}
+				Vector3 v = convert_to_vector<Vector3>(value);
+				gui[0] = v.x;
+				gui[1] = v.y;
+				gui[2] = v.z;
 			}
 		} break;
 		case ShaderLanguage::TYPE_VEC4: {
 			float *gui = (float *)data;
 
 			if (p_array_size > 0) {
-				if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
-					const PackedColorArray &a = value;
-					int s = a.size();
-
-					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-						if (i < s) {
-							Color color = a[i];
-							gui[j] = color.r;
-							gui[j + 1] = color.g;
-							gui[j + 2] = color.b;
-							gui[j + 3] = color.a;
-						} else {
-							gui[j] = 0;
-							gui[j + 1] = 0;
-							gui[j + 2] = 0;
-							gui[j + 3] = 0;
-						}
-					}
-				} else {
-					const PackedFloat32Array &a = value;
-					int s = a.size();
-					int count = 4 * p_array_size;
-
-					for (int i = 0; i < count; i += 4) {
-						if (i + 3 < s) {
-							gui[i] = a[i];
-							gui[i + 1] = a[i + 1];
-							gui[i + 2] = a[i + 2];
-							gui[i + 3] = a[i + 3];
-						} else {
-							gui[i] = 0;
-							gui[i + 1] = 0;
-							gui[i + 2] = 0;
-							gui[i + 3] = 0;
-						}
-					}
-				}
+				const PackedFloat32Array &a = convert_array_std140<Vector4, float>(value);
+				write_array_std140<Vector4>(a, gui, p_array_size, 4);
 			} else {
-				if (value.get_type() == Variant::COLOR) {
-					Color v = value;
-
-					gui[0] = v.r;
-					gui[1] = v.g;
-					gui[2] = v.b;
-					gui[3] = v.a;
-				} else if (value.get_type() == Variant::RECT2) {
-					Rect2 v = value;
-
-					gui[0] = v.position.x;
-					gui[1] = v.position.y;
-					gui[2] = v.size.x;
-					gui[3] = v.size.y;
-				} else if (value.get_type() == Variant::QUATERNION) {
-					Quaternion v = value;
-
-					gui[0] = v.x;
-					gui[1] = v.y;
-					gui[2] = v.z;
-					gui[3] = v.w;
-				} else if (value.get_type() == Variant::VECTOR4) {
-					Vector4 v = value;
-
-					gui[0] = v.x;
-					gui[1] = v.y;
-					gui[2] = v.z;
-					gui[3] = v.w;
-				} else {
-					Plane v = value;
-
-					gui[0] = v.normal.x;
-					gui[1] = v.normal.y;
-					gui[2] = v.normal.z;
-					gui[3] = v.d;
-				}
+				Vector4 v = convert_to_vector<Vector4>(value);
+				gui[0] = v.x;
+				gui[1] = v.y;
+				gui[2] = v.z;
+				gui[3] = v.w;
 			}
 		} break;
 		case ShaderLanguage::TYPE_MAT2: {
@@ -590,135 +305,42 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			float *gui = (float *)data;
 
 			if (p_array_size > 0) {
-				const PackedFloat32Array &a = value;
-				int s = a.size();
+				const PackedFloat32Array &a = convert_array_std140<Basis, float>(value);
+				const Basis default_basis;
+				const int s = a.size();
 
 				for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
 					if (i + 8 < s) {
 						gui[j] = a[i];
 						gui[j + 1] = a[i + 1];
 						gui[j + 2] = a[i + 2];
+						gui[j + 3] = 0; // Ignored.
 
 						gui[j + 4] = a[i + 3];
 						gui[j + 5] = a[i + 4];
 						gui[j + 6] = a[i + 5];
+						gui[j + 7] = 0; // Ignored.
 
 						gui[j + 8] = a[i + 6];
 						gui[j + 9] = a[i + 7];
 						gui[j + 10] = a[i + 8];
+						gui[j + 11] = 0; // Ignored.
 					} else {
-						gui[j] = 1;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-
-						gui[j + 4] = 0;
-						gui[j + 5] = 1;
-						gui[j + 6] = 0;
-
-						gui[j + 8] = 0;
-						gui[j + 9] = 0;
-						gui[j + 10] = 1;
+						convert_item_std140(default_basis, gui + j);
 					}
-					gui[j + 3] = 0; // ignored
-					gui[j + 7] = 0; // ignored
-					gui[j + 11] = 0; // ignored
 				}
 			} else {
-				Basis v = value;
-				gui[0] = v.rows[0][0];
-				gui[1] = v.rows[1][0];
-				gui[2] = v.rows[2][0];
-				gui[3] = 0; // ignored
-
-				gui[4] = v.rows[0][1];
-				gui[5] = v.rows[1][1];
-				gui[6] = v.rows[2][1];
-				gui[7] = 0; // ignored
-
-				gui[8] = v.rows[0][2];
-				gui[9] = v.rows[1][2];
-				gui[10] = v.rows[2][2];
-				gui[11] = 0; // ignored
+				convert_item_std140<Basis>(value, gui);
 			}
 		} break;
 		case ShaderLanguage::TYPE_MAT4: {
 			float *gui = (float *)data;
 
 			if (p_array_size > 0) {
-				const PackedFloat32Array &a = value;
-				int s = a.size();
-
-				for (int i = 0; i < p_array_size * 16; i += 16) {
-					if (i + 15 < s) {
-						gui[i] = a[i];
-						gui[i + 1] = a[i + 1];
-						gui[i + 2] = a[i + 2];
-						gui[i + 3] = a[i + 3];
-
-						gui[i + 4] = a[i + 4];
-						gui[i + 5] = a[i + 5];
-						gui[i + 6] = a[i + 6];
-						gui[i + 7] = a[i + 7];
-
-						gui[i + 8] = a[i + 8];
-						gui[i + 9] = a[i + 9];
-						gui[i + 10] = a[i + 10];
-						gui[i + 11] = a[i + 11];
-
-						gui[i + 12] = a[i + 12];
-						gui[i + 13] = a[i + 13];
-						gui[i + 14] = a[i + 14];
-						gui[i + 15] = a[i + 15];
-					} else {
-						gui[i] = 1;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-
-						gui[i + 4] = 0;
-						gui[i + 5] = 1;
-						gui[i + 6] = 0;
-						gui[i + 7] = 0;
-
-						gui[i + 8] = 0;
-						gui[i + 9] = 0;
-						gui[i + 10] = 1;
-						gui[i + 11] = 0;
-
-						gui[i + 12] = 0;
-						gui[i + 13] = 0;
-						gui[i + 14] = 0;
-						gui[i + 15] = 1;
-					}
-				}
-			} else if (value.get_type() == Variant::TRANSFORM3D) {
-				Transform3D v = value;
-				gui[0] = v.basis.rows[0][0];
-				gui[1] = v.basis.rows[1][0];
-				gui[2] = v.basis.rows[2][0];
-				gui[3] = 0;
-
-				gui[4] = v.basis.rows[0][1];
-				gui[5] = v.basis.rows[1][1];
-				gui[6] = v.basis.rows[2][1];
-				gui[7] = 0;
-
-				gui[8] = v.basis.rows[0][2];
-				gui[9] = v.basis.rows[1][2];
-				gui[10] = v.basis.rows[2][2];
-				gui[11] = 0;
-
-				gui[12] = v.origin.x;
-				gui[13] = v.origin.y;
-				gui[14] = v.origin.z;
-				gui[15] = 1;
+				const PackedFloat32Array &a = convert_array_std140<Projection, float>(value);
+				write_array_std140<Projection>(a, gui, p_array_size, 16);
 			} else {
-				Projection v = value;
-				for (int i = 0; i < 4; i++) {
-					for (int j = 0; j < 4; j++) {
-						gui[i * 4 + j] = v.columns[i][j];
-					}
-				}
+				convert_item_std140<Projection>(value, gui);
 			}
 		} break;
 		default: {
@@ -1943,7 +1565,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_IVEC2: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector2i v = p_value;
+			Vector2i v = convert_to_vector<Vector2i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = 0;
@@ -1951,7 +1573,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_IVEC3: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector3i v = p_value;
+			Vector3i v = convert_to_vector<Vector3i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = v.z;
@@ -1959,11 +1581,11 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_IVEC4: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector<int32_t> v = p_value;
-			bv.x = v.size() >= 1 ? v[0] : 0;
-			bv.y = v.size() >= 2 ? v[1] : 0;
-			bv.z = v.size() >= 3 ? v[2] : 0;
-			bv.w = v.size() >= 4 ? v[3] : 0;
+			Vector4i v = convert_to_vector<Vector4i>(p_value);
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = v.w;
 		} break;
 		case RS::GLOBAL_VAR_TYPE_RECT2I: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
@@ -1983,7 +1605,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_UVEC2: {
 			GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector2i v = p_value;
+			Vector2i v = convert_to_vector<Vector2i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = 0;
@@ -1991,7 +1613,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_UVEC3: {
 			GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector3i v = p_value;
+			Vector3i v = convert_to_vector<Vector3i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = v.z;
@@ -1999,11 +1621,11 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_UVEC4: {
 			GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector<int32_t> v = p_value;
-			bv.x = v.size() >= 1 ? v[0] : 0;
-			bv.y = v.size() >= 2 ? v[1] : 0;
-			bv.z = v.size() >= 3 ? v[2] : 0;
-			bv.w = v.size() >= 4 ? v[3] : 0;
+			Vector4i v = convert_to_vector<Vector4i>(p_value);
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = v.w;
 		} break;
 		case RS::GLOBAL_VAR_TYPE_FLOAT: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
@@ -2015,7 +1637,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_VEC2: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
-			Vector2 v = p_value;
+			Vector2 v = convert_to_vector<Vector2>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = 0;
@@ -2023,7 +1645,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_VEC3: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
-			Vector3 v = p_value;
+			Vector3 v = convert_to_vector<Vector3>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = v.z;
@@ -2031,11 +1653,11 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_VEC4: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
-			Plane v = p_value;
-			bv.x = v.normal.x;
-			bv.y = v.normal.y;
-			bv.z = v.normal.z;
-			bv.w = v.d;
+			Vector4 v = convert_to_vector<Vector4>(p_value);
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = v.w;
 		} break;
 		case RS::GLOBAL_VAR_TYPE_COLOR: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
@@ -2081,92 +1703,25 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		case RS::GLOBAL_VAR_TYPE_MAT3: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
 			Basis v = p_value;
-			bv[0].x = v.rows[0][0];
-			bv[0].y = v.rows[1][0];
-			bv[0].z = v.rows[2][0];
-			bv[0].w = 0;
-
-			bv[1].x = v.rows[0][1];
-			bv[1].y = v.rows[1][1];
-			bv[1].z = v.rows[2][1];
-			bv[1].w = 0;
-
-			bv[2].x = v.rows[0][2];
-			bv[2].y = v.rows[1][2];
-			bv[2].z = v.rows[2][2];
-			bv[2].w = 0;
+			convert_item_std140<Basis>(v, &bv->x);
 
 		} break;
 		case RS::GLOBAL_VAR_TYPE_MAT4: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
-
-			Vector<float> m2 = p_value;
-			if (m2.size() < 16) {
-				m2.resize(16);
-			}
-
-			bv[0].x = m2[0];
-			bv[0].y = m2[1];
-			bv[0].z = m2[2];
-			bv[0].w = m2[3];
-
-			bv[1].x = m2[4];
-			bv[1].y = m2[5];
-			bv[1].z = m2[6];
-			bv[1].w = m2[7];
-
-			bv[2].x = m2[8];
-			bv[2].y = m2[9];
-			bv[2].z = m2[10];
-			bv[2].w = m2[11];
-
-			bv[3].x = m2[12];
-			bv[3].y = m2[13];
-			bv[3].z = m2[14];
-			bv[3].w = m2[15];
+			Projection m = p_value;
+			convert_item_std140<Projection>(m, &bv->x);
 
 		} break;
 		case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
 			Transform2D v = p_value;
-			bv[0].x = v.columns[0][0];
-			bv[0].y = v.columns[0][1];
-			bv[0].z = 0;
-			bv[0].w = 0;
-
-			bv[1].x = v.columns[1][0];
-			bv[1].y = v.columns[1][1];
-			bv[1].z = 0;
-			bv[1].w = 0;
-
-			bv[2].x = v.columns[2][0];
-			bv[2].y = v.columns[2][1];
-			bv[2].z = 1;
-			bv[2].w = 0;
+			convert_item_std140<Transform2D>(v, &bv->x);
 
 		} break;
 		case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
 			Transform3D v = p_value;
-			bv[0].x = v.basis.rows[0][0];
-			bv[0].y = v.basis.rows[1][0];
-			bv[0].z = v.basis.rows[2][0];
-			bv[0].w = 0;
-
-			bv[1].x = v.basis.rows[0][1];
-			bv[1].y = v.basis.rows[1][1];
-			bv[1].z = v.basis.rows[2][1];
-			bv[1].w = 0;
-
-			bv[2].x = v.basis.rows[0][2];
-			bv[2].y = v.basis.rows[1][2];
-			bv[2].z = v.basis.rows[2][2];
-			bv[2].w = 0;
-
-			bv[3].x = v.origin.x;
-			bv[3].y = v.origin.y;
-			bv[3].z = v.origin.z;
-			bv[3].w = 1;
+			convert_item_std140<Transform3D>(v, &bv->x);
 
 		} break;
 		default: {

+ 6 - 40
editor/shader_globals_editor.cpp

@@ -198,7 +198,7 @@ protected:
 					pinfo.type = Variant::COLOR;
 				} break;
 				case RS::GLOBAL_VAR_TYPE_MAT2: {
-					pinfo.type = Variant::PACKED_INT32_ARRAY;
+					pinfo.type = Variant::PACKED_FLOAT32_ARRAY;
 				} break;
 				case RS::GLOBAL_VAR_TYPE_MAT3: {
 					pinfo.type = Variant::BASIS;
@@ -271,13 +271,7 @@ static Variant create_var(RS::GlobalShaderParameterType p_type) {
 			return Vector3i();
 		}
 		case RS::GLOBAL_VAR_TYPE_IVEC4: {
-			Vector<int> v4;
-			v4.resize(4);
-			v4.write[0] = 0;
-			v4.write[1] = 0;
-			v4.write[2] = 0;
-			v4.write[3] = 0;
-			return v4;
+			return Vector4i();
 		}
 		case RS::GLOBAL_VAR_TYPE_RECT2I: {
 			return Rect2i();
@@ -292,13 +286,7 @@ static Variant create_var(RS::GlobalShaderParameterType p_type) {
 			return Vector3i();
 		}
 		case RS::GLOBAL_VAR_TYPE_UVEC4: {
-			Vector<int> v4;
-			v4.resize(4);
-			v4.write[0] = 0;
-			v4.write[1] = 0;
-			v4.write[2] = 0;
-			v4.write[3] = 0;
-			return v4;
+			return Vector4i();
 		}
 		case RS::GLOBAL_VAR_TYPE_FLOAT: {
 			return 0.0;
@@ -310,7 +298,7 @@ static Variant create_var(RS::GlobalShaderParameterType p_type) {
 			return Vector3();
 		}
 		case RS::GLOBAL_VAR_TYPE_VEC4: {
-			return Quaternion();
+			return Vector4();
 		}
 		case RS::GLOBAL_VAR_TYPE_RECT2: {
 			return Rect2();
@@ -319,7 +307,7 @@ static Variant create_var(RS::GlobalShaderParameterType p_type) {
 			return Color();
 		}
 		case RS::GLOBAL_VAR_TYPE_MAT2: {
-			Vector<real_t> xform;
+			Vector<float> xform;
 			xform.resize(4);
 			xform.write[0] = 1;
 			xform.write[1] = 0;
@@ -337,29 +325,7 @@ static Variant create_var(RS::GlobalShaderParameterType p_type) {
 			return Transform3D();
 		}
 		case RS::GLOBAL_VAR_TYPE_MAT4: {
-			Vector<real_t> xform;
-			xform.resize(16);
-			xform.write[0] = 1;
-			xform.write[1] = 0;
-			xform.write[2] = 0;
-			xform.write[3] = 0;
-
-			xform.write[4] = 0;
-			xform.write[5] = 1;
-			xform.write[6] = 0;
-			xform.write[7] = 0;
-
-			xform.write[8] = 0;
-			xform.write[9] = 0;
-			xform.write[10] = 1;
-			xform.write[11] = 0;
-
-			xform.write[12] = 0;
-			xform.write[13] = 0;
-			xform.write[14] = 0;
-			xform.write[15] = 1;
-
-			return xform;
+			return Projection();
 		}
 		case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
 			return "";

+ 3 - 3
scene/main/shader_globals_override.cpp

@@ -128,7 +128,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
 				pinfo.type = Variant::VECTOR3I;
 			} break;
 			case RS::GLOBAL_VAR_TYPE_IVEC4: {
-				pinfo.type = Variant::PACKED_INT32_ARRAY;
+				pinfo.type = Variant::VECTOR4I;
 			} break;
 			case RS::GLOBAL_VAR_TYPE_RECT2I: {
 				pinfo.type = Variant::RECT2I;
@@ -143,7 +143,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
 				pinfo.type = Variant::VECTOR3I;
 			} break;
 			case RS::GLOBAL_VAR_TYPE_UVEC4: {
-				pinfo.type = Variant::PACKED_INT32_ARRAY;
+				pinfo.type = Variant::VECTOR4I;
 			} break;
 			case RS::GLOBAL_VAR_TYPE_FLOAT: {
 				pinfo.type = Variant::FLOAT;
@@ -164,7 +164,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
 				pinfo.type = Variant::COLOR;
 			} break;
 			case RS::GLOBAL_VAR_TYPE_MAT2: {
-				pinfo.type = Variant::PACKED_INT32_ARRAY;
+				pinfo.type = Variant::PACKED_FLOAT32_ARRAY;
 			} break;
 			case RS::GLOBAL_VAR_TYPE_MAT3: {
 				pinfo.type = Variant::BASIS;

+ 26 - 2
scene/resources/material.cpp

@@ -310,10 +310,34 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const {
 				vgroups.push_back(Pair<String, LocalVector<String>>("<None>", { "<None>" }));
 			}
 
+			const bool is_uniform_cached = param_cache.has(E->get().name);
+			bool is_uniform_type_compatible = true;
+
+			if (is_uniform_cached) {
+				// Check if the uniform Variant type changed, for example vec3 to vec4.
+				const Variant &cached = param_cache.get(E->get().name);
+
+				if (cached.is_array()) {
+					// Allow some array conversions for backwards compatibility.
+					is_uniform_type_compatible = Variant::can_convert(E->get().type, cached.get_type());
+				} else {
+					is_uniform_type_compatible = E->get().type == cached.get_type();
+				}
+
+				if (is_uniform_type_compatible && E->get().type == Variant::OBJECT && cached.get_type() == Variant::OBJECT) {
+					// Check if the Object class (hint string) changed, for example Texture2D sampler to Texture3D.
+					// Allow inheritance, Texture2D type sampler should also accept CompressedTexture2D.
+					Object *cached_obj = cached;
+					if (!cached_obj->is_class(E->get().hint_string)) {
+						is_uniform_type_compatible = false;
+					}
+				}
+			}
+
 			PropertyInfo info = E->get();
 			info.name = "shader_parameter/" + info.name;
-			if (!param_cache.has(E->get().name)) {
-				// Property has never been edited, retrieve with default value.
+			if (!is_uniform_cached || !is_uniform_type_compatible) {
+				// Property has never been edited or its type changed, retrieve with default value.
 				Variant default_value = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), E->get().name);
 				param_cache.insert(E->get().name, default_value);
 				remap_cache.insert(info.name, E->get().name);

+ 100 - 555
servers/rendering/renderer_rd/storage_rd/material_storage.cpp

@@ -32,6 +32,7 @@
 #include "core/config/engine.h"
 #include "core/config/project_settings.h"
 #include "core/io/resource_loader.h"
+#include "servers/rendering/storage/variant_converters.h"
 #include "texture_storage.h"
 
 using namespace RendererRD;
@@ -39,26 +40,17 @@ using namespace RendererRD;
 ///////////////////////////////////////////////////////////////////////////
 // UBI helper functions
 
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
 	switch (type) {
 		case ShaderLanguage::TYPE_BOOL: {
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = (r[i] != 0) ? 1 : 0;
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
+				PackedInt32Array ba = value;
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<int32_t>(ba, gui, p_array_size, 4);
 			} else {
 				bool v = value;
 				gui[0] = v ? 1 : 0;
@@ -68,22 +60,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-				int count = 2 * p_array_size;
-
-				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
-					if (i < s) {
-						gui[j] = r[i] ? 1 : 0;
-						gui[j + 1] = r[i + 1] ? 1 : 0;
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
+				PackedInt32Array ba = convert_array_std140<Vector2i, int32_t>(value);
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<Vector2i>(ba, gui, p_array_size, 4);
 			} else {
 				uint32_t v = value;
 				gui[0] = v & 1 ? 1 : 0;
@@ -94,23 +75,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-				int count = 3 * p_array_size;
-
-				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
-					if (i < s) {
-						gui[j] = r[i] ? 1 : 0;
-						gui[j + 1] = r[i + 1] ? 1 : 0;
-						gui[j + 2] = r[i + 2] ? 1 : 0;
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-					}
-					gui[j + 3] = 0; // ignored
+				PackedInt32Array ba = convert_array_std140<Vector3i, int32_t>(value);
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<Vector3i>(ba, gui, p_array_size, 4);
 			} else {
 				uint32_t v = value;
 				gui[0] = (v & 1) ? 1 : 0;
@@ -122,24 +91,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				const PackedInt32Array &ba = value;
-				int s = ba.size();
-				const int *r = ba.ptr();
-				int count = 4 * p_array_size;
-
-				for (int i = 0; i < count; i += 4) {
-					if (i < s) {
-						gui[i] = r[i] ? 1 : 0;
-						gui[i + 1] = r[i + 1] ? 1 : 0;
-						gui[i + 2] = r[i + 2] ? 1 : 0;
-						gui[i + 3] = r[i + 3] ? 1 : 0;
-					} else {
-						gui[i] = 0;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-					}
+				PackedInt32Array ba = convert_array_std140<Vector4i, int32_t>(value);
+				for (int i = 0; i < ba.size(); i++) {
+					ba.set(i, ba[i] ? 1 : 0);
 				}
+				write_array_std140<Vector4i>(ba, gui, p_array_size, 4);
 			} else {
 				uint32_t v = value;
 				gui[0] = (v & 1) ? 1 : 0;
@@ -152,20 +108,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			int32_t *gui = (int32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				const int *r = iv.ptr();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = value;
+				write_array_std140<int32_t>(iv, gui, p_array_size, 4);
 			} else {
 				int v = value;
 				gui[0] = v;
@@ -173,51 +117,24 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 		} break;
 		case ShaderLanguage::TYPE_IVEC2: {
 			int32_t *gui = (int32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 2 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector2i, int32_t>(value);
+				write_array_std140<Vector2i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector2i v = value;
+				Vector2i v = convert_to_vector<Vector2i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 			}
 		} break;
 		case ShaderLanguage::TYPE_IVEC3: {
 			int32_t *gui = (int32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 3 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-						gui[j + 2] = r[i + 2];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-					}
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector3i, int32_t>(value);
+				write_array_std140<Vector3i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector3i v = value;
+				Vector3i v = convert_to_vector<Vector3i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -225,27 +142,12 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 		} break;
 		case ShaderLanguage::TYPE_IVEC4: {
 			int32_t *gui = (int32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 4 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0; i < count; i += 4) {
-					if (i < s) {
-						gui[i] = r[i];
-						gui[i + 1] = r[i + 1];
-						gui[i + 2] = r[i + 2];
-						gui[i + 3] = r[i + 3];
-					} else {
-						gui[i] = 0;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-					}
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector4i, int32_t>(value);
+				write_array_std140<Vector4i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector4i v = value;
+				Vector4i v = convert_to_vector<Vector4i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -256,20 +158,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			uint32_t *gui = (uint32_t *)data;
 
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				const int *r = iv.ptr();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = value;
+				write_array_std140<uint32_t>(iv, gui, p_array_size, 4);
 			} else {
 				int v = value;
 				gui[0] = v;
@@ -277,51 +167,24 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 		} break;
 		case ShaderLanguage::TYPE_UVEC2: {
 			uint32_t *gui = (uint32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 2 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector2i, int32_t>(value);
+				write_array_std140<Vector2i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector2i v = value;
+				Vector2i v = convert_to_vector<Vector2i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 			}
 		} break;
 		case ShaderLanguage::TYPE_UVEC3: {
 			uint32_t *gui = (uint32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 3 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
-					if (i < s) {
-						gui[j] = r[i];
-						gui[j + 1] = r[i + 1];
-						gui[j + 2] = r[i + 2];
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-					}
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector3i, int32_t>(value);
+				write_array_std140<Vector3i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector3i v = value;
+				Vector3i v = convert_to_vector<Vector3i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -329,27 +192,12 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 		} break;
 		case ShaderLanguage::TYPE_UVEC4: {
 			uint32_t *gui = (uint32_t *)data;
+
 			if (p_array_size > 0) {
-				Vector<int> iv = value;
-				int s = iv.size();
-				int count = 4 * p_array_size;
-
-				const int *r = iv.ptr();
-				for (int i = 0; i < count; i++) {
-					if (i < s) {
-						gui[i] = r[i];
-						gui[i + 1] = r[i + 1];
-						gui[i + 2] = r[i + 2];
-						gui[i + 3] = r[i + 3];
-					} else {
-						gui[i] = 0;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-					}
-				}
+				const PackedInt32Array &iv = convert_array_std140<Vector4i, int32_t>(value);
+				write_array_std140<Vector4i>(iv, gui, p_array_size, 4);
 			} else {
-				Vector4i v = value;
+				Vector4i v = convert_to_vector<Vector4i>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 				gui[2] = v.z;
@@ -361,18 +209,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 
 			if (p_array_size > 0) {
 				const PackedFloat32Array &a = value;
-				int s = a.size();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = a[i];
-					} else {
-						gui[j] = 0;
-					}
-					gui[j + 1] = 0; // ignored
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				write_array_std140<float>(a, gui, p_array_size, 4);
 			} else {
 				float v = value;
 				gui[0] = v;
@@ -382,22 +219,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			float *gui = reinterpret_cast<float *>(data);
 
 			if (p_array_size > 0) {
-				const PackedVector2Array &a = value;
-				int s = a.size();
-
-				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-					if (i < s) {
-						gui[j] = a[i].x;
-						gui[j + 1] = a[i].y;
-					} else {
-						gui[j] = 0;
-						gui[j + 1] = 0;
-					}
-					gui[j + 2] = 0; // ignored
-					gui[j + 3] = 0; // ignored
-				}
+				const PackedFloat32Array &a = convert_array_std140<Vector2, float>(value);
+				write_array_std140<Vector2>(a, gui, p_array_size, 4);
 			} else {
-				Vector2 v = value;
+				Vector2 v = convert_to_vector<Vector2>(value);
 				gui[0] = v.x;
 				gui[1] = v.y;
 			}
@@ -406,147 +231,27 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			float *gui = reinterpret_cast<float *>(data);
 
 			if (p_array_size > 0) {
-				if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
-					const PackedColorArray &a = value;
-					int s = a.size();
-
-					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-						if (i < s) {
-							Color color = a[i];
-							if (p_linear_color) {
-								color = color.srgb_to_linear();
-							}
-							gui[j] = color.r;
-							gui[j + 1] = color.g;
-							gui[j + 2] = color.b;
-						} else {
-							gui[j] = 0;
-							gui[j + 1] = 0;
-							gui[j + 2] = 0;
-						}
-						gui[j + 3] = 0; // ignored
-					}
-				} else {
-					const PackedVector3Array &a = value;
-					int s = a.size();
-
-					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-						if (i < s) {
-							gui[j] = a[i].x;
-							gui[j + 1] = a[i].y;
-							gui[j + 2] = a[i].z;
-						} else {
-							gui[j] = 0;
-							gui[j + 1] = 0;
-							gui[j + 2] = 0;
-						}
-						gui[j + 3] = 0; // ignored
-					}
-				}
+				const PackedFloat32Array &a = convert_array_std140<Vector3, float>(value, p_linear_color);
+				write_array_std140<Vector3>(a, gui, p_array_size, 4);
 			} else {
-				if (value.get_type() == Variant::COLOR) {
-					Color v = value;
-
-					if (p_linear_color) {
-						v = v.srgb_to_linear();
-					}
-
-					gui[0] = v.r;
-					gui[1] = v.g;
-					gui[2] = v.b;
-				} else {
-					Vector3 v = value;
-					gui[0] = v.x;
-					gui[1] = v.y;
-					gui[2] = v.z;
-				}
+				Vector3 v = convert_to_vector<Vector3>(value, p_linear_color);
+				gui[0] = v.x;
+				gui[1] = v.y;
+				gui[2] = v.z;
 			}
 		} break;
 		case ShaderLanguage::TYPE_VEC4: {
 			float *gui = reinterpret_cast<float *>(data);
 
 			if (p_array_size > 0) {
-				if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
-					const PackedColorArray &a = value;
-					int s = a.size();
-
-					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
-						if (i < s) {
-							Color color = a[i];
-							if (p_linear_color) {
-								color = color.srgb_to_linear();
-							}
-							gui[j] = color.r;
-							gui[j + 1] = color.g;
-							gui[j + 2] = color.b;
-							gui[j + 3] = color.a;
-						} else {
-							gui[j] = 0;
-							gui[j + 1] = 0;
-							gui[j + 2] = 0;
-							gui[j + 3] = 0;
-						}
-					}
-				} else {
-					const PackedFloat32Array &a = value;
-					int s = a.size();
-					int count = 4 * p_array_size;
-
-					for (int i = 0; i < count; i += 4) {
-						if (i + 3 < s) {
-							gui[i] = a[i];
-							gui[i + 1] = a[i + 1];
-							gui[i + 2] = a[i + 2];
-							gui[i + 3] = a[i + 3];
-						} else {
-							gui[i] = 0;
-							gui[i + 1] = 0;
-							gui[i + 2] = 0;
-							gui[i + 3] = 0;
-						}
-					}
-				}
+				const PackedFloat32Array &a = convert_array_std140<Vector4, float>(value, p_linear_color);
+				write_array_std140<Vector4>(a, gui, p_array_size, 4);
 			} else {
-				if (value.get_type() == Variant::COLOR) {
-					Color v = value;
-
-					if (p_linear_color) {
-						v = v.srgb_to_linear();
-					}
-
-					gui[0] = v.r;
-					gui[1] = v.g;
-					gui[2] = v.b;
-					gui[3] = v.a;
-				} else if (value.get_type() == Variant::RECT2) {
-					Rect2 v = value;
-
-					gui[0] = v.position.x;
-					gui[1] = v.position.y;
-					gui[2] = v.size.x;
-					gui[3] = v.size.y;
-				} else if (value.get_type() == Variant::QUATERNION) {
-					Quaternion v = value;
-
-					gui[0] = v.x;
-					gui[1] = v.y;
-					gui[2] = v.z;
-					gui[3] = v.w;
-				} else if (value.get_type() == Variant::PLANE) {
-					Plane v = value;
-
-					gui[0] = v.normal.x;
-					gui[1] = v.normal.y;
-					gui[2] = v.normal.z;
-					gui[3] = v.d;
-				} else {
-					Vector4 v = value;
-
-					gui[0] = v.x;
-					gui[1] = v.y;
-					gui[2] = v.z;
-					gui[3] = v.w;
-				}
+				Vector4 v = convert_to_vector<Vector4>(value, p_linear_color);
+				gui[0] = v.x;
+				gui[1] = v.y;
+				gui[2] = v.z;
+				gui[3] = v.w;
 			}
 		} break;
 		case ShaderLanguage::TYPE_MAT2: {
@@ -594,135 +299,42 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
 			float *gui = reinterpret_cast<float *>(data);
 
 			if (p_array_size > 0) {
-				const PackedFloat32Array &a = value;
-				int s = a.size();
+				const PackedFloat32Array &a = convert_array_std140<Basis, float>(value);
+				const Basis default_basis;
+				const int s = a.size();
 
 				for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
 					if (i + 8 < s) {
 						gui[j] = a[i];
 						gui[j + 1] = a[i + 1];
 						gui[j + 2] = a[i + 2];
+						gui[j + 3] = 0; // Ignored.
 
 						gui[j + 4] = a[i + 3];
 						gui[j + 5] = a[i + 4];
 						gui[j + 6] = a[i + 5];
+						gui[j + 7] = 0; // Ignored.
 
 						gui[j + 8] = a[i + 6];
 						gui[j + 9] = a[i + 7];
 						gui[j + 10] = a[i + 8];
+						gui[j + 11] = 0; // Ignored.
 					} else {
-						gui[j] = 1;
-						gui[j + 1] = 0;
-						gui[j + 2] = 0;
-
-						gui[j + 4] = 0;
-						gui[j + 5] = 1;
-						gui[j + 6] = 0;
-
-						gui[j + 8] = 0;
-						gui[j + 9] = 0;
-						gui[j + 10] = 1;
+						convert_item_std140(default_basis, gui + j);
 					}
-					gui[j + 3] = 0; // ignored
-					gui[j + 7] = 0; // ignored
-					gui[j + 11] = 0; // ignored
 				}
 			} else {
-				Basis v = value;
-				gui[0] = v.rows[0][0];
-				gui[1] = v.rows[1][0];
-				gui[2] = v.rows[2][0];
-				gui[3] = 0; // ignored
-
-				gui[4] = v.rows[0][1];
-				gui[5] = v.rows[1][1];
-				gui[6] = v.rows[2][1];
-				gui[7] = 0; // ignored
-
-				gui[8] = v.rows[0][2];
-				gui[9] = v.rows[1][2];
-				gui[10] = v.rows[2][2];
-				gui[11] = 0; // ignored
+				convert_item_std140<Basis>(value, gui);
 			}
 		} break;
 		case ShaderLanguage::TYPE_MAT4: {
 			float *gui = reinterpret_cast<float *>(data);
 
 			if (p_array_size > 0) {
-				const PackedFloat32Array &a = value;
-				int s = a.size();
-
-				for (int i = 0; i < p_array_size * 16; i += 16) {
-					if (i + 15 < s) {
-						gui[i] = a[i];
-						gui[i + 1] = a[i + 1];
-						gui[i + 2] = a[i + 2];
-						gui[i + 3] = a[i + 3];
-
-						gui[i + 4] = a[i + 4];
-						gui[i + 5] = a[i + 5];
-						gui[i + 6] = a[i + 6];
-						gui[i + 7] = a[i + 7];
-
-						gui[i + 8] = a[i + 8];
-						gui[i + 9] = a[i + 9];
-						gui[i + 10] = a[i + 10];
-						gui[i + 11] = a[i + 11];
-
-						gui[i + 12] = a[i + 12];
-						gui[i + 13] = a[i + 13];
-						gui[i + 14] = a[i + 14];
-						gui[i + 15] = a[i + 15];
-					} else {
-						gui[i] = 1;
-						gui[i + 1] = 0;
-						gui[i + 2] = 0;
-						gui[i + 3] = 0;
-
-						gui[i + 4] = 0;
-						gui[i + 5] = 1;
-						gui[i + 6] = 0;
-						gui[i + 7] = 0;
-
-						gui[i + 8] = 0;
-						gui[i + 9] = 0;
-						gui[i + 10] = 1;
-						gui[i + 11] = 0;
-
-						gui[i + 12] = 0;
-						gui[i + 13] = 0;
-						gui[i + 14] = 0;
-						gui[i + 15] = 1;
-					}
-				}
-			} else if (value.get_type() == Variant::TRANSFORM3D) {
-				Transform3D v = value;
-				gui[0] = v.basis.rows[0][0];
-				gui[1] = v.basis.rows[1][0];
-				gui[2] = v.basis.rows[2][0];
-				gui[3] = 0;
-
-				gui[4] = v.basis.rows[0][1];
-				gui[5] = v.basis.rows[1][1];
-				gui[6] = v.basis.rows[2][1];
-				gui[7] = 0;
-
-				gui[8] = v.basis.rows[0][2];
-				gui[9] = v.basis.rows[1][2];
-				gui[10] = v.basis.rows[2][2];
-				gui[11] = 0;
-
-				gui[12] = v.origin.x;
-				gui[13] = v.origin.y;
-				gui[14] = v.origin.z;
-				gui[15] = 1;
+				const PackedFloat32Array &a = convert_array_std140<Projection, float>(value);
+				write_array_std140<Projection>(a, gui, p_array_size, 16);
 			} else {
-				Projection v = value;
-				for (int i = 0; i < 4; i++) {
-					for (int j = 0; j < 4; j++) {
-						gui[i * 4 + j] = v.columns[i][j];
-					}
-				}
+				convert_item_std140<Projection>(value, gui);
 			}
 		} break;
 		default: {
@@ -1820,7 +1432,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_IVEC2: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector2i v = p_value;
+			Vector2i v = convert_to_vector<Vector2i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = 0;
@@ -1828,7 +1440,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_IVEC3: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector3i v = p_value;
+			Vector3i v = convert_to_vector<Vector3i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = v.z;
@@ -1836,11 +1448,11 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_IVEC4: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector<int32_t> v = p_value;
-			bv.x = v.size() >= 1 ? v[0] : 0;
-			bv.y = v.size() >= 2 ? v[1] : 0;
-			bv.z = v.size() >= 3 ? v[2] : 0;
-			bv.w = v.size() >= 4 ? v[3] : 0;
+			Vector4i v = convert_to_vector<Vector4i>(p_value);
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = v.w;
 		} break;
 		case RS::GLOBAL_VAR_TYPE_RECT2I: {
 			GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
@@ -1860,7 +1472,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_UVEC2: {
 			GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector2i v = p_value;
+			Vector2i v = convert_to_vector<Vector2i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = 0;
@@ -1868,7 +1480,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_UVEC3: {
 			GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector3i v = p_value;
+			Vector3i v = convert_to_vector<Vector3i>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = v.z;
@@ -1876,11 +1488,11 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_UVEC4: {
 			GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
-			Vector<int32_t> v = p_value;
-			bv.x = v.size() >= 1 ? v[0] : 0;
-			bv.y = v.size() >= 2 ? v[1] : 0;
-			bv.z = v.size() >= 3 ? v[2] : 0;
-			bv.w = v.size() >= 4 ? v[3] : 0;
+			Vector4i v = convert_to_vector<Vector4i>(p_value);
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = v.w;
 		} break;
 		case RS::GLOBAL_VAR_TYPE_FLOAT: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
@@ -1892,7 +1504,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_VEC2: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
-			Vector2 v = p_value;
+			Vector2 v = convert_to_vector<Vector2>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = 0;
@@ -1900,7 +1512,7 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_VEC3: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
-			Vector3 v = p_value;
+			Vector3 v = convert_to_vector<Vector3>(p_value);
 			bv.x = v.x;
 			bv.y = v.y;
 			bv.z = v.z;
@@ -1908,11 +1520,11 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		} break;
 		case RS::GLOBAL_VAR_TYPE_VEC4: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
-			Plane v = p_value;
-			bv.x = v.normal.x;
-			bv.y = v.normal.y;
-			bv.z = v.normal.z;
-			bv.w = v.d;
+			Vector4 v = convert_to_vector<Vector4>(p_value);
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = v.w;
 		} break;
 		case RS::GLOBAL_VAR_TYPE_COLOR: {
 			GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
@@ -1958,92 +1570,25 @@ void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS
 		case RS::GLOBAL_VAR_TYPE_MAT3: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
 			Basis v = p_value;
-			bv[0].x = v.rows[0][0];
-			bv[0].y = v.rows[1][0];
-			bv[0].z = v.rows[2][0];
-			bv[0].w = 0;
-
-			bv[1].x = v.rows[0][1];
-			bv[1].y = v.rows[1][1];
-			bv[1].z = v.rows[2][1];
-			bv[1].w = 0;
-
-			bv[2].x = v.rows[0][2];
-			bv[2].y = v.rows[1][2];
-			bv[2].z = v.rows[2][2];
-			bv[2].w = 0;
+			convert_item_std140<Basis>(v, &bv->x);
 
 		} break;
 		case RS::GLOBAL_VAR_TYPE_MAT4: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
-
-			Vector<float> m2 = p_value;
-			if (m2.size() < 16) {
-				m2.resize(16);
-			}
-
-			bv[0].x = m2[0];
-			bv[0].y = m2[1];
-			bv[0].z = m2[2];
-			bv[0].w = m2[3];
-
-			bv[1].x = m2[4];
-			bv[1].y = m2[5];
-			bv[1].z = m2[6];
-			bv[1].w = m2[7];
-
-			bv[2].x = m2[8];
-			bv[2].y = m2[9];
-			bv[2].z = m2[10];
-			bv[2].w = m2[11];
-
-			bv[3].x = m2[12];
-			bv[3].y = m2[13];
-			bv[3].z = m2[14];
-			bv[3].w = m2[15];
+			Projection m = p_value;
+			convert_item_std140<Projection>(m, &bv->x);
 
 		} break;
 		case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
 			Transform2D v = p_value;
-			bv[0].x = v.columns[0][0];
-			bv[0].y = v.columns[0][1];
-			bv[0].z = 0;
-			bv[0].w = 0;
-
-			bv[1].x = v.columns[1][0];
-			bv[1].y = v.columns[1][1];
-			bv[1].z = 0;
-			bv[1].w = 0;
-
-			bv[2].x = v.columns[2][0];
-			bv[2].y = v.columns[2][1];
-			bv[2].z = 1;
-			bv[2].w = 0;
+			convert_item_std140<Transform2D>(v, &bv->x);
 
 		} break;
 		case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
 			GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
 			Transform3D v = p_value;
-			bv[0].x = v.basis.rows[0][0];
-			bv[0].y = v.basis.rows[1][0];
-			bv[0].z = v.basis.rows[2][0];
-			bv[0].w = 0;
-
-			bv[1].x = v.basis.rows[0][1];
-			bv[1].y = v.basis.rows[1][1];
-			bv[1].z = v.basis.rows[2][1];
-			bv[1].w = 0;
-
-			bv[2].x = v.basis.rows[0][2];
-			bv[2].y = v.basis.rows[1][2];
-			bv[2].z = v.basis.rows[2][2];
-			bv[2].w = 0;
-
-			bv[3].x = v.origin.x;
-			bv[3].y = v.origin.y;
-			bv[3].z = v.origin.z;
-			bv[3].w = 1;
+			convert_item_std140<Transform3D>(v, &bv->x);
 
 		} break;
 		default: {

+ 7 - 7
servers/rendering/shader_language.cpp

@@ -3790,7 +3790,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					}
 					value = Variant(array);
 				} else {
-					value = Variant(Vector2(p_value[0].sint, p_value[1].sint));
+					value = Variant(Vector2i(p_value[0].sint, p_value[1].sint));
 				}
 				break;
 			case ShaderLanguage::TYPE_IVEC3:
@@ -3803,7 +3803,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					}
 					value = Variant(array);
 				} else {
-					value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint));
+					value = Variant(Vector3i(p_value[0].sint, p_value[1].sint, p_value[2].sint));
 				}
 				break;
 			case ShaderLanguage::TYPE_IVEC4:
@@ -3816,7 +3816,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					}
 					value = Variant(array);
 				} else {
-					value = Variant(Quaternion(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+					value = Variant(Vector4i(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
 				}
 				break;
 			case ShaderLanguage::TYPE_UINT:
@@ -3840,7 +3840,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					}
 					value = Variant(array);
 				} else {
-					value = Variant(Vector2(p_value[0].uint, p_value[1].uint));
+					value = Variant(Vector2i(p_value[0].uint, p_value[1].uint));
 				}
 				break;
 			case ShaderLanguage::TYPE_UVEC3:
@@ -3853,7 +3853,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					}
 					value = Variant(array);
 				} else {
-					value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint));
+					value = Variant(Vector3i(p_value[0].uint, p_value[1].uint, p_value[2].uint));
 				}
 				break;
 			case ShaderLanguage::TYPE_UVEC4:
@@ -3866,7 +3866,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					}
 					value = Variant(array);
 				} else {
-					value = Variant(Quaternion(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+					value = Variant(Vector4i(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
 				}
 				break;
 			case ShaderLanguage::TYPE_FLOAT:
@@ -3942,7 +3942,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
 					if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
 						value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
 					} else {
-						value = Variant(Quaternion(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+						value = Variant(Vector4(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
 					}
 				}
 				break;

+ 322 - 0
servers/rendering/storage/variant_converters.h

@@ -0,0 +1,322 @@
+/**************************************************************************/
+/*  variant_converters.h                                                  */
+/**************************************************************************/
+/*                         This file is part of:                          */
+/*                             GODOT ENGINE                               */
+/*                        https://godotengine.org                         */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
+/*                                                                        */
+/* Permission is hereby granted, free of charge, to any person obtaining  */
+/* a copy of this software and associated documentation files (the        */
+/* "Software"), to deal in the Software without restriction, including    */
+/* without limitation the rights to use, copy, modify, merge, publish,    */
+/* distribute, sublicense, and/or sell copies of the Software, and to     */
+/* permit persons to whom the Software is furnished to do so, subject to  */
+/* the following conditions:                                              */
+/*                                                                        */
+/* The above copyright notice and this permission notice shall be         */
+/* included in all copies or substantial portions of the Software.        */
+/*                                                                        */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
+/**************************************************************************/
+
+#ifndef VARIANT_CONVERTERS_H
+#define VARIANT_CONVERTERS_H
+
+#include "core/error/error_macros.h"
+#include "core/variant/array.h"
+#include "core/variant/variant.h"
+
+#include <initializer_list>
+#include <type_traits>
+
+template <typename T>
+struct VariantConverterStd140 {
+	// Generic base template for all Vector2/3/4(i) classes.
+	static constexpr int Elements = T::AXIS_COUNT;
+
+	template <typename P>
+	static void convert(const T &p_v, P *p_write, bool p_compact) {
+		for (int i = 0; i < Elements; i++) {
+			p_write[i] = p_v[i];
+		}
+	}
+};
+
+template <>
+struct VariantConverterStd140<float> {
+	static constexpr int Elements = 1;
+
+	template <typename P>
+	static void convert(float p_v, P *p_write, bool p_compact) {
+		p_write[0] = p_v;
+	}
+};
+
+template <>
+struct VariantConverterStd140<int32_t> {
+	static constexpr int Elements = 1;
+
+	template <typename P>
+	static void convert(int32_t p_v, P *p_write, bool p_compact) {
+		p_write[0] = p_v;
+	}
+};
+
+template <>
+struct VariantConverterStd140<uint32_t> {
+	static constexpr int Elements = 1;
+
+	template <typename P>
+	static void convert(uint32_t p_v, P *p_write, bool p_compact) {
+		p_write[0] = p_v;
+	}
+};
+
+template <>
+struct VariantConverterStd140<Basis> {
+	static constexpr int Elements = 9;
+
+	template <typename P>
+	static void convert(const Basis &p_v, P *p_write, bool p_compact) {
+		// Basis can have compact 9 floats or std140 layout 12 floats.
+		int i = 0;
+
+		p_write[i++] = p_v.rows[0][0];
+		p_write[i++] = p_v.rows[1][0];
+		p_write[i++] = p_v.rows[2][0];
+		if (!p_compact) {
+			p_write[i++] = 0;
+		}
+
+		p_write[i++] = p_v.rows[0][1];
+		p_write[i++] = p_v.rows[1][1];
+		p_write[i++] = p_v.rows[2][1];
+		if (!p_compact) {
+			p_write[i++] = 0;
+		}
+
+		p_write[i++] = p_v.rows[0][2];
+		p_write[i++] = p_v.rows[1][2];
+		p_write[i++] = p_v.rows[2][2];
+		if (!p_compact) {
+			p_write[i++] = 0;
+		}
+	}
+};
+
+template <>
+struct VariantConverterStd140<Transform2D> {
+	static constexpr int Elements = 12;
+
+	template <typename P>
+	static void convert(const Transform2D &p_v, P *p_write, bool p_compact) {
+		p_write[0] = p_v.columns[0][0];
+		p_write[1] = p_v.columns[0][1];
+		p_write[2] = 0;
+		p_write[3] = 0;
+
+		p_write[4] = p_v.columns[1][0];
+		p_write[5] = p_v.columns[1][1];
+		p_write[6] = 0;
+		p_write[7] = 0;
+
+		p_write[8] = p_v.columns[2][0];
+		p_write[9] = p_v.columns[2][1];
+		p_write[10] = 1;
+		p_write[11] = 0;
+	}
+};
+
+template <>
+struct VariantConverterStd140<Transform3D> {
+	static constexpr int Elements = 16;
+
+	template <typename P>
+	static void convert(const Transform3D &p_v, P *p_write, bool p_compact) {
+		p_write[0] = p_v.basis.rows[0][0];
+		p_write[1] = p_v.basis.rows[1][0];
+		p_write[2] = p_v.basis.rows[2][0];
+		p_write[3] = 0;
+
+		p_write[4] = p_v.basis.rows[0][1];
+		p_write[5] = p_v.basis.rows[1][1];
+		p_write[6] = p_v.basis.rows[2][1];
+		p_write[7] = 0;
+
+		p_write[8] = p_v.basis.rows[0][2];
+		p_write[9] = p_v.basis.rows[1][2];
+		p_write[10] = p_v.basis.rows[2][2];
+		p_write[11] = 0;
+
+		p_write[12] = p_v.origin.x;
+		p_write[13] = p_v.origin.y;
+		p_write[14] = p_v.origin.z;
+		p_write[15] = 1;
+	}
+};
+
+template <>
+struct VariantConverterStd140<Projection> {
+	static constexpr int Elements = 16;
+
+	template <typename P>
+	static void convert(const Projection &p_v, P *p_write, bool p_compact) {
+		for (int i = 0; i < 4; i++) {
+			for (int j = 0; j < 4; j++) {
+				p_write[i * 4 + j] = p_v.columns[i][j];
+			}
+		}
+	}
+};
+
+template <typename T, typename P>
+T construct_vector(const std::initializer_list<P> &values) {
+	T vector{};
+	int index = 0;
+	for (P v : values) {
+		vector[index++] = v;
+		if (index >= T::AXIS_COUNT) {
+			break;
+		}
+	}
+	return vector;
+}
+
+// Compatibility converter, tries to convert certain Variant types into a Vector2/3/4(i).
+
+template <typename T>
+T convert_to_vector(const Variant &p_variant, bool p_linear_color = false) {
+	const Variant::Type type = p_variant.get_type();
+
+	if (type == Variant::QUATERNION) {
+		Quaternion quat = p_variant;
+		return construct_vector<T>({ quat.x, quat.y, quat.z, quat.w });
+	} else if (type == Variant::PLANE) {
+		Plane p = p_variant;
+		return construct_vector<T>({ p.normal.x, p.normal.y, p.normal.z, p.d });
+	} else if (type == Variant::RECT2 || type == Variant::RECT2I) {
+		Rect2 r = p_variant;
+		return construct_vector<T>({ r.position.x, r.position.y, r.size.x, r.size.y });
+	} else if (type == Variant::COLOR) {
+		Color c = p_variant;
+		if (p_linear_color) {
+			c = c.srgb_to_linear();
+		}
+		return construct_vector<T>({ c.r, c.g, c.b, c.a });
+	} else if (p_variant.is_array()) {
+		const Array &array = p_variant;
+		const int size = MIN(array.size(), T::AXIS_COUNT);
+		T vector{};
+		for (int i = 0; i < size; i++) {
+			vector[i] = array.get(i);
+		}
+		return vector;
+	}
+
+	return p_variant; // Default Variant conversion, covers all Vector2/3/4(i) types.
+}
+
+inline bool is_number_array(const Array &p_array) {
+	const int size = p_array.size();
+	for (int i = 0; i < size; i++) {
+		if (!p_array.get(i).is_num()) {
+			return false;
+		}
+	}
+	return true;
+}
+
+inline bool is_convertible_array(Variant::Type type) {
+	return type == Variant::ARRAY ||
+			type == Variant::PACKED_VECTOR2_ARRAY ||
+			type == Variant::PACKED_VECTOR3_ARRAY ||
+			type == Variant::PACKED_COLOR_ARRAY;
+}
+
+template <class, class = void>
+struct is_vector_type : std::false_type {};
+
+template <class T>
+struct is_vector_type<T, std::void_t<decltype(T::AXIS_COUNT)>> : std::true_type {};
+
+template <typename T, typename P>
+void convert_item_std140(const T &p_item, P *p_write, bool p_compact = false) {
+	VariantConverterStd140<T>::template convert<P>(p_item, p_write, p_compact);
+}
+
+template <typename T, typename P>
+Vector<P> convert_array_std140(const Variant &p_variant, [[maybe_unused]] bool p_linear_color = false) {
+	if (is_convertible_array(p_variant.get_type())) {
+		// Slow path, convert Variant arrays and some packed arrays manually into primitive types.
+		const Array &array = p_variant;
+		if (is_number_array(array)) {
+			// Already flattened and converted (or empty) array, usually coming from saved resources.
+			return p_variant;
+		}
+
+		const int items = array.size();
+		constexpr int elements = VariantConverterStd140<T>::Elements;
+
+		Vector<P> result;
+		result.resize(items * elements);
+		P *write = result.ptrw();
+
+		for (int i = 0; i < items; i++) {
+			const Variant &item = array.get(i);
+			P *offset = write + (i * elements);
+
+			if constexpr (is_vector_type<T>::value) {
+				const T &vec = convert_to_vector<T>(item, p_linear_color);
+				convert_item_std140<T, P>(vec, offset, true);
+			} else {
+				convert_item_std140<T, P>(item.operator T(), offset, true);
+			}
+		}
+		return result;
+
+	} else if (p_variant.is_array()) {
+		// Fast path, return the packed array directly.
+		return p_variant;
+	}
+
+	// Not an array type. Usually happens with uninitialized null shader resource parameters.
+	// Just return an empty array, uniforms will be default initialized later.
+
+	return Vector<P>();
+}
+
+template <typename T, typename From, typename To>
+void write_array_std140(const Vector<From> &p_values, To *p_write, int p_array_size, int p_stride) {
+	constexpr int elements = VariantConverterStd140<T>::Elements;
+	const int src_count = p_values.size();
+	const int dst_count = elements * p_array_size;
+	const int stride_count = p_stride * p_array_size;
+	const From *read = p_values.ptr();
+	const T default_value{};
+
+	memset(p_write, 0, sizeof(To) * stride_count);
+
+	for (int i = 0, j = 0; i < dst_count; i += elements, j += p_stride) {
+		if (i + elements - 1 < src_count) {
+			// Only copy full items with all elements, no partial or missing data.
+			for (int e = 0; e < elements; e++) {
+				DEV_ASSERT(j + e < stride_count && i + e < src_count);
+				p_write[j + e] = read[i + e];
+			}
+		} else {
+			// If not enough source data was passed in, write default values.
+			convert_item_std140(default_value, p_write + j);
+		}
+	}
+}
+
+#endif // VARIANT_CONVERTERS_H