Skip to content

RenderingServer.multimesh_instance_get_transform() uses CPU-cached value rather than GPU buffer data #108847

@natstott

Description

@natstott

Tested versions

Reproducable in 4.4.1. and v4.5.beta3.official

System information

Godot v4.4.1.stable - Linux Mint 21.3 (Virginia) on X11 - X11 display driver, Multi-window, 1 monitor - Vulkan (Forward+) - dedicated NVIDIA GeForce 930MX (nvidia; 570.169) - Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz (8 threads)

Issue description

A multimesh is created in RenderingServer and the positions of the multimesh instances are updated in a compute shader. This part is working fine, I can update mesh locations in the compute shader and they are being drawn correctly.

I try getting the location of individual meshes so e.g. the camera can follow one planet as a test:

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

In the MVP a position is just retrieved and printed when the space bar is pressed.

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.

While a more complete indirect multimesh might allow draw calls to use a SSBO directly, I have used the multimesh buffer as this appears to be the only way to do multiple draw calls using GPU created data.

MrCDK confirmed on forum that:
servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp does not update if cached buffer is still present. But there does not seem to be any use case for instance_get_transform() if the instance positions have not been changed outside the GPU. I suspect the same is true for get_color and get_custom.

Forum post with link to Godot source

A quick fix would be to change MeshStorage::_multimesh_make_local

and remove :

	if (multimesh->data_cache.size() > 0) {
		return; //already local
	}

But it would possibly be better to retrieve the individual instance data when needed to reduce transfers.

Steps to reproduce

Create Multimesh

Get Multimesh buffer RID and use it as a storage buffer for a compute shader to update mesh positions on GPU.

Retrieve a mesh instance transform using RenderingServer.multimesh_instance_get_transform

Minimal reproduction project (MRP)

MVPMMBug.tar.gz

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions