Sfoglia il codice sorgente

Merge pull request #51769 from The-O-King/oct_split_stream_fix

Fix Octahedral/Split Stream Options
Rémi Verschelde 4 anni fa
parent
commit
92a7ae022d

+ 1 - 1
doc/classes/VisualServer.xml

@@ -1958,8 +1958,8 @@
 			<argument index="0" name="format" type="int" />
 			<argument index="0" name="format" type="int" />
 			<argument index="1" name="vertex_len" type="int" />
 			<argument index="1" name="vertex_len" type="int" />
 			<argument index="2" name="index_len" type="int" />
 			<argument index="2" name="index_len" type="int" />
+			<argument index="3" name="array_index" type="int" />
 			<description>
 			<description>
-				Function is unused in Godot 3.x.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="mesh_surface_get_index_array" qualifiers="const">
 		<method name="mesh_surface_get_index_array" qualifiers="const">

+ 3 - 3
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -2114,7 +2114,7 @@ static PoolVector<uint8_t> _unpack_half_floats(const PoolVector<uint8_t> &array,
 			} break;
 			} break;
 			case VS::ARRAY_TANGENT: {
 			case VS::ARRAY_TANGENT: {
 				if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
-					if (!(p_format & VS::ARRAY_COMPRESS_TANGENT)) {
+					if (!(p_format & VS::ARRAY_COMPRESS_TANGENT && p_format & VS::ARRAY_COMPRESS_NORMAL)) {
 						src_size[VS::ARRAY_NORMAL] = 8;
 						src_size[VS::ARRAY_NORMAL] = 8;
 						dst_size[VS::ARRAY_NORMAL] = 8;
 						dst_size[VS::ARRAY_NORMAL] = 8;
 					}
 					}
@@ -2254,7 +2254,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
 	}
 	}
 
 
 	//bool has_morph = p_blend_shapes.size();
 	//bool has_morph = p_blend_shapes.size();
-	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream");
+	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream") && !(p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
 
 
 	Surface::Attrib attribs[VS::ARRAY_MAX];
 	Surface::Attrib attribs[VS::ARRAY_MAX];
 
 
@@ -2330,7 +2330,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
 			case VS::ARRAY_TANGENT: {
 			case VS::ARRAY_TANGENT: {
 				if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 					attribs[i].enabled = false;
 					attribs[i].enabled = false;
-					if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
+					if (p_format & VS::ARRAY_COMPRESS_TANGENT && p_format & VS::ARRAY_COMPRESS_NORMAL) {
 						// normal and tangent will each be oct16 (2 bytes each)
 						// normal and tangent will each be oct16 (2 bytes each)
 						// pack into single vec4<GL_BYTE> for memory bandwidth
 						// pack into single vec4<GL_BYTE> for memory bandwidth
 						// savings while keeping 4 byte alignment
 						// savings while keeping 4 byte alignment

+ 2 - 2
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -3349,7 +3349,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
 	}
 	}
 
 
 	//bool has_morph = p_blend_shapes.size();
 	//bool has_morph = p_blend_shapes.size();
-	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream");
+	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream") && !(p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
 
 
 	Surface::Attrib attribs[VS::ARRAY_MAX];
 	Surface::Attrib attribs[VS::ARRAY_MAX];
 
 
@@ -3424,7 +3424,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
 			case VS::ARRAY_TANGENT: {
 			case VS::ARRAY_TANGENT: {
 				if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 					attribs[i].enabled = false;
 					attribs[i].enabled = false;
-					if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
+					if (p_format & VS::ARRAY_COMPRESS_TANGENT && p_format & VS::ARRAY_COMPRESS_NORMAL) {
 						// normal and tangent will each be oct16 (2 bytes each)
 						// normal and tangent will each be oct16 (2 bytes each)
 						// pack into single vec4<GL_BYTE> for memory bandwidth
 						// pack into single vec4<GL_BYTE> for memory bandwidth
 						// savings while keeping 4 byte alignment
 						// savings while keeping 4 byte alignment

+ 8 - 2
scene/3d/mesh_instance.cpp

@@ -414,7 +414,10 @@ void MeshInstance::_update_skinning() {
 		const int index_count_write = software_skinning_mesh->surface_get_array_index_len(surface_index);
 		const int index_count_write = software_skinning_mesh->surface_get_array_index_len(surface_index);
 
 
 		uint32_t array_offsets_write[Mesh::ARRAY_MAX];
 		uint32_t array_offsets_write[Mesh::ARRAY_MAX];
-		const uint32_t stride_write = visual_server->mesh_surface_make_offsets_from_format(format_write, vertex_count_write, index_count_write, array_offsets_write);
+		uint32_t array_strides_write[Mesh::ARRAY_MAX];
+		visual_server->mesh_surface_make_offsets_from_format(format_write, vertex_count_write, index_count_write, array_offsets_write, array_strides_write);
+		ERR_FAIL_COND(array_strides_write[Mesh::ARRAY_VERTEX] != array_strides_write[Mesh::ARRAY_NORMAL])
+		const uint32_t stride_write = array_strides_write[Mesh::ARRAY_VERTEX];
 		const uint32_t offset_vertices_write = array_offsets_write[Mesh::ARRAY_VERTEX];
 		const uint32_t offset_vertices_write = array_offsets_write[Mesh::ARRAY_VERTEX];
 		const uint32_t offset_normals_write = array_offsets_write[Mesh::ARRAY_NORMAL];
 		const uint32_t offset_normals_write = array_offsets_write[Mesh::ARRAY_NORMAL];
 		const uint32_t offset_tangents_write = array_offsets_write[Mesh::ARRAY_TANGENT];
 		const uint32_t offset_tangents_write = array_offsets_write[Mesh::ARRAY_TANGENT];
@@ -433,7 +436,10 @@ void MeshInstance::_update_skinning() {
 		ERR_CONTINUE(vertex_count != vertex_count_write);
 		ERR_CONTINUE(vertex_count != vertex_count_write);
 
 
 		uint32_t array_offsets[Mesh::ARRAY_MAX];
 		uint32_t array_offsets[Mesh::ARRAY_MAX];
-		const uint32_t stride = visual_server->mesh_surface_make_offsets_from_format(format_read, vertex_count, index_count, array_offsets);
+		uint32_t array_strides[Mesh::ARRAY_MAX];
+		visual_server->mesh_surface_make_offsets_from_format(format_read, vertex_count, index_count, array_offsets, array_strides);
+		ERR_FAIL_COND(array_strides[Mesh::ARRAY_VERTEX] != array_strides[Mesh::ARRAY_NORMAL])
+		const uint32_t stride = array_strides[Mesh::ARRAY_VERTEX];
 		const uint32_t offset_vertices = array_offsets[Mesh::ARRAY_VERTEX];
 		const uint32_t offset_vertices = array_offsets[Mesh::ARRAY_VERTEX];
 		const uint32_t offset_normals = array_offsets[Mesh::ARRAY_NORMAL];
 		const uint32_t offset_normals = array_offsets[Mesh::ARRAY_NORMAL];
 		const uint32_t offset_tangents = array_offsets[Mesh::ARRAY_TANGENT];
 		const uint32_t offset_tangents = array_offsets[Mesh::ARRAY_TANGENT];

+ 4 - 1
scene/3d/soft_body.cpp

@@ -52,9 +52,12 @@ void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) {
 	const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface);
 	const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface);
 	const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface);
 	const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface);
 	uint32_t surface_offsets[VS::ARRAY_MAX];
 	uint32_t surface_offsets[VS::ARRAY_MAX];
+	uint32_t surface_strides[VS::ARRAY_MAX];
 
 
 	buffer = VS::get_singleton()->mesh_surface_get_array(mesh, surface);
 	buffer = VS::get_singleton()->mesh_surface_get_array(mesh, surface);
-	stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets);
+	VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets, surface_strides);
+	ERR_FAIL_COND(surface_strides[VS::ARRAY_VERTEX] != surface_strides[VS::ARRAY_NORMAL]);
+	stride = surface_strides[VS::ARRAY_VERTEX];
 	offset_vertices = surface_offsets[VS::ARRAY_VERTEX];
 	offset_vertices = surface_offsets[VS::ARRAY_VERTEX];
 	offset_normal = surface_offsets[VS::ARRAY_NORMAL];
 	offset_normal = surface_offsets[VS::ARRAY_NORMAL];
 }
 }

+ 14 - 12
scene/3d/sprite_3d.cpp

@@ -404,13 +404,15 @@ SpriteBase3D::SpriteBase3D() {
 	mesh_array[VS::ARRAY_COLOR] = mesh_colors;
 	mesh_array[VS::ARRAY_COLOR] = mesh_colors;
 	mesh_array[VS::ARRAY_TEX_UV] = mesh_uvs;
 	mesh_array[VS::ARRAY_TEX_UV] = mesh_uvs;
 
 
-	VS::get_singleton()->mesh_add_surface_from_arrays(mesh, VS::PRIMITIVE_TRIANGLE_FAN, mesh_array, Array(), (VS::ARRAY_COMPRESS_DEFAULT & ~VS::ARRAY_COMPRESS_TEX_UV) & ~VS::ARRAY_COMPRESS_COLOR);
+	uint32_t compress_format = (VS::ARRAY_COMPRESS_DEFAULT & ~VS::ARRAY_COMPRESS_TEX_UV) & ~VS::ARRAY_COMPRESS_COLOR;
+	compress_format |= VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
+	VS::get_singleton()->mesh_add_surface_from_arrays(mesh, VS::PRIMITIVE_TRIANGLE_FAN, mesh_array, Array(), compress_format);
 	const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, 0);
 	const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, 0);
 	const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
 	const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
 
 
 	mesh_surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, 0);
 	mesh_surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, 0);
 	mesh_buffer = VS::get_singleton()->mesh_surface_get_array(mesh, 0);
 	mesh_buffer = VS::get_singleton()->mesh_surface_get_array(mesh, 0);
-	mesh_stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(mesh_surface_format, surface_vertex_len, surface_index_len, mesh_surface_offsets);
+	VS::get_singleton()->mesh_surface_make_offsets_from_format(mesh_surface_format, surface_vertex_len, surface_index_len, mesh_surface_offsets, mesh_stride);
 	set_base(mesh);
 	set_base(mesh);
 }
 }
 
 
@@ -558,13 +560,13 @@ void Sprite3D::_draw() {
 		}
 		}
 
 
 		float v_uv[2] = { uvs[i].x, uvs[i].y };
 		float v_uv[2] = { uvs[i].x, uvs[i].y };
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TEX_UV]], v_uv, 8);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_TEX_UV] + mesh_surface_offsets[VS::ARRAY_TEX_UV]], v_uv, 8);
 
 
 		float v_vertex[3] = { vtx.x, vtx.y, vtx.z };
 		float v_vertex[3] = { vtx.x, vtx.y, vtx.z };
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_NORMAL]], v_normal, 2);
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TANGENT]], v_tangent, 2);
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_COLOR]], color.components, 4 * 4);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_VERTEX] + mesh_surface_offsets[VS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_NORMAL] + mesh_surface_offsets[VS::ARRAY_NORMAL]], v_normal, 2);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_TANGENT] + mesh_surface_offsets[VS::ARRAY_TANGENT]], v_tangent, 2);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_COLOR] + mesh_surface_offsets[VS::ARRAY_COLOR]], color.components, 4 * 4);
 	}
 	}
 
 
 	write_buffer.release();
 	write_buffer.release();
@@ -903,13 +905,13 @@ void AnimatedSprite3D::_draw() {
 		}
 		}
 
 
 		float v_uv[2] = { uvs[i].x, uvs[i].y };
 		float v_uv[2] = { uvs[i].x, uvs[i].y };
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TEX_UV]], v_uv, 8);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_TEX_UV] + mesh_surface_offsets[VS::ARRAY_TEX_UV]], v_uv, 8);
 
 
 		float v_vertex[3] = { vtx.x, vtx.y, vtx.z };
 		float v_vertex[3] = { vtx.x, vtx.y, vtx.z };
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_NORMAL]], v_normal, 2);
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TANGENT]], v_tangent, 2);
-		memcpy(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_COLOR]], color.components, 4 * 4);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_VERTEX] + mesh_surface_offsets[VS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_NORMAL] + mesh_surface_offsets[VS::ARRAY_NORMAL]], v_normal, 2);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_TANGENT] + mesh_surface_offsets[VS::ARRAY_TANGENT]], v_tangent, 2);
+		memcpy(&write_buffer[i * mesh_stride[VS::ARRAY_COLOR] + mesh_surface_offsets[VS::ARRAY_COLOR]], color.components, 4 * 4);
 	}
 	}
 
 
 	write_buffer.release();
 	write_buffer.release();

+ 1 - 1
scene/3d/sprite_3d.h

@@ -97,7 +97,7 @@ protected:
 
 
 	uint32_t mesh_surface_offsets[VS::ARRAY_MAX];
 	uint32_t mesh_surface_offsets[VS::ARRAY_MAX];
 	PoolByteArray mesh_buffer;
 	PoolByteArray mesh_buffer;
-	uint32_t mesh_stride;
+	uint32_t mesh_stride[VS::ARRAY_MAX];
 	uint32_t mesh_surface_format;
 	uint32_t mesh_surface_format;
 
 
 	void _queue_update();
 	void _queue_update();

+ 113 - 41
servers/visual_server.cpp

@@ -844,17 +844,24 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
 
 
 uint32_t VisualServer::mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const {
 uint32_t VisualServer::mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const {
 	uint32_t offsets[ARRAY_MAX];
 	uint32_t offsets[ARRAY_MAX];
-	mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets);
+	uint32_t strides[ARRAY_MAX];
+	mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets, strides);
 	return offsets[p_array_index];
 	return offsets[p_array_index];
 }
 }
 
 
-uint32_t VisualServer::mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const {
+uint32_t VisualServer::mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const {
 	uint32_t offsets[ARRAY_MAX];
 	uint32_t offsets[ARRAY_MAX];
-	return mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets);
+	uint32_t strides[ARRAY_MAX];
+	mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets, strides);
+	return strides[p_array_index];
 }
 }
 
 
-uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const {
-	int total_elem_size = 0;
+void VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets, uint32_t *r_strides) const {
+	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream") && !(p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
+
+	int attributes_base_offset = 0;
+	int attributes_stride = 0;
+	int positions_stride = 0;
 
 
 	for (int i = 0; i < VS::ARRAY_MAX; i++) {
 	for (int i = 0; i < VS::ARRAY_MAX; i++) {
 		r_offsets[i] = 0; //reset
 		r_offsets[i] = 0; //reset
@@ -883,6 +890,14 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 					elem_size = 8;
 					elem_size = 8;
 				}
 				}
 
 
+				r_offsets[i] = 0;
+				positions_stride = elem_size;
+				if (use_split_stream) {
+					attributes_base_offset = elem_size * p_vertex_len;
+				} else {
+					attributes_base_offset = elem_size;
+				}
+
 			} break;
 			} break;
 			case VS::ARRAY_NORMAL: {
 			case VS::ARRAY_NORMAL: {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
@@ -901,12 +916,14 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 						elem_size = sizeof(float) * 3;
 						elem_size = sizeof(float) * 3;
 					}
 					}
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 
 
 			case VS::ARRAY_TANGENT: {
 			case VS::ARRAY_TANGENT: {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
-					if (p_format & ARRAY_COMPRESS_TANGENT) {
+					if (p_format & ARRAY_COMPRESS_TANGENT && (p_format & ARRAY_FORMAT_NORMAL) && (p_format & ARRAY_COMPRESS_NORMAL)) {
 						elem_size = sizeof(uint8_t) * 2;
 						elem_size = sizeof(uint8_t) * 2;
 					} else {
 					} else {
 						elem_size = sizeof(uint16_t) * 2;
 						elem_size = sizeof(uint16_t) * 2;
@@ -918,6 +935,8 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 						elem_size = sizeof(float) * 4;
 						elem_size = sizeof(float) * 4;
 					}
 					}
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_COLOR: {
 			case VS::ARRAY_COLOR: {
@@ -926,6 +945,9 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 				} else {
 				} else {
 					elem_size = sizeof(float) * 4;
 					elem_size = sizeof(float) * 4;
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
+
 			} break;
 			} break;
 			case VS::ARRAY_TEX_UV: {
 			case VS::ARRAY_TEX_UV: {
 				if (p_format & ARRAY_COMPRESS_TEX_UV) {
 				if (p_format & ARRAY_COMPRESS_TEX_UV) {
@@ -933,6 +955,8 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 				} else {
 				} else {
 					elem_size = sizeof(float) * 2;
 					elem_size = sizeof(float) * 2;
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 
 
@@ -942,6 +966,8 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 				} else {
 				} else {
 					elem_size = sizeof(float) * 2;
 					elem_size = sizeof(float) * 2;
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_WEIGHTS: {
 			case VS::ARRAY_WEIGHTS: {
@@ -950,6 +976,8 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 				} else {
 				} else {
 					elem_size = sizeof(float) * 4;
 					elem_size = sizeof(float) * 4;
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_BONES: {
 			case VS::ARRAY_BONES: {
@@ -958,6 +986,8 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 				} else {
 				} else {
 					elem_size = sizeof(uint32_t);
 					elem_size = sizeof(uint32_t);
 				}
 				}
+				r_offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_INDEX: {
 			case VS::ARRAY_INDEX: {
@@ -976,21 +1006,28 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
 				continue;
 				continue;
 			}
 			}
 			default: {
 			default: {
-				ERR_FAIL_V(0);
+				ERR_FAIL();
 			}
 			}
 		}
 		}
+	}
 
 
-		r_offsets[i] = total_elem_size;
-		total_elem_size += elem_size;
+	if (use_split_stream) {
+		r_strides[VS::ARRAY_VERTEX] = positions_stride;
+		for (int i = 1; i < VS::ARRAY_MAX - 1; i++) {
+			r_strides[i] = attributes_stride;
+		}
+	} else {
+		for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
+			r_strides[i] = positions_stride + attributes_stride;
+		}
 	}
 	}
-	return total_elem_size;
 }
 }
 
 
 void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_compress_format) {
 void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_compress_format) {
 	ERR_FAIL_INDEX(p_primitive, VS::PRIMITIVE_MAX);
 	ERR_FAIL_INDEX(p_primitive, VS::PRIMITIVE_MAX);
 	ERR_FAIL_COND(p_arrays.size() != VS::ARRAY_MAX);
 	ERR_FAIL_COND(p_arrays.size() != VS::ARRAY_MAX);
 
 
-	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream");
+	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream") && !(p_compress_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
 
 
 	uint32_t format = 0;
 	uint32_t format = 0;
 
 
@@ -1116,7 +1153,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
 
 
 			case VS::ARRAY_TANGENT: {
 			case VS::ARRAY_TANGENT: {
 				if (p_compress_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_compress_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
-					if (p_compress_format & ARRAY_COMPRESS_TANGENT) {
+					if (p_compress_format & ARRAY_COMPRESS_TANGENT && (format & ARRAY_FORMAT_NORMAL) && (p_compress_format & ARRAY_COMPRESS_NORMAL)) {
 						elem_size = sizeof(uint8_t) * 2;
 						elem_size = sizeof(uint8_t) * 2;
 					} else {
 					} else {
 						elem_size = sizeof(uint16_t) * 2;
 						elem_size = sizeof(uint16_t) * 2;
@@ -1266,9 +1303,14 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
 }
 }
 
 
 Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_t> p_vertex_data, int p_vertex_len, PoolVector<uint8_t> p_index_data, int p_index_len) const {
 Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_t> p_vertex_data, int p_vertex_len, PoolVector<uint8_t> p_index_data, int p_index_len) const {
+	bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream") && !(p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
+
 	uint32_t offsets[ARRAY_MAX];
 	uint32_t offsets[ARRAY_MAX];
+	uint32_t strides[VS::ARRAY_MAX];
 
 
-	int total_elem_size = 0;
+	int attributes_base_offset = 0;
+	int attributes_stride = 0;
+	int positions_stride = 0;
 
 
 	for (int i = 0; i < VS::ARRAY_MAX; i++) {
 	for (int i = 0; i < VS::ARRAY_MAX; i++) {
 		offsets[i] = 0; //reset
 		offsets[i] = 0; //reset
@@ -1278,7 +1320,6 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 		}
 		}
 
 
 		int elem_size = 0;
 		int elem_size = 0;
-
 		switch (i) {
 		switch (i) {
 			case VS::ARRAY_VERTEX: {
 			case VS::ARRAY_VERTEX: {
 				if (p_format & ARRAY_FLAG_USE_2D_VERTICES) {
 				if (p_format & ARRAY_FLAG_USE_2D_VERTICES) {
@@ -1297,6 +1338,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					elem_size = 8;
 					elem_size = 8;
 				}
 				}
 
 
+				offsets[i] = 0;
+				positions_stride = elem_size;
+				if (use_split_stream) {
+					attributes_base_offset = elem_size * p_vertex_len;
+				} else {
+					attributes_base_offset = elem_size;
+				}
+
 			} break;
 			} break;
 			case VS::ARRAY_NORMAL: {
 			case VS::ARRAY_NORMAL: {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
@@ -1315,12 +1364,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						elem_size = sizeof(float) * 3;
 						elem_size = sizeof(float) * 3;
 					}
 					}
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 
 
 			case VS::ARRAY_TANGENT: {
 			case VS::ARRAY_TANGENT: {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
 				if (p_format & ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
-					if (p_format & ARRAY_COMPRESS_TANGENT) {
+					if (p_format & ARRAY_COMPRESS_TANGENT && (p_format & ARRAY_FORMAT_NORMAL) && (p_format & ARRAY_COMPRESS_NORMAL)) {
 						elem_size = sizeof(uint8_t) * 2;
 						elem_size = sizeof(uint8_t) * 2;
 					} else {
 					} else {
 						elem_size = sizeof(uint16_t) * 2;
 						elem_size = sizeof(uint16_t) * 2;
@@ -1332,6 +1383,8 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						elem_size = sizeof(float) * 4;
 						elem_size = sizeof(float) * 4;
 					}
 					}
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_COLOR: {
 			case VS::ARRAY_COLOR: {
@@ -1340,6 +1393,9 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 				} else {
 				} else {
 					elem_size = sizeof(float) * 4;
 					elem_size = sizeof(float) * 4;
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
+
 			} break;
 			} break;
 			case VS::ARRAY_TEX_UV: {
 			case VS::ARRAY_TEX_UV: {
 				if (p_format & ARRAY_COMPRESS_TEX_UV) {
 				if (p_format & ARRAY_COMPRESS_TEX_UV) {
@@ -1347,6 +1403,8 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 				} else {
 				} else {
 					elem_size = sizeof(float) * 2;
 					elem_size = sizeof(float) * 2;
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 
 
@@ -1356,6 +1414,8 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 				} else {
 				} else {
 					elem_size = sizeof(float) * 2;
 					elem_size = sizeof(float) * 2;
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_WEIGHTS: {
 			case VS::ARRAY_WEIGHTS: {
@@ -1364,6 +1424,8 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 				} else {
 				} else {
 					elem_size = sizeof(float) * 4;
 					elem_size = sizeof(float) * 4;
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_BONES: {
 			case VS::ARRAY_BONES: {
@@ -1372,6 +1434,8 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 				} else {
 				} else {
 					elem_size = sizeof(uint32_t);
 					elem_size = sizeof(uint32_t);
 				}
 				}
+				offsets[i] = attributes_base_offset + attributes_stride;
+				attributes_stride += elem_size;
 
 
 			} break;
 			} break;
 			case VS::ARRAY_INDEX: {
 			case VS::ARRAY_INDEX: {
@@ -1393,9 +1457,17 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 				ERR_FAIL_V(Array());
 				ERR_FAIL_V(Array());
 			}
 			}
 		}
 		}
+	}
 
 
-		offsets[i] = total_elem_size;
-		total_elem_size += elem_size;
+	if (use_split_stream) {
+		strides[VS::ARRAY_VERTEX] = positions_stride;
+		for (int i = 1; i < VS::ARRAY_MAX - 1; i++) {
+			strides[i] = attributes_stride;
+		}
+	} else {
+		for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
+			strides[i] = positions_stride + attributes_stride;
+		}
 	}
 	}
 
 
 	Array ret;
 	Array ret;
@@ -1418,14 +1490,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<Vector2>::Write w = arr_2d.write();
 						PoolVector<Vector2>::Write w = arr_2d.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+							const uint16_t *v = (const uint16_t *)&r[j * strides[i] + offsets[i]];
 							w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
 							w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
 						}
 						}
 					} else {
 					} else {
 						PoolVector<Vector2>::Write w = arr_2d.write();
 						PoolVector<Vector2>::Write w = arr_2d.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+							const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 							w[j] = Vector2(v[0], v[1]);
 							w[j] = Vector2(v[0], v[1]);
 						}
 						}
 					}
 					}
@@ -1439,14 +1511,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<Vector3>::Write w = arr_3d.write();
 						PoolVector<Vector3>::Write w = arr_3d.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+							const uint16_t *v = (const uint16_t *)&r[j * strides[i] + offsets[i]];
 							w[j] = Vector3(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]), Math::halfptr_to_float(&v[2]));
 							w[j] = Vector3(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]), Math::halfptr_to_float(&v[2]));
 						}
 						}
 					} else {
 					} else {
 						PoolVector<Vector3>::Write w = arr_3d.write();
 						PoolVector<Vector3>::Write w = arr_3d.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+							const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 							w[j] = Vector3(v[0], v[1], v[2]);
 							w[j] = Vector3(v[0], v[1], v[2]);
 						}
 						}
 					}
 					}
@@ -1464,7 +1536,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<Vector3>::Write w = arr.write();
 						PoolVector<Vector3>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const int8_t *n = (const int8_t *)&r[j * total_elem_size + offsets[i]];
+							const int8_t *n = (const int8_t *)&r[j * strides[i] + offsets[i]];
 							Vector2 enc(n[0] / 127.0f, n[1] / 127.0f);
 							Vector2 enc(n[0] / 127.0f, n[1] / 127.0f);
 
 
 							w[j] = oct_to_norm(enc);
 							w[j] = oct_to_norm(enc);
@@ -1473,7 +1545,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<Vector3>::Write w = arr.write();
 						PoolVector<Vector3>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const int16_t *n = (const int16_t *)&r[j * total_elem_size + offsets[i]];
+							const int16_t *n = (const int16_t *)&r[j * strides[i] + offsets[i]];
 							Vector2 enc(n[0] / 32767.0f, n[1] / 32767.0f);
 							Vector2 enc(n[0] / 32767.0f, n[1] / 32767.0f);
 
 
 							w[j] = oct_to_norm(enc);
 							w[j] = oct_to_norm(enc);
@@ -1485,14 +1557,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						const float multiplier = 1.f / 127.f;
 						const float multiplier = 1.f / 127.f;
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]];
+							const int8_t *v = (const int8_t *)&r[j * strides[i] + offsets[i]];
 							w[j] = Vector3(float(v[0]) * multiplier, float(v[1]) * multiplier, float(v[2]) * multiplier);
 							w[j] = Vector3(float(v[0]) * multiplier, float(v[1]) * multiplier, float(v[2]) * multiplier);
 						}
 						}
 					} else {
 					} else {
 						PoolVector<Vector3>::Write w = arr.write();
 						PoolVector<Vector3>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+							const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 							w[j] = Vector3(v[0], v[1], v[2]);
 							w[j] = Vector3(v[0], v[1], v[2]);
 						}
 						}
 					}
 					}
@@ -1511,7 +1583,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<float>::Write w = arr.write();
 						PoolVector<float>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const int8_t *t = (const int8_t *)&r[j * total_elem_size + offsets[i]];
+							const int8_t *t = (const int8_t *)&r[j * strides[i] + offsets[i]];
 							Vector2 enc(t[0] / 127.0f, t[1] / 127.0f);
 							Vector2 enc(t[0] / 127.0f, t[1] / 127.0f);
 							Vector3 dec = oct_to_tangent(enc, &w[j * 4 + 3]);
 							Vector3 dec = oct_to_tangent(enc, &w[j * 4 + 3]);
 
 
@@ -1523,7 +1595,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<float>::Write w = arr.write();
 						PoolVector<float>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const int16_t *t = (const int16_t *)&r[j * total_elem_size + offsets[i]];
+							const int16_t *t = (const int16_t *)&r[j * strides[i] + offsets[i]];
 							Vector2 enc(t[0] / 32767.0f, t[1] / 32767.0f);
 							Vector2 enc(t[0] / 32767.0f, t[1] / 32767.0f);
 							Vector3 dec = oct_to_tangent(enc, &w[j * 4 + 3]);
 							Vector3 dec = oct_to_tangent(enc, &w[j * 4 + 3]);
 
 
@@ -1537,7 +1609,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<float>::Write w = arr.write();
 						PoolVector<float>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]];
+							const int8_t *v = (const int8_t *)&r[j * strides[i] + offsets[i]];
 							for (int k = 0; k < 4; k++) {
 							for (int k = 0; k < 4; k++) {
 								w[j * 4 + k] = float(v[k] / 127.0);
 								w[j * 4 + k] = float(v[k] / 127.0);
 							}
 							}
@@ -1546,7 +1618,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 						PoolVector<float>::Write w = arr.write();
 						PoolVector<float>::Write w = arr.write();
 
 
 						for (int j = 0; j < p_vertex_len; j++) {
 						for (int j = 0; j < p_vertex_len; j++) {
-							const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+							const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 							for (int k = 0; k < 4; k++) {
 							for (int k = 0; k < 4; k++) {
 								w[j * 4 + k] = v[k];
 								w[j * 4 + k] = v[k];
 							}
 							}
@@ -1565,14 +1637,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<Color>::Write w = arr.write();
 					PoolVector<Color>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const uint8_t *v = (const uint8_t *)&r[j * total_elem_size + offsets[i]];
+						const uint8_t *v = (const uint8_t *)&r[j * strides[i] + offsets[i]];
 						w[j] = Color(float(v[0] / 255.0), float(v[1] / 255.0), float(v[2] / 255.0), float(v[3] / 255.0));
 						w[j] = Color(float(v[0] / 255.0), float(v[1] / 255.0), float(v[2] / 255.0), float(v[3] / 255.0));
 					}
 					}
 				} else {
 				} else {
 					PoolVector<Color>::Write w = arr.write();
 					PoolVector<Color>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+						const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 						w[j] = Color(v[0], v[1], v[2], v[3]);
 						w[j] = Color(v[0], v[1], v[2], v[3]);
 					}
 					}
 				}
 				}
@@ -1587,14 +1659,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<Vector2>::Write w = arr.write();
 					PoolVector<Vector2>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+						const uint16_t *v = (const uint16_t *)&r[j * strides[i] + offsets[i]];
 						w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
 						w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
 					}
 					}
 				} else {
 				} else {
 					PoolVector<Vector2>::Write w = arr.write();
 					PoolVector<Vector2>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+						const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 						w[j] = Vector2(v[0], v[1]);
 						w[j] = Vector2(v[0], v[1]);
 					}
 					}
 				}
 				}
@@ -1610,14 +1682,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<Vector2>::Write w = arr.write();
 					PoolVector<Vector2>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+						const uint16_t *v = (const uint16_t *)&r[j * strides[i] + offsets[i]];
 						w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
 						w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
 					}
 					}
 				} else {
 				} else {
 					PoolVector<Vector2>::Write w = arr.write();
 					PoolVector<Vector2>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+						const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 						w[j] = Vector2(v[0], v[1]);
 						w[j] = Vector2(v[0], v[1]);
 					}
 					}
 				}
 				}
@@ -1632,7 +1704,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<float>::Write w = arr.write();
 					PoolVector<float>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+						const uint16_t *v = (const uint16_t *)&r[j * strides[i] + offsets[i]];
 						for (int k = 0; k < 4; k++) {
 						for (int k = 0; k < 4; k++) {
 							w[j * 4 + k] = float(v[k] / 65535.0);
 							w[j * 4 + k] = float(v[k] / 65535.0);
 						}
 						}
@@ -1641,7 +1713,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<float>::Write w = arr.write();
 					PoolVector<float>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
+						const float *v = (const float *)&r[j * strides[i] + offsets[i]];
 						for (int k = 0; k < 4; k++) {
 						for (int k = 0; k < 4; k++) {
 							w[j * 4 + k] = v[k];
 							w[j * 4 + k] = v[k];
 						}
 						}
@@ -1658,7 +1730,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<int>::Write w = arr.write();
 					PoolVector<int>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+						const uint16_t *v = (const uint16_t *)&r[j * strides[i] + offsets[i]];
 						for (int k = 0; k < 4; k++) {
 						for (int k = 0; k < 4; k++) {
 							w[j * 4 + k] = v[k];
 							w[j * 4 + k] = v[k];
 						}
 						}
@@ -1667,7 +1739,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
 					PoolVector<int>::Write w = arr.write();
 					PoolVector<int>::Write w = arr.write();
 
 
 					for (int j = 0; j < p_vertex_len; j++) {
 					for (int j = 0; j < p_vertex_len; j++) {
-						const uint8_t *v = (const uint8_t *)&r[j * total_elem_size + offsets[i]];
+						const uint8_t *v = (const uint8_t *)&r[j * strides[i] + offsets[i]];
 						for (int k = 0; k < 4; k++) {
 						for (int k = 0; k < 4; k++) {
 							w[j * 4 + k] = v[k];
 							w[j * 4 + k] = v[k];
 						}
 						}
@@ -1809,7 +1881,7 @@ void VisualServer::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create);
 	ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create);
 	ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_len", "index_len", "array_index"), &VisualServer::mesh_surface_get_format_offset);
 	ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_len", "index_len", "array_index"), &VisualServer::mesh_surface_get_format_offset);
-	ClassDB::bind_method(D_METHOD("mesh_surface_get_format_stride", "format", "vertex_len", "index_len"), &VisualServer::mesh_surface_get_format_stride);
+	ClassDB::bind_method(D_METHOD("mesh_surface_get_format_stride", "format", "vertex_len", "index_len", "array_index"), &VisualServer::mesh_surface_get_format_stride);
 	ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
 	ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
 	ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count);
 	ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count);
 	ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count);
 	ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count);
@@ -2561,7 +2633,7 @@ VisualServer::VisualServer() {
 	GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx", false);
 	GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx", false);
 	GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true);
 	GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true);
 
 
-	GLOBAL_DEF("rendering/mesh_storage/split_stream", false);
+	GLOBAL_DEF_RST("rendering/mesh_storage/split_stream", false);
 
 
 	GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
 	GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
 	GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
 	GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");

+ 2 - 2
servers/visual_server.h

@@ -287,9 +287,9 @@ public:
 	virtual RID mesh_create() = 0;
 	virtual RID mesh_create() = 0;
 
 
 	virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const;
 	virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const;
-	virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const;
+	virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const;
 	/// Returns stride
 	/// Returns stride
-	virtual uint32_t mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const;
+	virtual void mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets, uint32_t *r_strides) const;
 	virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
 	virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
 	virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t>> &p_blend_shapes = Vector<PoolVector<uint8_t>>(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0;
 	virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t>> &p_blend_shapes = Vector<PoolVector<uint8_t>>(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0;