diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 93ae82f52a0..fafd1292608 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -2559,6 +2559,7 @@
+
@@ -2593,6 +2594,29 @@
Returns the [RenderingDevice] [RID] handle of the [MultiMesh], which can be used as any other buffer on the Rendering Device.
+
+
+
+
+ Returns the [RenderingDevice] [RID] handle of the [MultiMesh] command buffer. This [RID] is only valid if [code]use_indirect[/code] is set to [code]true[/code] when allocating data through [method multimesh_allocate_data]. It can be used to directly modify the instance count via buffer.
+ The data structure is dependent on both how many surfaces the mesh contains and whether it is indexed or not, the buffer has 5 integers in it, with the last unused if the mesh is not indexed.
+ Each of the values in the buffer correspond to these options:
+ [codeblock lang=text]
+ Indexed:
+ 0 - indexCount;
+ 1 - instanceCount;
+ 2 - firstIndex;
+ 3 - vertexOffset;
+ 4 - firstInstance;
+ Non Indexed:
+ 0 - vertexCount;
+ 1 - instanceCount;
+ 2 - firstVertex;
+ 3 - firstInstance;
+ 4 - unused;
+ [/codeblock]
+
+
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index a3362942320..428646aaf71 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -1518,7 +1518,7 @@ void MeshStorage::_multimesh_free(RID 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);
ERR_FAIL_NULL(multimesh);
@@ -2041,6 +2041,10 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector &p_
}
}
+RID MeshStorage::_multimesh_get_command_buffer_rd_rid(RID p_multimesh) const {
+ ERR_FAIL_V_MSG(RID(), "GLES3 does not implement indirect multimeshes.");
+}
+
RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
ERR_FAIL_V_MSG(RID(), "GLES3 does not contain a Rid for the multimesh buffer.");
}
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 83ac0efc5c8..3b9084a04ce 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -502,7 +502,7 @@ public:
virtual RID _multimesh_allocate() override;
virtual void _multimesh_initialize(RID p_rid) override;
virtual void _multimesh_free(RID p_rid) override;
- virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
+ virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override;
virtual int _multimesh_get_instance_count(RID p_multimesh) const override;
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
@@ -521,6 +521,7 @@ public:
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) override;
+ virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
virtual Vector _multimesh_get_buffer(RID p_multimesh) const override;
diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected
index 91db0dd9b7a..cf3aa2d0582 100644
--- a/misc/extension_api_validation/4.3-stable.expected
+++ b/misc/extension_api_validation/4.3-stable.expected
@@ -217,6 +217,13 @@ Validate extension JSON: Error: Field 'classes/Control/properties/offset_top': t
Property type changed to float to match the actual internal API and documentation.
+GH-99455
+--------
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/multimesh_allocate_data/arguments': size changed value in new API, from 5 to 6.
+
+Optional argument added to allow setting indirect draw mode on Multimesh. Compatibility method registered.
+
+
GH-100129
---------
Validate extension JSON: Error: Field 'classes/NavigationServer2D/methods/query_path': is_const changed value in new API, from true to false.
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index 97789d3a82d..ffffa4ef534 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -151,7 +151,7 @@ public:
virtual void _multimesh_initialize(RID p_rid) override;
virtual void _multimesh_free(RID p_rid) override;
- virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
+ virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override {}
virtual int _multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
@@ -171,6 +171,7 @@ public:
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) override;
+ virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override { return RID(); }
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override { return RID(); }
virtual Vector _multimesh_get_buffer(RID p_multimesh) const override;
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 207538c7104..70b3a89c4a6 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -599,7 +599,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
instance_count /= surf->owner->trail_steps;
}
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
+ if (bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT)) {
+ RD::get_singleton()->draw_list_draw_indirect(draw_list, index_array_rd.is_valid(), mesh_storage->_multimesh_get_command_buffer_rd_rid(surf->owner->data->base), surf->surface_index * sizeof(uint32_t) * mesh_storage->INDIRECT_MULTIMESH_COMMAND_STRIDE, 1, 0);
+ } else {
+ RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
+ }
}
i += element_info.repeat - 1; //skip equal elements
@@ -1083,6 +1087,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
} else {
surf->sort.lod_index = 0;
if (p_render_data->render_info) {
+ // This does not include primitives rendered via indirect draw calls.
uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
@@ -4205,9 +4210,9 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p
ginstance->base_flags = 0;
bool store_transform = true;
-
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+
if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
@@ -4217,6 +4222,9 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p
if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
+ if (mesh_storage->multimesh_uses_indirect(ginstance->data->base)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT;
+ }
ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 42c1da1a971..567ca5d80fa 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -255,6 +255,7 @@ private:
// When changing any of these enums, remember to change the corresponding enums in the shader files as well.
enum {
+ INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT = 1 << 2,
INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3,
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 6d217964366..1651e82276d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -2380,7 +2380,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
instance_count /= surf->owner->trail_steps;
}
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
+ if (bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT)) {
+ RD::get_singleton()->draw_list_draw_indirect(draw_list, index_array_rd.is_valid(), mesh_storage->_multimesh_get_command_buffer_rd_rid(surf->owner->data->base), surf->surface_index * sizeof(uint32_t) * mesh_storage->INDIRECT_MULTIMESH_COMMAND_STRIDE, 1, 0);
+ } else {
+ RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
+ }
}
}
@@ -2801,6 +2805,7 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+
if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
@@ -2810,6 +2815,9 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge
if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
+ if (mesh_storage->multimesh_uses_indirect(ginstance->data->base)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT;
+ }
ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 77242c8c93c..e6aec9752ec 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -358,6 +358,7 @@ protected:
// When changing any of these enums, remember to change the corresponding enums in the shader files as well.
enum {
+ INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT = 1 << 2,
INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3,
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index bd5f8dc787e..84f4b452996 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -1485,7 +1485,7 @@ void MeshStorage::_multimesh_free(RID 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);
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->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));
multimesh->data_cache = Vector();
multimesh->aabb = AABB();
@@ -1609,6 +1612,30 @@ void MeshStorage::_multimesh_set_mesh(RID p_multimesh, RID 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 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(count));
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE + 1, static_cast(count >> 8));
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE + 2, static_cast(count >> 16));
+ newVector.set(i * sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE + 3, static_cast(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) {
return;
}
@@ -2064,6 +2091,12 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector &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 {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
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;
+ 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);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 7a8f0c8e608..5b8ed343857 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -59,6 +59,10 @@ public:
DEFAULT_RD_BUFFER_MAX,
};
+ enum IndirectMultiMesh : uint32_t {
+ INDIRECT_MULTIMESH_COMMAND_STRIDE = 5
+ };
+
private:
static MeshStorage *singleton;
@@ -226,6 +230,7 @@ private:
AABB custom_aabb;
bool aabb_dirty = false;
bool buffer_set = false;
+ bool indirect = false;
bool motion_vectors_enabled = false;
uint32_t motion_vectors_current_offset = 0;
uint32_t motion_vectors_previous_offset = 0;
@@ -243,6 +248,7 @@ private:
RID buffer; //storage buffer
RID uniform_set_3d;
RID uniform_set_2d;
+ RID command_buffer; //used if indirect setting is used
bool dirty = false;
MultiMesh *dirty_list = nullptr;
@@ -637,7 +643,7 @@ public:
virtual void _multimesh_initialize(RID p_multimesh) override;
virtual void _multimesh_free(RID p_rid) override;
- virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
+ virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override;
virtual int _multimesh_get_instance_count(RID p_multimesh) const override;
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
@@ -654,6 +660,7 @@ public:
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) override;
+ virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
virtual Vector _multimesh_get_buffer(RID p_multimesh) const override;
@@ -672,6 +679,11 @@ public:
bool _multimesh_uses_motion_vectors_offsets(RID p_multimesh);
bool _multimesh_uses_motion_vectors(RID p_multimesh);
+ _FORCE_INLINE_ bool multimesh_uses_indirect(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->indirect;
+ }
+
_FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
return multimesh->xform_format;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 16d32f00a46..14794f7bab7 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -382,7 +382,7 @@ public:
FUNCRIDSPLIT(multimesh)
- FUNC5(multimesh_allocate_data, RID, int, MultimeshTransformFormat, bool, bool)
+ FUNC6(multimesh_allocate_data, RID, int, MultimeshTransformFormat, bool, bool, bool)
FUNC1RC(int, multimesh_get_instance_count, RID)
FUNC2(multimesh_set_mesh, RID, RID)
@@ -403,6 +403,7 @@ public:
FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
FUNC2(multimesh_set_buffer, RID, const Vector &)
+ FUNC1RC(RID, multimesh_get_command_buffer_rd_rid, RID)
FUNC1RC(RID, multimesh_get_buffer_rd_rid, RID)
FUNC1RC(Vector, multimesh_get_buffer, RID)
diff --git a/servers/rendering/storage/mesh_storage.cpp b/servers/rendering/storage/mesh_storage.cpp
index 4a6746e6c91..5b899878039 100644
--- a/servers/rendering/storage/mesh_storage.cpp
+++ b/servers/rendering/storage/mesh_storage.cpp
@@ -48,7 +48,7 @@ void RendererMeshStorage::multimesh_free(RID p_rid) {
_multimesh_free(p_rid);
}
-void RendererMeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+void RendererMeshStorage::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) {
MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
if (mmi) {
mmi->_transform_format = p_transform_format;
@@ -68,7 +68,7 @@ void RendererMeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instanc
mmi->_data_interpolated.resize_zeroed(size_in_floats);
}
- _multimesh_allocate_data(p_multimesh, p_instances, p_transform_format, p_use_colors, p_use_custom_data);
+ _multimesh_allocate_data(p_multimesh, p_instances, p_transform_format, p_use_colors, p_use_custom_data, p_use_indirect);
}
int RendererMeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
@@ -223,6 +223,10 @@ void RendererMeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer);
+ virtual RID multimesh_get_command_buffer_rd_rid(RID p_multimesh) const;
virtual RID multimesh_get_buffer_rd_rid(RID p_multimesh) const;
virtual Vector multimesh_get_buffer(RID p_multimesh) const;
@@ -159,7 +160,7 @@ public:
virtual void _multimesh_initialize(RID p_rid) = 0;
virtual void _multimesh_free(RID p_rid) = 0;
- virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+ virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) = 0;
virtual int _multimesh_get_instance_count(RID p_multimesh) const = 0;
@@ -180,6 +181,7 @@ public:
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) = 0;
+ virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const = 0;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const = 0;
virtual Vector _multimesh_get_buffer(RID p_multimesh) const = 0;
diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc
index 99f2de9a9a3..2ae2f3c8844 100644
--- a/servers/rendering_server.compat.inc
+++ b/servers/rendering_server.compat.inc
@@ -30,6 +30,10 @@
#ifndef DISABLE_DEPRECATED
+void RenderingServer::_multimesh_allocate_data_bind_compat_99455(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+ multimesh_allocate_data(p_multimesh, p_instances, p_transform_format, p_use_colors, p_use_custom_data, false);
+}
+
void RenderingServer::_environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) {
environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL);
}
@@ -47,6 +51,7 @@ void RenderingServer::_canvas_item_add_circle_bind_compat_84523(RID p_item, cons
}
void RenderingServer::_bind_compatibility_methods() {
+ ClassDB::bind_compatibility_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::_multimesh_allocate_data_bind_compat_99455, DEFVAL(false), DEFVAL(false));
ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792);
ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::_canvas_item_add_multiline_bind_compat_84523, DEFVAL(-1.0));
ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::_canvas_item_add_rect_bind_compat_84523);
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index a38d9a4b05c..422faa13a09 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2441,7 +2441,7 @@ void RenderingServer::_bind_methods() {
/* MULTIMESH API */
ClassDB::bind_method(D_METHOD("multimesh_create"), &RenderingServer::multimesh_create);
- ClassDB::bind_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate_data, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format", "use_indirect"), &RenderingServer::multimesh_allocate_data, DEFVAL(false), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &RenderingServer::multimesh_get_instance_count);
ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &RenderingServer::multimesh_set_mesh);
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &RenderingServer::multimesh_instance_set_transform);
@@ -2459,6 +2459,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &RenderingServer::multimesh_set_visible_instances);
ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &RenderingServer::multimesh_get_visible_instances);
ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &RenderingServer::multimesh_set_buffer);
+ ClassDB::bind_method(D_METHOD("multimesh_get_command_buffer_rd_rid", "multimesh"), &RenderingServer::multimesh_get_command_buffer_rd_rid);
ClassDB::bind_method(D_METHOD("multimesh_get_buffer_rd_rid", "multimesh"), &RenderingServer::multimesh_get_buffer_rd_rid);
ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &RenderingServer::multimesh_get_buffer);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 94447baf67c..1206911e4b2 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -457,7 +457,12 @@ public:
MULTIMESH_INTERP_QUALITY_HIGH,
};
- virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+protected:
+#ifndef DISABLE_DEPRECATED
+ void _multimesh_allocate_data_bind_compat_99455(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data);
+#endif
+public:
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) = 0;
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
@@ -478,6 +483,7 @@ public:
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
virtual void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) = 0;
+ virtual RID multimesh_get_command_buffer_rd_rid(RID p_multimesh) const = 0;
virtual RID multimesh_get_buffer_rd_rid(RID p_multimesh) const = 0;
virtual Vector multimesh_get_buffer(RID p_multimesh) const = 0;