Multimesh_instance_get_transform not updating when buffer updated in compute shader?

Godot Version

`4.4.1

Question

I’ve got a multimesh created in RenderingServer and I’m updating the positions of the multimesh instances in a compute shader. This is all working fine, I’m getting thousands of planets updated in the compute and being drawn correctly.

But I decided to try getting the camera to follow one planet as a test:

var EarthPosition=RenderingServer.multimesh_instance_get_transform(planet_Multimesh,4)
look_at(EarthPosition.origin)

The camera is stuck looking at the starting position of that planet, which of course has moved away due to the compute shader. It looks like multimesh_instance_get_transform is retrieving a CPU copy of the buffer?

Is this expected?

I’d be happy to try and fix it if it isn’t, but I’d need some help.

Seems like a bug. As you said, the information must be copied to a CPU buffer which happens here:

But _multimesh_make_local() will only do it once and bail if the data was already in the cache:

Using RenderingServer.multimesh_get_buffer() has the same issue as far as I can tell:

I’ve not tested this but I think a workaround is to get the raw buffer directly from the main rendering device and interpret it as needed. Something like:

var buffer_rid = RenderingServer.multimesh_get_buffer_rd_rid(multimesh_rid)
var main_rd = RenderingServer.get_rendering_device()
var buffer = main_rd.buffer_get_data(buffer_rid).to_float32_buffer()
# parse the buffer data

But I don’t know how to skip the motion vectors data that the buffer contains.

Please, open an issue in the issue tracker. Try to attach a MRP (minimum reproduction project) so people have an easier time trying to fix the issue.

1 Like

Thanks for finding that. I’ll have a go at raising an issue - There seems little point in having the instance_get functions if the multimesh has not been updated.

You’re right, I could try buffer_get_data() with an offset to just read the transform I need.

Thanks.

Workaround tested and can be adapted to retrieve other individual multimesh values:

func Get_Planet(planetid):
	var stride = 80 #20*4 bytes as using custom and color
	var rd = RenderingServer.get_rendering_device()
	var buffer_rid = RenderingServer.multimesh_get_buffer_rd_rid(planet_Multimesh) 
	var main_rd = RenderingServer.get_rendering_device()
	var buffer = main_rd.buffer_get_data(buffer_rid,planetid*stride,stride).to_float32_array()
		# parse the buffer data
	var thisposition = Vector3(buffer.get(3), buffer.get(7),buffer.get(11))# based on transform buffer in multimesh
	return thisposition

An issue has been raised:

https://github.com/godotengine/godot/issues/108847

1 Like