Godot Version
4.3
Question
I am working on a GDExtension class that generates a custom texture that needs to be updated every frame. The texture is very large and I would like to minimize the amount of data copying that happens during the update. I have the texture internally stored in the private class member PackedByteArray pixel_data_
that is written to by the update logic and then updates the texture inside of C++ like this:
void World::_process(double delta) {
// Update visualization
world_image_->set_data(Globals::kWorldWidth, Globals::kWorldHeight, false,
Image::FORMAT_R8, pixel_data_);
world_texture_->update(world_image_);
}
My understanding of Godot’s internal logic is that the call to Image::set_data()
will only update the image’s internal data pointer to point to my new array without making a copy, and the call to ImageTexture::update()
will only cause a single copy from the CPU to the GPU, which isn’t really avoidable.
In the interest of separating concerns, I am considering moving some of this update code to GDScript, but would like to do so in a way that doesn’t add extra overhead from copying data needlessly. If I instead turn this into a property:
PackedByteArray get_pixel_data() const { return pixel_data_; }
and do the update inside of GDScript:
func _process(_delta):
update_visualization()
func update_visualization():
world_image.set_data(Globals.kWorldWidth, Globals.kWorldHeight, false, Image.FORMAT_R8, world.get_pixel_data())
world_texture.update(world_image)
will this still pass the data by reference, or will there be another copy made in here? Is there a way I can do this without making an extra copy?
I know the documentation for PackedByteArray has this to say:
Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use duplicate. This is not the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will not affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
This is a little confusing to me. It’s clear to me that PackedByteArray
s passed within GDScript are passed by reference, but I’m not sure if an array returned from a GDExtension class would qualify as “built-in” under this definition.