diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index aebe194033b8..8ea56998807d 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1187,6 +1187,9 @@
The default compression level for lossless WebP. Higher levels result in smaller files at the cost of compression speed. Decompression speed is mostly unaffected by the compression level. Supported values are 0 to 9. Note that compression levels above 6 are very slow and offer very little savings.
+
+ On import, mesh vertex data will be split into two streams within a single vertex buffer, one for position data and the other for interleaved attributes data. Recommended to be enabled if targeting mobile devices. Requires manual reimport of meshes after toggling.
+
If [code]true[/code], allocates the main framebuffer with high dynamic range. High dynamic range allows the use of [Color] values greater than 1.
[b]Note:[/b] Only available on the GLES3 backend.
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 0776902b1e5b..17a59c0fdabf 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -2240,10 +2240,13 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
//bool has_morph = p_blend_shapes.size();
+ bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream");
Surface::Attrib attribs[VS::ARRAY_MAX];
- int stride = 0;
+ int attributes_base_offset = 0;
+ int attributes_stride = 0;
+ int positions_stride = 0;
bool uses_half_float = false;
for (int i = 0; i < VS::ARRAY_MAX; i++) {
@@ -2256,7 +2259,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
attribs[i].enabled = true;
- attribs[i].offset = stride;
+ attribs[i].offset = attributes_base_offset + attributes_stride;
attribs[i].integer = false;
switch (i) {
@@ -2269,26 +2272,31 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
attribs[i].type = _GL_HALF_FLOAT_OES;
- stride += attribs[i].size * 2;
- uses_half_float = true;
+ positions_stride += attribs[i].size * 2;
} else {
attribs[i].type = GL_FLOAT;
- stride += attribs[i].size * 4;
+ positions_stride += attribs[i].size * 4;
}
attribs[i].normalized = GL_FALSE;
+ if (use_split_stream) {
+ attributes_base_offset = positions_stride * p_vertex_count;
+ } else {
+ attributes_base_offset = positions_stride;
+ }
+
} break;
case VS::ARRAY_NORMAL: {
attribs[i].size = 3;
if (p_format & VS::ARRAY_COMPRESS_NORMAL) {
attribs[i].type = GL_BYTE;
- stride += 4; //pad extra byte
+ attributes_stride += 4; //pad extra byte
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 12;
+ attributes_stride += 12;
attribs[i].normalized = GL_FALSE;
}
@@ -2298,11 +2306,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
attribs[i].type = GL_BYTE;
- stride += 4;
+ attributes_stride += 4;
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 16;
+ attributes_stride += 16;
attribs[i].normalized = GL_FALSE;
}
@@ -2312,11 +2320,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_COLOR) {
attribs[i].type = GL_UNSIGNED_BYTE;
- stride += 4;
+ attributes_stride += 4;
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 16;
+ attributes_stride += 16;
attribs[i].normalized = GL_FALSE;
}
@@ -2326,11 +2334,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
attribs[i].type = _GL_HALF_FLOAT_OES;
- stride += 4;
+ attributes_stride += 4;
uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
- stride += 8;
+ attributes_stride += 8;
}
attribs[i].normalized = GL_FALSE;
@@ -2341,11 +2349,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
attribs[i].type = _GL_HALF_FLOAT_OES;
- stride += 4;
+ attributes_stride += 4;
uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
- stride += 8;
+ attributes_stride += 8;
}
attribs[i].normalized = GL_FALSE;
@@ -2355,10 +2363,10 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) {
attribs[i].type = GL_UNSIGNED_SHORT;
- stride += 8;
+ attributes_stride += 8;
} else {
attribs[i].type = GL_UNSIGNED_BYTE;
- stride += 4;
+ attributes_stride += 4;
}
attribs[i].normalized = GL_FALSE;
@@ -2370,11 +2378,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) {
attribs[i].type = GL_UNSIGNED_SHORT;
- stride += 8;
+ attributes_stride += 8;
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 16;
+ attributes_stride += 16;
attribs[i].normalized = GL_FALSE;
}
@@ -2396,13 +2404,21 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
}
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
- attribs[i].stride = stride;
+ if (use_split_stream) {
+ attribs[VS::ARRAY_VERTEX].stride = positions_stride;
+ for (int i = 1; i < VS::ARRAY_MAX - 1; i++) {
+ attribs[i].stride = attributes_stride;
+ }
+ } else {
+ for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
+ attribs[i].stride = positions_stride + attributes_stride;
+ }
}
//validate sizes
PoolVector array = p_array;
+ int stride = positions_stride + attributes_stride;
int array_size = stride * p_vertex_count;
int index_array_size = 0;
if (array.size() != array_size && array.size() + p_vertex_count * 2 == array_size) {
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 9762b48b25c1..d6233db3572c 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -3349,10 +3349,13 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
//bool has_morph = p_blend_shapes.size();
+ bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream");
Surface::Attrib attribs[VS::ARRAY_MAX];
- int stride = 0;
+ int attributes_base_offset = 0;
+ int attributes_stride = 0;
+ int positions_stride = 0;
for (int i = 0; i < VS::ARRAY_MAX; i++) {
attribs[i].index = i;
@@ -3364,7 +3367,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
attribs[i].enabled = true;
- attribs[i].offset = stride;
+ attribs[i].offset = attributes_base_offset + attributes_stride;
attribs[i].integer = false;
switch (i) {
@@ -3377,25 +3380,31 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
attribs[i].type = GL_HALF_FLOAT;
- stride += attribs[i].size * 2;
+ positions_stride += attribs[i].size * 2;
} else {
attribs[i].type = GL_FLOAT;
- stride += attribs[i].size * 4;
+ positions_stride += attribs[i].size * 4;
}
attribs[i].normalized = GL_FALSE;
+ if (use_split_stream) {
+ attributes_base_offset = positions_stride * p_vertex_count;
+ } else {
+ attributes_base_offset = positions_stride;
+ }
+
} break;
case VS::ARRAY_NORMAL: {
attribs[i].size = 3;
if (p_format & VS::ARRAY_COMPRESS_NORMAL) {
attribs[i].type = GL_BYTE;
- stride += 4; //pad extra byte
+ attributes_stride += 4; //pad extra byte
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 12;
+ attributes_stride += 12;
attribs[i].normalized = GL_FALSE;
}
@@ -3405,11 +3414,11 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
attribs[i].type = GL_BYTE;
- stride += 4;
+ attributes_stride += 4;
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 16;
+ attributes_stride += 16;
attribs[i].normalized = GL_FALSE;
}
@@ -3419,11 +3428,11 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_COLOR) {
attribs[i].type = GL_UNSIGNED_BYTE;
- stride += 4;
+ attributes_stride += 4;
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 16;
+ attributes_stride += 16;
attribs[i].normalized = GL_FALSE;
}
@@ -3433,10 +3442,10 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
attribs[i].type = GL_HALF_FLOAT;
- stride += 4;
+ attributes_stride += 4;
} else {
attribs[i].type = GL_FLOAT;
- stride += 8;
+ attributes_stride += 8;
}
attribs[i].normalized = GL_FALSE;
@@ -3447,10 +3456,10 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
attribs[i].type = GL_HALF_FLOAT;
- stride += 4;
+ attributes_stride += 4;
} else {
attribs[i].type = GL_FLOAT;
- stride += 8;
+ attributes_stride += 8;
}
attribs[i].normalized = GL_FALSE;
@@ -3460,10 +3469,10 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) {
attribs[i].type = GL_UNSIGNED_SHORT;
- stride += 8;
+ attributes_stride += 8;
} else {
attribs[i].type = GL_UNSIGNED_BYTE;
- stride += 4;
+ attributes_stride += 4;
}
attribs[i].normalized = GL_FALSE;
@@ -3475,11 +3484,11 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) {
attribs[i].type = GL_UNSIGNED_SHORT;
- stride += 8;
+ attributes_stride += 8;
attribs[i].normalized = GL_TRUE;
} else {
attribs[i].type = GL_FLOAT;
- stride += 16;
+ attributes_stride += 16;
attribs[i].normalized = GL_FALSE;
}
@@ -3501,12 +3510,20 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
}
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
- attribs[i].stride = stride;
+ if (use_split_stream) {
+ attribs[VS::ARRAY_VERTEX].stride = positions_stride;
+ for (int i = 1; i < VS::ARRAY_MAX - 1; i++) {
+ attribs[i].stride = attributes_stride;
+ }
+ } else {
+ for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
+ attribs[i].stride = positions_stride + attributes_stride;
+ }
}
//validate sizes
+ int stride = positions_stride + attributes_stride;
int array_size = stride * p_vertex_count;
int index_array_size = 0;
if (array.size() != array_size && array.size() + p_vertex_count * 2 == array_size) {
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 49410bb90390..fac03115916a 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -329,7 +329,7 @@ RID VisualServer::get_white_texture() {
#define SMALL_VEC2 Vector2(0.00001, 0.00001)
#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001)
-Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector &r_vertex_array, int p_vertex_array_len, PoolVector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb) {
+Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t *p_stride, PoolVector &r_vertex_array, int p_vertex_array_len, PoolVector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb) {
PoolVector::Write vw = r_vertex_array.write();
PoolVector::Write iw;
@@ -360,7 +360,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
for (int i = 0; i < p_vertex_array_len; i++) {
uint16_t vector[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) };
- memcpy(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(uint16_t) * 2);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], vector, sizeof(uint16_t) * 2);
if (i == 0) {
aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size
@@ -373,7 +373,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
for (int i = 0; i < p_vertex_array_len; i++) {
float vector[2] = { src[i].x, src[i].y };
- memcpy(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(float) * 2);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], vector, sizeof(float) * 2);
if (i == 0) {
aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size
@@ -399,7 +399,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
for (int i = 0; i < p_vertex_array_len; i++) {
uint16_t vector[4] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y), Math::make_half_float(src[i].z), Math::make_half_float(1.0) };
- memcpy(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(uint16_t) * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], vector, sizeof(uint16_t) * 4);
if (i == 0) {
aabb = AABB(src[i], SMALL_VEC3);
@@ -412,7 +412,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
for (int i = 0; i < p_vertex_array_len; i++) {
float vector[3] = { src[i].x, src[i].y, src[i].z };
- memcpy(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(float) * 3);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], vector, sizeof(float) * 3);
if (i == 0) {
aabb = AABB(src[i], SMALL_VEC3);
@@ -446,13 +446,13 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
0,
};
- memcpy(&vw[p_offsets[ai] + i * p_stride], vector, 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], vector, 4);
}
} else {
for (int i = 0; i < p_vertex_array_len; i++) {
float vector[3] = { src[i].x, src[i].y, src[i].z };
- memcpy(&vw[p_offsets[ai] + i * p_stride], vector, 3 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], vector, 3 * 4);
}
}
@@ -477,7 +477,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
(int8_t)CLAMP(src[i * 4 + 3] * 127, -128, 127)
};
- memcpy(&vw[p_offsets[ai] + i * p_stride], xyzw, 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], xyzw, 4);
}
} else {
@@ -489,7 +489,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
src[i * 4 + 3]
};
- memcpy(&vw[p_offsets[ai] + i * p_stride], xyzw, 4 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], xyzw, 4 * 4);
}
}
@@ -512,11 +512,11 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
colors[j] = CLAMP(int((src[i][j]) * 255.0), 0, 255);
}
- memcpy(&vw[p_offsets[ai] + i * p_stride], colors, 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], colors, 4);
}
} else {
for (int i = 0; i < p_vertex_array_len; i++) {
- memcpy(&vw[p_offsets[ai] + i * p_stride], &src[i], 4 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], &src[i], 4 * 4);
}
}
@@ -535,14 +535,14 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
if (p_format & ARRAY_COMPRESS_TEX_UV) {
for (int i = 0; i < p_vertex_array_len; i++) {
uint16_t uv[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) };
- memcpy(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 2);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], uv, 2 * 2);
}
} else {
for (int i = 0; i < p_vertex_array_len; i++) {
float uv[2] = { src[i].x, src[i].y };
- memcpy(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], uv, 2 * 4);
}
}
@@ -562,14 +562,14 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
if (p_format & ARRAY_COMPRESS_TEX_UV2) {
for (int i = 0; i < p_vertex_array_len; i++) {
uint16_t uv[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) };
- memcpy(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 2);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], uv, 2 * 2);
}
} else {
for (int i = 0; i < p_vertex_array_len; i++) {
float uv[2] = { src[i].x, src[i].y };
- memcpy(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], uv, 2 * 4);
}
}
} break;
@@ -591,7 +591,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
data[j] = CLAMP(src[i * VS::ARRAY_WEIGHTS_SIZE + j] * 65535, 0, 65535);
}
- memcpy(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], data, 2 * 4);
}
} else {
for (int i = 0; i < p_vertex_array_len; i++) {
@@ -600,7 +600,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j];
}
- memcpy(&vw[p_offsets[ai] + i * p_stride], data, 4 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], data, 4 * 4);
}
}
@@ -624,7 +624,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
max_bone = MAX(data[j], max_bone);
}
- memcpy(&vw[p_offsets[ai] + i * p_stride], data, 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], data, 4);
}
} else {
@@ -635,7 +635,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
max_bone = MAX(data[j], max_bone);
}
- memcpy(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4);
+ memcpy(&vw[p_offsets[ai] + i * p_stride[ai]], data, 2 * 4);
}
}
@@ -856,6 +856,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
ERR_FAIL_INDEX(p_primitive, VS::PRIMITIVE_MAX);
ERR_FAIL_COND(p_arrays.size() != VS::ARRAY_MAX);
+ bool use_split_stream = GLOBAL_GET("rendering/mesh_storage/split_stream");
+
uint32_t format = 0;
// validation
@@ -908,8 +910,11 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
}
uint32_t offsets[VS::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++) {
offsets[i] = 0; //reset
@@ -944,6 +949,14 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
elem_size = 8;
}
+ offsets[i] = 0;
+ positions_stride = elem_size;
+ if (use_split_stream) {
+ attributes_base_offset = elem_size * array_len;
+ } else {
+ attributes_base_offset = elem_size;
+ }
+
} break;
case VS::ARRAY_NORMAL: {
if (p_compress_format & ARRAY_COMPRESS_NORMAL) {
@@ -951,6 +964,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} else {
elem_size = sizeof(float) * 3;
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
} break;
@@ -960,6 +975,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} else {
elem_size = sizeof(float) * 4;
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
} break;
case VS::ARRAY_COLOR: {
@@ -968,6 +985,9 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} else {
elem_size = sizeof(float) * 4;
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
+
} break;
case VS::ARRAY_TEX_UV: {
if (p_compress_format & ARRAY_COMPRESS_TEX_UV) {
@@ -975,6 +995,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} else {
elem_size = sizeof(float) * 2;
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
} break;
@@ -984,6 +1006,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} else {
elem_size = sizeof(float) * 2;
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
} break;
case VS::ARRAY_WEIGHTS: {
@@ -992,6 +1016,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} else {
elem_size = sizeof(float) * 4;
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
} break;
case VS::ARRAY_BONES: {
@@ -1013,6 +1039,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
p_compress_format &= ~ARRAY_FLAG_USE_16_BIT_BONES;
elem_size = sizeof(uint32_t);
}
+ offsets[i] = attributes_base_offset + attributes_stride;
+ attributes_stride += elem_size;
} break;
case VS::ARRAY_INDEX: {
@@ -1034,15 +1062,23 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
ERR_FAIL();
}
}
+ }
- 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;
+ }
}
uint32_t mask = (1 << ARRAY_MAX) - 1;
format |= (~mask) & p_compress_format; //make the full format
- int array_size = total_elem_size * array_len;
+ int array_size = (positions_stride + attributes_stride) * array_len;
PoolVector vertex_array;
vertex_array.resize(array_size);
@@ -1055,7 +1091,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
AABB aabb;
Vector bone_aabb;
- Error err = _surface_set_data(p_arrays, format, offsets, total_elem_size, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb);
+ Error err = _surface_set_data(p_arrays, format, offsets, strides, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb);
ERR_FAIL_COND_MSG(err, "Invalid array format for surface.");
Vector> blend_shape_data;
@@ -1066,7 +1102,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
PoolVector noindex;
AABB laabb;
- Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
+ Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, strides, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
aabb.merge_with(laabb);
ERR_FAIL_COND_MSG(err2 != OK, "Invalid blend shape array format for surface.");
@@ -2299,6 +2335,8 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx", false);
GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true);
+ GLOBAL_DEF("rendering/mesh_storage/split_stream", false);
+
GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
diff --git a/servers/visual_server.h b/servers/visual_server.h
index b46c5173937e..a9ea43835bee 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -60,7 +60,7 @@ class VisualServer : public Object {
RID white_texture;
RID test_material;
- Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector &r_vertex_array, int p_vertex_array_len, PoolVector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb);
+ Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t *p_stride, PoolVector &r_vertex_array, int p_vertex_array_len, PoolVector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb);
static VisualServer *(*create_func)();
static void _bind_methods();