How to draw texture RID from local RenderingDevice on screen?

Godot Version

4.4.1

Question

I was following this thread trying to figure out how to get a texture I’m computing in a local rendering device to display in Godot components like TextureRect. I’m pretty sure the texture computation part is working because it displays properly when I do everything on the main RenderingDevice.

I was adapting this code the best I could from:

My code currently looks like this:

func get_image()->Texture2DRD:
	render_image()
	
	var fmt:RDTextureFormat = rd.texture_get_format(texture_output_rd)
	
	var rd_main:RenderingDevice = RenderingServer.get_rendering_device()

	display_output_tex = Texture2DRD.new()
	
	var display_output_tex_rid:RID = rd_main.texture_create_from_extension(
		RenderingDevice.TEXTURE_TYPE_2D,
		fmt.format,
		fmt.samples,
		fmt.usage_bits,
		rd_main.get_driver_resource(RenderingDevice.DRIVER_RESOURCE_TEXTURE, texture_output_rid, 0),
		fmt.width,
		fmt.height,
		fmt.depth,
		fmt.array_layers
	)
	
	display_output_tex.texture_rd_rid = display_output_tex_rid
	return display_output_tex

It crashes when I get to rd_main.texture_create_from_extension. I’m not sure what’s wrong.

Also - am I right in thinking this is performing a copy of the texture data onto a new device?

It’s the other way around. You first create the texture from the main rendering device and share it with your local rendering device with texture_create_from_extension()

Here’s creating the texture in the main rendering device:

Here, the texture variable, holds the texture that will be used by the mesh/sprite. It points to the texture RID created in the main rendering device.

And here’s it sharing the texture in the local rendering device:

The output_texture_rid is the texture RID in the local rendering device.

As far as I understand, it’s not creating a copy of the data but sharing the resource (it’s the same data).

I want to go the other way. I was thinking that it would be best for my computation to be off of the main thread, and I just want to be able to show the results on the main rendering thread when it’s done.

My aim is to create a pipeline of several shaders and send the outputs of one to the shaders to the inputs of the next. I also want to interact with CPU code, and would like to have a way to know that the computation has finished before I run the next compute shader in the chain (so that I can set some parameters). That does not seem to be possible on the main rendering device thread, since you cannot call sync() on it.

Can I share something created on the local device with the main rendering device?

I know what you want and the only way I found it works fine is if you first create the texture in the main rendering device so you can use it in your game with a Texture2DRD and share that texture with your local rendering device where you will modify it.

I’ve not tested doing it the other way around. Maybe if you change this line in your code:

rd_main.get_driver_resource(RenderingDevice.DRIVER_RESOURCE_TEXTURE, texture_output_rid, 0),

to:

rd.get_driver_resource(RenderingDevice.DRIVER_RESOURCE_TEXTURE, texture_output_rid, 0)

may work. It’s your local rendering device (rd) the one that has the texture resource (texture_output_rid) and not the main rendering device (main_rd)

1 Like