|
@@ -1485,7 +1485,7 @@ void MeshStorage::_multimesh_free(RID p_rid) {
|
|
multimesh_owner.free(p_rid);
|
|
multimesh_owner.free(p_rid);
|
|
}
|
|
}
|
|
|
|
|
|
-void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
|
|
|
|
|
|
+void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data, bool p_use_indirect) {
|
|
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
|
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
|
ERR_FAIL_NULL(multimesh);
|
|
ERR_FAIL_NULL(multimesh);
|
|
|
|
|
|
@@ -1521,6 +1521,9 @@ void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS:
|
|
multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
|
|
multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
|
|
multimesh->buffer_set = false;
|
|
multimesh->buffer_set = false;
|
|
|
|
|
|
|
|
+ multimesh->indirect = p_use_indirect;
|
|
|
|
+ multimesh->command_buffer = RID();
|
|
|
|
+
|
|
//print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
|
|
//print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
|
|
multimesh->data_cache = Vector<float>();
|
|
multimesh->data_cache = Vector<float>();
|
|
multimesh->aabb = AABB();
|
|
multimesh->aabb = AABB();
|
|
@@ -1609,6 +1612,30 @@ void MeshStorage::_multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
|
|
}
|
|
}
|
|
multimesh->mesh = p_mesh;
|
|
multimesh->mesh = p_mesh;
|
|
|
|
|
|
|
|
+ if (multimesh->indirect) {
|
|
|
|
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
|
|
|
|
+ ERR_FAIL_NULL(mesh);
|
|
|
|
+ if (mesh->surface_count > 0) {
|
|
|
|
+ if (multimesh->command_buffer.is_valid()) {
|
|
|
|
+ RD::get_singleton()->free(multimesh->command_buffer);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Vector<uint8_t> newVector;
|
|
|
|
+ newVector.resize_zeroed(sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE * mesh->surface_count);
|
|
|
|
+
|
|
|
|
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
|
|
|
+ uint32_t count = mesh_surface_get_vertices_drawn_count(mesh->surfaces[i]);
|
|
|
|
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE, static_cast<uint8_t>(count));
|
|
|
|
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE + 1, static_cast<uint8_t>(count >> 8));
|
|
|
|
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE + 2, static_cast<uint8_t>(count >> 16));
|
|
|
|
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE + 3, static_cast<uint8_t>(count >> 24));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ RID newBuffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE * mesh->surface_count, newVector, RD::STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
|
|
|
|
+ multimesh->command_buffer = newBuffer;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (multimesh->instances == 0) {
|
|
if (multimesh->instances == 0) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -2064,6 +2091,12 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+RID MeshStorage::_multimesh_get_command_buffer_rd_rid(RID p_multimesh) const {
|
|
|
|
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
|
|
|
+ ERR_FAIL_NULL_V(multimesh, RID());
|
|
|
|
+ return multimesh->command_buffer;
|
|
|
|
+}
|
|
|
|
+
|
|
RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
|
|
RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
|
|
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
|
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
|
ERR_FAIL_NULL_V(multimesh, RID());
|
|
ERR_FAIL_NULL_V(multimesh, RID());
|
|
@@ -2111,6 +2144,15 @@ void MeshStorage::_multimesh_set_visible_instances(RID p_multimesh, int p_visibl
|
|
|
|
|
|
multimesh->visible_instances = p_visible;
|
|
multimesh->visible_instances = p_visible;
|
|
|
|
|
|
|
|
+ if (multimesh->indirect) { //we have to update the command buffer for the instance counts, in each stride this will be the second integer.
|
|
|
|
+ Mesh *mesh = mesh_owner.get_or_null(multimesh->mesh);
|
|
|
|
+ if (mesh != nullptr) {
|
|
|
|
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
|
|
|
+ RD::get_singleton()->buffer_update(multimesh->command_buffer, (i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE) + sizeof(uint32_t), sizeof(uint32_t), &p_visible);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
|
|
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
|
|
}
|
|
}
|
|
|
|
|