Description
Describe the project you are working on
fennecs, a pure C# ECS that works with Godot.
Describe the problem or limitation you are having in your project
A common use case is to pass component data into a Multimesh
for rendering by Godot. With RenderingServer
, this is done by passing a float[]
. (internally, this gets marshalled and copied into native memory)
My ECS queries preferably pass Span<T>
and Memory<T>
to the user. These aren't System.Array
.
Calling .ToArray()
on a Span
adds a full, redundant memory copy and heap allocation operation. (the data is usually too large for any sort of stackalloc, and originates from the heap anyway)
In a more commonplace use case (which also applies to ECS), it is somewhat cumbersome to cast a Transform3D[]
or Span<Transform3D>
into a float[]
(because of the steps involved, and exacerbated by struct layout incompatibility); and the same is true for some hypothetical contiguous array of structs extended with the optional data for the Multimesh.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Suggested overloads:
public static void MultimeshSetBuffer(Rid multimesh, Span<float> buffer) //basic requirement
public static void MultimeshSetBuffer<T>(Rid multimesh, Memory<T> buffer) //marry me please
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
... will become this (note the removed array allocation) ...
... and most elegantly, with the Memory overload (would internally use MemoryHandle Memory.Pin to get the pointer for the native call, and could use Memory.Length and sizeof(T) to determine length of the PackedArray):
If this enhancement will not be used often, can it be worked around with a few lines of script?
The extra memory allocation has a significant impact that, to my knowledge, cannot be worked around at the moment. Because the internal API of Multimesh is so strict, arrays of larger length (with unused elements at the end) cannot be submitted, so a workaround using ArrayPool or something similar just isn't feasible, because that only returns arrays of a minimum size, not an exact size. Going through Span<float>
s is the right way here, and the backing Native interop API already uses them. They are just not exposed to the user of GodotSharp.
Is there a reason why this should be core and not an add-on in the asset library?
This should be part of the C# module / extension. I think it primarly affects the glue code and a few lines of code within earshot of Godot.Marshaling.