summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp12
-rw-r--r--drivers/gles3/shaders/scene.glsl79
-rw-r--r--drivers/gles3/storage/material_storage.cpp2
-rw-r--r--drivers/gles3/storage/material_storage.h2
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp308
-rw-r--r--drivers/gles3/storage/mesh_storage.h16
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp11
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h4
9 files changed, 272 insertions, 164 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index fcd3af8d62..7fce06c133 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1383,7 +1383,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
GLuint vertex_array_gl = 0;
GLuint index_array_gl = 0;
- uint32_t input_mask = 0; // 2D meshes always use the same vertex format
+ uint64_t input_mask = 0; // 2D meshes always use the same vertex format.
if (mesh_instance.is_valid()) {
mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array_gl);
} else {
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 22bb772e4f..d359a4252f 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -2908,6 +2908,18 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, spec_constants);
+ {
+ GLES3::Mesh::Surface *s = reinterpret_cast<GLES3::Mesh::Surface *>(surf->surface);
+ if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::COMPRESSED_AABB_POSITION, s->aabb.position, shader->version, instance_variant, spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::COMPRESSED_AABB_SIZE, s->aabb.size, shader->version, instance_variant, spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::UV_SCALE, s->uv_scale, shader->version, instance_variant, spec_constants);
+ } else {
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::COMPRESSED_AABB_POSITION, Vector3(0.0, 0.0, 0.0), shader->version, instance_variant, spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::COMPRESSED_AABB_SIZE, Vector3(1.0, 1.0, 1.0), shader->version, instance_variant, spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::UV_SCALE, Vector4(0.0, 0.0, 0.0, 0.0), shader->version, instance_variant, spec_constants);
+ }
+ }
// Can be index count or vertex count
uint32_t count = 0;
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 0c1a20caed..c98b5f3ed7 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -52,8 +52,8 @@ ADDITIVE_SPOT = false
/*
from RenderingServer:
-ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit)
-ARRAY_NORMAL = 1, // RG16 octahedral compression
+ARRAY_VERTEX = 0, // RGB32F or RGBA16
+ARRAY_NORMAL = 1, // RG16 octahedral compression or RGBA16 normal + angle
ARRAY_TANGENT = 2, // RG16 octahedral compression, sign stored in sign of G
ARRAY_COLOR = 3, // RGBA8
ARRAY_TEX_UV = 4, // RG32F
@@ -68,16 +68,16 @@ ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights)
/* INPUT ATTRIBS */
-layout(location = 0) in highp vec3 vertex_attrib;
+// Always contains vertex position in XYZ, can contain tangent angle in W.
+layout(location = 0) in highp vec4 vertex_angle_attrib;
/* clang-format on */
#ifdef NORMAL_USED
-layout(location = 1) in vec2 normal_attrib;
+// Contains Normal/Axis in RG, can contain tangent in BA.
+layout(location = 1) in vec4 axis_tangent_attrib;
#endif
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec2 tangent_attrib;
-#endif
+// location 2 is unused.
#if defined(COLOR_USED)
layout(location = 3) in vec4 color_attrib;
@@ -122,6 +122,16 @@ vec3 oct_to_vec3(vec2 e) {
return normalize(v);
}
+void axis_angle_to_tbn(vec3 axis, float angle, out vec3 tangent, out vec3 binormal, out vec3 normal) {
+ float c = cos(angle);
+ float s = sin(angle);
+ vec3 omc_axis = (1.0 - c) * axis;
+ vec3 s_axis = s * axis;
+ tangent = omc_axis.xxx * axis + vec3(c, -s_axis.z, s_axis.y);
+ binormal = omc_axis.yyy * axis + vec3(s_axis.z, c, -s_axis.x);
+ normal = omc_axis.zzz * axis + vec3(-s_axis.y, s_axis.x, c);
+}
+
#ifdef USE_INSTANCING
layout(location = 12) in highp vec4 instance_xform0;
layout(location = 13) in highp vec4 instance_xform1;
@@ -228,10 +238,9 @@ multiview_data;
#endif
uniform highp mat4 world_transform;
-
-#ifdef USE_LIGHTMAP
-uniform highp vec4 lightmap_uv_rect;
-#endif
+uniform highp vec3 compressed_aabb_position;
+uniform highp vec3 compressed_aabb_size;
+uniform highp vec4 uv_scale;
/* Varyings */
@@ -248,13 +257,9 @@ out vec4 color_interp;
out vec2 uv_interp;
#endif
-#if defined(UV2_USED)
-out vec2 uv2_interp;
-#else
-#ifdef USE_LIGHTMAP
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
out vec2 uv2_interp;
#endif
-#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
out vec3 tangent_interp;
@@ -294,7 +299,7 @@ layout(std140) uniform MaterialUniforms { // ubo:3
invariant gl_Position;
void main() {
- highp vec3 vertex = vertex_attrib;
+ highp vec3 vertex = vertex_angle_attrib.xyz * compressed_aabb_size + compressed_aabb_position;
highp mat4 model_matrix = world_transform;
#ifdef USE_INSTANCING
@@ -303,15 +308,30 @@ void main() {
#endif
#ifdef NORMAL_USED
- vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
+ vec3 normal = oct_to_vec3(axis_tangent_attrib.xy * 2.0 - 1.0);
#endif
highp mat3 model_normal_matrix = mat3(model_matrix);
-#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
- vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
- float binormalf = sign(signed_tangent_attrib.y);
- vec3 binormal = normalize(cross(normal, tangent) * binormalf);
+#if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+
+ vec3 binormal;
+ float binormal_sign;
+ vec3 tangent;
+ if (axis_tangent_attrib.z > 0.0 || axis_tangent_attrib.w < 1.0) {
+ // Uncompressed format.
+ vec2 signed_tangent_attrib = axis_tangent_attrib.zw * 2.0 - 1.0;
+ tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ binormal_sign = sign(signed_tangent_attrib.y);
+ binormal = normalize(cross(normal, tangent) * binormal_sign);
+ } else {
+ // Compressed format.
+ float angle = vertex_angle_attrib.w;
+ binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller.
+ angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably.
+ vec3 axis = normal;
+ axis_angle_to_tbn(axis, angle, tangent, binormal, normal);
+ binormal *= binormal_sign;
+ }
#endif
#if defined(COLOR_USED)
@@ -326,13 +346,18 @@ void main() {
uv_interp = uv_attrib;
#endif
-#ifdef USE_LIGHTMAP
- uv2_interp = lightmap_uv_rect.zw * uv2_attrib + lightmap_uv_rect.xy;
-#else
-#if defined(UV2_USED)
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib;
#endif
+
+ if (uv_scale != vec4(0.0)) { // Compression enabled
+#ifdef UV_USED
+ uv_interp = (uv_interp - 0.5) * uv_scale.xy;
+#endif
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+ uv2_interp = (uv2_interp - 0.5) * uv_scale.zw;
#endif
+ }
#if defined(OVERRIDE_POSITION)
highp vec4 position;
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index a594813ed0..613b03e30e 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -2944,7 +2944,7 @@ void SceneShaderData::set_code(const String &p_code) {
cull_mode = Cull(cull_modei);
blend_mode = BlendMode(blend_modei);
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
- vertex_input_mask = uint32_t(uses_normal);
+ vertex_input_mask = uint64_t(uses_normal);
vertex_input_mask |= uses_tangent << 1;
vertex_input_mask |= uses_color << 2;
vertex_input_mask |= uses_uv << 3;
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 9c63c8847d..75127bb198 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -316,7 +316,7 @@ struct SceneShaderData : public ShaderData {
bool uses_bones;
bool uses_weights;
- uint32_t vertex_input_mask = 0;
+ uint64_t vertex_input_mask = 0;
uint64_t last_pass = 0;
uint32_t index = 0;
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index cc6031fa57..ae04b63cfe 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -117,34 +117,40 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
uint32_t skin_stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
- if ((p_surface.format & (1 << i))) {
+ if ((p_surface.format & (1ULL << i))) {
switch (i) {
case RS::ARRAY_VERTEX: {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ if ((p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) || (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
stride += sizeof(float) * 2;
} else {
stride += sizeof(float) * 3;
}
-
} break;
case RS::ARRAY_NORMAL: {
stride += sizeof(uint16_t) * 2;
} break;
case RS::ARRAY_TANGENT: {
- stride += sizeof(uint16_t) * 2;
-
+ if (!(p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
+ stride += sizeof(uint16_t) * 2;
+ }
} break;
case RS::ARRAY_COLOR: {
attrib_stride += sizeof(uint32_t);
} break;
case RS::ARRAY_TEX_UV: {
- attrib_stride += sizeof(float) * 2;
-
+ if (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attrib_stride += sizeof(uint16_t) * 2;
+ } else {
+ attrib_stride += sizeof(float) * 2;
+ }
} break;
case RS::ARRAY_TEX_UV2: {
- attrib_stride += sizeof(float) * 2;
-
+ if (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attrib_stride += sizeof(uint16_t) * 2;
+ } else {
+ attrib_stride += sizeof(float) * 2;
+ }
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
@@ -185,92 +191,121 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
#endif
+ uint64_t surface_version = p_surface.format & (uint64_t(RS::ARRAY_FLAG_FORMAT_VERSION_MASK) << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
+ RS::SurfaceData new_surface = p_surface;
+#ifdef DISABLE_DEPRECATED
+
+ ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION, "Surface version provided (" + itos(int(surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT)) + ") does not match current version (" + itos(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) + ")");
+
+#else
+
+ if (surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION)) {
+ RS::_fix_surface_compatibility(new_surface);
+ surface_version = new_surface.format & (uint64_t(RS::ARRAY_FLAG_FORMAT_VERSION_MASK) << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
+ ERR_FAIL_COND_MSG(surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION),
+ "Surface version provided (" +
+ itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
+ ") does not match current version (" +
+ itos((uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION) >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
+ ")");
+ }
+#endif
+
Mesh::Surface *s = memnew(Mesh::Surface);
- s->format = p_surface.format;
- s->primitive = p_surface.primitive;
+ s->format = new_surface.format;
+ s->primitive = new_surface.primitive;
- if (p_surface.vertex_data.size()) {
+ if (new_surface.vertex_data.size()) {
glGenBuffers(1, &s->vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->vertex_buffer, p_surface.vertex_data.size(), p_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh vertex buffer");
- s->vertex_buffer_size = p_surface.vertex_data.size();
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->vertex_buffer, new_surface.vertex_data.size(), new_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh vertex buffer");
+ s->vertex_buffer_size = new_surface.vertex_data.size();
}
- if (p_surface.attribute_data.size()) {
+ if (new_surface.attribute_data.size()) {
glGenBuffers(1, &s->attribute_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->attribute_buffer, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh attribute buffer");
- s->attribute_buffer_size = p_surface.attribute_data.size();
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->attribute_buffer, new_surface.attribute_data.size(), new_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh attribute buffer");
+ s->attribute_buffer_size = new_surface.attribute_data.size();
}
- if (p_surface.skin_data.size()) {
+ if (new_surface.skin_data.size()) {
glGenBuffers(1, &s->skin_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->skin_buffer, p_surface.skin_data.size(), p_surface.skin_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh skin buffer");
- s->skin_buffer_size = p_surface.skin_data.size();
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->skin_buffer, new_surface.skin_data.size(), new_surface.skin_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh skin buffer");
+ s->skin_buffer_size = new_surface.skin_data.size();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
- s->vertex_count = p_surface.vertex_count;
+ s->vertex_count = new_surface.vertex_count;
- if (p_surface.format & RS::ARRAY_FORMAT_BONES) {
+ if (new_surface.format & RS::ARRAY_FORMAT_BONES) {
mesh->has_bone_weights = true;
}
- if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
+ if (new_surface.index_count) {
+ bool is_index_16 = new_surface.vertex_count <= 65536 && new_surface.vertex_count > 0;
glGenBuffers(1, &s->index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer, new_surface.index_data.size(), new_surface.index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
- s->index_count = p_surface.index_count;
- s->index_buffer_size = p_surface.index_data.size();
+ s->index_count = new_surface.index_count;
+ s->index_buffer_size = new_surface.index_data.size();
- if (p_surface.lods.size()) {
- s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
- s->lod_count = p_surface.lods.size();
+ if (new_surface.lods.size()) {
+ s->lods = memnew_arr(Mesh::Surface::LOD, new_surface.lods.size());
+ s->lod_count = new_surface.lods.size();
- for (int i = 0; i < p_surface.lods.size(); i++) {
+ for (int i = 0; i < new_surface.lods.size(); i++) {
glGenBuffers(1, &s->lods[i].index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer, p_surface.lods[i].index_data.size(), p_surface.lods[i].index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer LOD[" + itos(i) + "]");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer, new_surface.lods[i].index_data.size(), new_surface.lods[i].index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer LOD[" + itos(i) + "]");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
- s->lods[i].edge_length = p_surface.lods[i].edge_length;
- s->lods[i].index_count = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
- s->lods[i].index_buffer_size = p_surface.lods[i].index_data.size();
+ s->lods[i].edge_length = new_surface.lods[i].edge_length;
+ s->lods[i].index_count = new_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer_size = new_surface.lods[i].index_data.size();
}
}
}
- ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+ ERR_FAIL_COND_MSG(!new_surface.index_count && !new_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
- s->aabb = p_surface.aabb;
- s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
+ s->aabb = new_surface.aabb;
+ s->bone_aabbs = new_surface.bone_aabbs; //only really useful for returning them.
- if (p_surface.skin_data.size() || mesh->blend_shape_count > 0) {
+ s->uv_scale = new_surface.uv_scale;
+
+ if (new_surface.skin_data.size() || mesh->blend_shape_count > 0) {
// Size must match the size of the vertex array.
- int size = p_surface.vertex_data.size();
+ int size = new_surface.vertex_data.size();
int vertex_size = 0;
- int stride = 0;
+ int position_stride = 0;
+ int normal_tangent_stride = 0;
int normal_offset = 0;
int tangent_offset = 0;
- if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ if ((new_surface.format & (1ULL << RS::ARRAY_VERTEX))) {
+ if (new_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
vertex_size = 2;
+ position_stride = sizeof(float) * vertex_size;
} else {
- vertex_size = 3;
+ if (new_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ vertex_size = 4;
+ position_stride = sizeof(uint16_t) * vertex_size;
+ } else {
+ vertex_size = 3;
+ position_stride = sizeof(float) * vertex_size;
+ }
}
- stride = sizeof(float) * vertex_size;
}
- if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
- normal_offset = stride;
- stride += sizeof(uint16_t) * 2;
+ if ((new_surface.format & (1ULL << RS::ARRAY_NORMAL))) {
+ normal_offset = position_stride * s->vertex_count;
+ normal_tangent_stride += sizeof(uint16_t) * 2;
}
- if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
- tangent_offset = stride;
- stride += sizeof(uint16_t) * 2;
+ if ((new_surface.format & (1ULL << RS::ARRAY_TANGENT))) {
+ tangent_offset = normal_offset + normal_tangent_stride;
+ normal_tangent_stride += sizeof(uint16_t) * 2;
}
if (mesh->blend_shape_count > 0) {
@@ -282,54 +317,38 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBindVertexArray(s->blend_shapes[i].vertex_array);
glGenBuffers(1, &s->blend_shapes[i].vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer, size, p_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh blend shape buffer");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer, size, new_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh blend shape buffer");
- if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
+ if ((new_surface.format & (1ULL << RS::ARRAY_VERTEX))) {
glEnableVertexAttribArray(RS::ARRAY_VERTEX + 3);
- glVertexAttribPointer(RS::ARRAY_VERTEX + 3, vertex_size, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribPointer(RS::ARRAY_VERTEX + 3, vertex_size, GL_FLOAT, GL_FALSE, position_stride, CAST_INT_TO_UCHAR_PTR(0));
}
- if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
+ if ((new_surface.format & (1ULL << RS::ARRAY_NORMAL))) {
+ // Normal and tangent are packed into the same attribute.
glEnableVertexAttribArray(RS::ARRAY_NORMAL + 3);
- glVertexAttribPointer(RS::ARRAY_NORMAL + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
+ glVertexAttribPointer(RS::ARRAY_NORMAL + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, normal_tangent_stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
}
- if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
+ if ((p_surface.format & (1ULL << RS::ARRAY_TANGENT))) {
glEnableVertexAttribArray(RS::ARRAY_TANGENT + 3);
- glVertexAttribPointer(RS::ARRAY_TANGENT + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
+ glVertexAttribPointer(RS::ARRAY_TANGENT + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, normal_tangent_stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
}
}
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
- // Create a vertex array to use for skeleton/blend shapes.
- glGenVertexArrays(1, &s->skeleton_vertex_array);
- glBindVertexArray(s->skeleton_vertex_array);
- glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
-
- if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
- glEnableVertexAttribArray(RS::ARRAY_VERTEX);
- glVertexAttribPointer(RS::ARRAY_VERTEX, vertex_size, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
- }
- if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
- glEnableVertexAttribArray(RS::ARRAY_NORMAL);
- glVertexAttribPointer(RS::ARRAY_NORMAL, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
- }
- if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
- glEnableVertexAttribArray(RS::ARRAY_TANGENT);
- glVertexAttribPointer(RS::ARRAY_TANGENT, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
- }
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (mesh->surface_count == 0) {
- mesh->aabb = p_surface.aabb;
+ mesh->aabb = new_surface.aabb;
} else {
- mesh->aabb.merge_with(p_surface.aabb);
+ mesh->aabb.merge_with(new_surface.aabb);
}
mesh->skeleton_aabb_version = 0;
- s->material = p_surface.material;
+ s->material = new_surface.material;
mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
mesh->surfaces[mesh->surface_count] = s;
@@ -479,6 +498,8 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
}
}
+ sd.uv_scale = s.uv_scale;
+
return sd;
}
@@ -696,10 +717,6 @@ void MeshStorage::mesh_clear(RID p_mesh) {
}
memdelete_arr(s.blend_shapes);
}
- if (s.skeleton_vertex_array != 0) {
- glDeleteVertexArrays(1, &s.skeleton_vertex_array);
- s.skeleton_vertex_array = 0;
- }
memdelete(mesh->surfaces[i]);
}
@@ -720,15 +737,16 @@ void MeshStorage::mesh_clear(RID p_mesh) {
}
}
-void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
+void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, MeshInstance::Surface *mis) {
Mesh::Surface::Attrib attribs[RS::ARRAY_MAX];
+ int position_stride = 0; // Vertex position only.
+ int normal_tangent_stride = 0;
int attributes_stride = 0;
- int vertex_stride = 0;
int skin_stride = 0;
for (int i = 0; i < RS::ARRAY_INDEX; i++) {
- if (!(s->format & (1 << i))) {
+ if (!(s->format & (1ULL << i))) {
attribs[i].enabled = false;
attribs[i].integer = false;
continue;
@@ -739,29 +757,55 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
switch (i) {
case RS::ARRAY_VERTEX: {
- attribs[i].offset = vertex_stride;
+ attribs[i].offset = 0;
+ attribs[i].type = GL_FLOAT;
+ attribs[i].normalized = GL_FALSE;
if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
attribs[i].size = 2;
+ position_stride = attribs[i].size * sizeof(float);
} else {
- attribs[i].size = 3;
+ if (!mis && (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
+ attribs[i].size = 4;
+ position_stride = attribs[i].size * sizeof(uint16_t);
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ attribs[i].normalized = GL_TRUE;
+ } else {
+ attribs[i].size = 3;
+ position_stride = attribs[i].size * sizeof(float);
+ }
}
- attribs[i].type = GL_FLOAT;
- vertex_stride += attribs[i].size * sizeof(float);
- attribs[i].normalized = GL_FALSE;
} break;
case RS::ARRAY_NORMAL: {
- attribs[i].offset = vertex_stride;
- attribs[i].size = 2;
+ if (!mis && (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
+ attribs[i].size = 2;
+ normal_tangent_stride += 2 * attribs[i].size;
+ } else {
+ attribs[i].size = 4;
+ // A small trick here: if we are uncompressed and we have normals, but no tangents. We need
+ // the shader to think there are 4 components to "axis_tangent_attrib". So we give a size of 4,
+ // but a stride based on only having 2 elements.
+ if (!(s->format & RS::ARRAY_FORMAT_TANGENT)) {
+ normal_tangent_stride += (mis ? sizeof(float) : sizeof(uint16_t)) * 2;
+ } else {
+ normal_tangent_stride += (mis ? sizeof(float) : sizeof(uint16_t)) * 4;
+ }
+ }
+
+ if (mis) {
+ // Transform feedback has interleave all or no attributes. It can't mix interleaving.
+ attribs[i].offset = position_stride;
+ normal_tangent_stride += position_stride;
+ position_stride = normal_tangent_stride;
+ } else {
+ attribs[i].offset = position_stride * s->vertex_count;
+ }
attribs[i].type = (mis ? GL_FLOAT : GL_UNSIGNED_SHORT);
- vertex_stride += sizeof(uint16_t) * 2 * (mis ? 2 : 1);
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_TANGENT: {
- attribs[i].offset = vertex_stride;
- attribs[i].size = 2;
- attribs[i].type = (mis ? GL_FLOAT : GL_UNSIGNED_SHORT);
- vertex_stride += sizeof(uint16_t) * 2 * (mis ? 2 : 1);
- attribs[i].normalized = GL_TRUE;
+ // We never use the tangent attribute. It is always packed in ARRAY_NORMAL, or ARRAY_VERTEX.
+ attribs[i].enabled = false;
+ attribs[i].integer = false;
} break;
case RS::ARRAY_COLOR: {
attribs[i].offset = attributes_stride;
@@ -773,16 +817,28 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
case RS::ARRAY_TEX_UV: {
attribs[i].offset = attributes_stride;
attribs[i].size = 2;
- attribs[i].type = GL_FLOAT;
- attributes_stride += 2 * sizeof(float);
- attribs[i].normalized = GL_FALSE;
+ if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ attributes_stride += 2 * sizeof(uint16_t);
+ attribs[i].normalized = GL_TRUE;
+ } else {
+ attribs[i].type = GL_FLOAT;
+ attributes_stride += 2 * sizeof(float);
+ attribs[i].normalized = GL_FALSE;
+ }
} break;
case RS::ARRAY_TEX_UV2: {
attribs[i].offset = attributes_stride;
attribs[i].size = 2;
- attribs[i].type = GL_FLOAT;
- attributes_stride += 2 * sizeof(float);
- attribs[i].normalized = GL_FALSE;
+ if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ attributes_stride += 2 * sizeof(uint16_t);
+ attribs[i].normalized = GL_TRUE;
+ } else {
+ attribs[i].type = GL_FLOAT;
+ attributes_stride += 2 * sizeof(float);
+ attribs[i].normalized = GL_FALSE;
+ }
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
@@ -828,7 +884,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
continue;
}
if (i <= RS::ARRAY_TANGENT) {
- attribs[i].stride = vertex_stride;
+ attribs[i].stride = (i == RS::ARRAY_VERTEX) ? position_stride : normal_tangent_stride;
if (mis) {
glBindBuffer(GL_ARRAY_BUFFER, mis->vertex_buffer);
} else {
@@ -946,7 +1002,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
// Cache surface properties
s.format_cache = mesh->surfaces[p_surface]->format;
- if ((s.format_cache & (1 << RS::ARRAY_VERTEX))) {
+ if ((s.format_cache & (1ULL << RS::ARRAY_VERTEX))) {
if (s.format_cache & RS::ARRAY_FLAG_USE_2D_VERTICES) {
s.vertex_size_cache = 2;
} else {
@@ -954,25 +1010,27 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
}
s.vertex_stride_cache = sizeof(float) * s.vertex_size_cache;
}
- if ((s.format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((s.format_cache & (1ULL << RS::ARRAY_NORMAL))) {
s.vertex_normal_offset_cache = s.vertex_stride_cache;
s.vertex_stride_cache += sizeof(uint32_t) * 2;
}
- if ((s.format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((s.format_cache & (1ULL << RS::ARRAY_TANGENT))) {
s.vertex_tangent_offset_cache = s.vertex_stride_cache;
s.vertex_stride_cache += sizeof(uint32_t) * 2;
}
+ int buffer_size = s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count;
+
// Buffer to be used for rendering. Final output of skeleton and blend shapes.
glGenBuffers(1, &s.vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW, "MeshInstance vertex buffer");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffer, buffer_size, nullptr, GL_DYNAMIC_DRAW, "MeshInstance vertex buffer");
if (mesh->blend_shape_count > 0) {
// Ping-Pong buffers for processing blendshapes.
glGenBuffers(2, s.vertex_buffers);
for (uint32_t i = 0; i < 2; i++) {
glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffers[i]);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffers[i], s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW, "MeshInstance process buffer[" + itos(i) + "]");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffers[i], buffer_size, nullptr, GL_DYNAMIC_DRAW, "MeshInstance process buffer[" + itos(i) + "]");
}
}
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
@@ -1011,19 +1069,19 @@ void MeshStorage::mesh_instance_set_canvas_item_transform(RID p_mesh_instance, c
void MeshStorage::_blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface) {
glBindBuffer(GL_ARRAY_BUFFER, p_mi->surfaces[p_surface].vertex_buffers[0]);
- if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_VERTEX))) {
+ if ((p_mi->surfaces[p_surface].format_cache & (1ULL << RS::ARRAY_VERTEX))) {
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
glVertexAttribPointer(RS::ARRAY_VERTEX, p_mi->surfaces[p_surface].vertex_size_cache, GL_FLOAT, GL_FALSE, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(0));
} else {
glDisableVertexAttribArray(RS::ARRAY_VERTEX);
}
- if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((p_mi->surfaces[p_surface].format_cache & (1ULL << RS::ARRAY_NORMAL))) {
glEnableVertexAttribArray(RS::ARRAY_NORMAL);
glVertexAttribIPointer(RS::ARRAY_NORMAL, 2, GL_UNSIGNED_INT, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(p_mi->surfaces[p_surface].vertex_normal_offset_cache));
} else {
glDisableVertexAttribArray(RS::ARRAY_NORMAL);
}
- if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((p_mi->surfaces[p_surface].format_cache & (1ULL << RS::ARRAY_TANGENT))) {
glEnableVertexAttribArray(RS::ARRAY_TANGENT);
glVertexAttribIPointer(RS::ARRAY_TANGENT, 2, GL_UNSIGNED_INT, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(p_mi->surfaces[p_surface].vertex_tangent_offset_cache));
} else {
@@ -1091,7 +1149,7 @@ void MeshStorage::update_mesh_instances() {
}
for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].vertex_buffer == 0 || mi->mesh->surfaces[i]->skeleton_vertex_array == 0) {
+ if (mi->surfaces[i].vertex_buffer == 0) {
continue;
}
@@ -1106,10 +1164,10 @@ void MeshStorage::update_mesh_instances() {
specialization |= array_is_2d ? SkeletonShaderGLES3::MODE_2D : 0;
specialization |= SkeletonShaderGLES3::USE_BLEND_SHAPES;
if (!array_is_2d) {
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_NORMAL))) {
specialization |= SkeletonShaderGLES3::USE_NORMAL;
}
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_TANGENT))) {
specialization |= SkeletonShaderGLES3::USE_TANGENT;
}
}
@@ -1123,7 +1181,12 @@ void MeshStorage::update_mesh_instances() {
skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_SHAPE_COUNT, float(mi->mesh->blend_shape_count), skeleton_shader.shader_version, variant, specialization);
glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array);
+ GLuint vertex_array_gl = 0;
+ uint64_t mask = ((1 << 10) - 1) << 3; // Mask from ARRAY_FORMAT_COLOR to ARRAY_FORMAT_INDEX.
+ mask = ~mask;
+ uint64_t format = mi->surfaces[i].format_cache & mask; // Format should only have vertex, normal, tangent (as necessary) + compressions.
+ mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
+ glBindVertexArray(vertex_array_gl);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffers[0]);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, mi->mesh->surfaces[i]->vertex_count);
@@ -1210,10 +1273,10 @@ void MeshStorage::update_mesh_instances() {
specialization |= SkeletonShaderGLES3::FINAL_PASS;
specialization |= use_8_weights ? SkeletonShaderGLES3::USE_EIGHT_WEIGHTS : 0;
if (!array_is_2d) {
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_NORMAL))) {
specialization |= SkeletonShaderGLES3::USE_NORMAL;
}
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_TANGENT))) {
specialization |= SkeletonShaderGLES3::USE_TANGENT;
}
}
@@ -1233,7 +1296,12 @@ void MeshStorage::update_mesh_instances() {
skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_Y, inverse_transform[1], skeleton_shader.shader_version, variant, specialization);
skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_OFFSET, inverse_transform[2], skeleton_shader.shader_version, variant, specialization);
- glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array);
+ GLuint vertex_array_gl = 0;
+ uint64_t mask = ((1 << 10) - 1) << 3; // Mask from ARRAY_FORMAT_COLOR to ARRAY_FORMAT_INDEX.
+ mask = ~mask;
+ uint64_t format = mi->surfaces[i].format_cache & mask; // Format should only have vertex, normal, tangent (as necessary) + compressions.
+ mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
+ glBindVertexArray(vertex_array_gl);
_compute_skeleton(mi, sk, i);
}
}
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 09212e4b5c..25b15ab6a6 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -58,7 +58,7 @@ struct Mesh {
uint32_t offset;
};
RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
- uint32_t format = 0;
+ uint64_t format = 0;
GLuint vertex_buffer = 0;
GLuint attribute_buffer = 0;
@@ -98,6 +98,8 @@ struct Mesh {
Vector<AABB> bone_aabbs;
+ Vector4 uv_scale;
+
struct BlendShape {
GLuint vertex_buffer = 0;
GLuint vertex_array = 0;
@@ -144,7 +146,7 @@ struct MeshInstance {
int vertex_size_cache = 0;
int vertex_normal_offset_cache = 0;
int vertex_tangent_offset_cache = 0;
- uint32_t format_cache = 0;
+ uint64_t format_cache = 0;
Mesh::Surface::Version *versions = nullptr; //allocated on demand
uint32_t version_count = 0;
@@ -221,7 +223,7 @@ private:
mutable RID_Owner<Mesh, true> mesh_owner;
- void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
+ void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, MeshInstance::Surface *mis = nullptr);
/* Mesh Instance API */
@@ -381,18 +383,18 @@ public:
}
// Use this to cache Vertex Array Objects so they are only generated once
- _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
+ _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint64_t p_input_mask, GLuint &r_vertex_array_gl) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
s->version_lock.lock();
- //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
+ // There will never be more than 3 or 4 versions, so iterating is the fastest way.
for (uint32_t i = 0; i < s->version_count; i++) {
if (s->versions[i].input_mask != p_input_mask) {
continue;
}
- //we have this version, hooray
+ // We have this version, hooray.
r_vertex_array_gl = s->versions[i].vertex_array;
s->version_lock.unlock();
return;
@@ -424,7 +426,7 @@ public:
// TODO: considering hashing versions with multimesh buffer RID.
// Doing so would allow us to avoid specifying multimesh buffer pointers every frame and may improve performance.
- _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
+ _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint64_t p_input_mask, GLuint &r_vertex_array_gl) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_NULL(mi);
Mesh *mesh = mi->mesh;
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index e553b2b522..5c68149a5f 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -4499,6 +4499,7 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
if (atf.frequency == VERTEX_FREQUENCY_VERTEX) {
// Validate size for regular drawing.
uint64_t total_size = uint64_t(atf.stride) * (p_vertex_count - 1) + atf.offset + element_size;
+
ERR_FAIL_COND_V_MSG(total_size > buffer->size, RID(),
"Attachment (" + itos(i) + ") will read past the end of the buffer.");
@@ -4665,7 +4666,7 @@ struct RenderingDeviceVulkanShaderBinarySpecializationConstant {
};
struct RenderingDeviceVulkanShaderBinaryData {
- uint32_t vertex_input_mask;
+ uint64_t vertex_input_mask;
uint32_t fragment_output_mask;
uint32_t specialization_constants_count;
uint32_t is_compute;
@@ -4881,7 +4882,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
push_constant.size = binary_data.push_constant_size;
push_constant.vk_stages_mask = binary_data.push_constant_vk_stages_mask;
- uint32_t vertex_input_mask = binary_data.vertex_input_mask;
+ uint64_t vertex_input_mask = binary_data.vertex_input_mask;
uint32_t fragment_output_mask = binary_data.fragment_output_mask;
@@ -5209,7 +5210,7 @@ RID RenderingDeviceVulkan::shader_create_placeholder() {
return shader_owner.make_rid(shader);
}
-uint32_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) {
+uint64_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) {
_THREAD_SAFE_METHOD_
const Shader *shader = shader_owner.get_or_null(p_shader);
@@ -6152,8 +6153,8 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
pipeline_vertex_input_state_create_info = vd.create_info;
// Validate with inputs.
- for (uint32_t i = 0; i < 32; i++) {
- if (!(shader->vertex_input_mask & (1UL << i))) {
+ for (uint64_t i = 0; i < 64; i++) {
+ if (!(shader->vertex_input_mask & (1ULL << i))) {
continue;
}
bool found = false;
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index fd14449ee7..7c514c11f8 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -621,7 +621,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE;
};
- uint32_t vertex_input_mask = 0; // Inputs used, this is mostly for validation.
+ uint64_t vertex_input_mask = 0; // Inputs used, this is mostly for validation.
uint32_t fragment_output_mask = 0;
struct PushConstant {
@@ -1140,7 +1140,7 @@ public:
virtual RID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, RID p_placeholder = RID());
virtual RID shader_create_placeholder();
- virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader);
+ virtual uint64_t shader_get_vertex_input_attribute_mask(RID p_shader);
/*****************/
/**** UNIFORM ****/