Compute shader crashing Godot

Godot Version: 4.6.stable.steam

Currently I’m trying to create an image that I can modify between frames with a compute shader.

The code I have is meant to create an image on the main rendering thread, pass it to a compute shader, and get modified there. Currently, testing the project runs it and then crashes without any errors in the editor.

Right now, it’s crashing the moment it reaches the imageLoad function in the compute shader; disabling the RenderingServer.submit() (rdloc.submit() in the code) stops my crash. Enabling it and disabling the ImageLoad function in the compute shader itself also prevents any crashing, so I know that’s the line that’s causing the crash.
From what I’ve looked up elsewhere, it’s possible there’s something wrong with the image attached to the compute shader, but I’m not sure what. I’ve done what I can with the documents, reading a few old help threads here, and trying to look through the godot help files, but I can’t figure out why this isn’t working.
Supposedly the compute shader is creating a copy of the texture data from the main rendering device, and it shows as valid if I test it with rdloc.texture_is_valid(), so I’m not sure what I’ve done wrong here.

extends Node2D
#Rendering Server and other setup
var rdmain := RenderingServer.get_rendering_device()
var rdloc := RenderingServer.create_local_rendering_device()
var level_picture : Image = load("res://boid_particles/Trash.png").get_image()
var level_size : Vector2
var level_texture := Texture2DRD.new()

#Compute Pipeline setup
var pipeline : RID
var bindings : Array
var uniform_set : RID
#Compute Pipeline parts
var params_buffer: RID
var params_uniform : RDUniform

func _ready() -> void:
	var setup_image : Image
	setup_image = level_picture
	setup_image.convert(Image.FORMAT_RGBAF) 
	level_size = setup_image.get_size()
	var texture_format = _create_texture_format()
	var view = RDTextureView.new()
	var local_texture = rdmain.texture_create(texture_format,view,[setup_image.get_data()]) #Create a texture on the main rendering device
	level_texture.texture_rd_rid = local_texture
	$TextureRect.texture = level_texture #set the texture to the one referenced on the main rendering device. Seems to work fine.
	
	var output_texture_rid = rdloc.texture_create_from_extension(RenderingDevice.TEXTURE_TYPE_2D,
	texture_format.format,
	texture_format.samples,
	texture_format.usage_bits,
	rdmain.get_driver_resource(RenderingDevice.DRIVER_RESOURCE_TEXTURE,local_texture,0),
	texture_format.width,
	texture_format.height,
	texture_format.depth,
	texture_format.array_layers
	)
	
	var uniform := RDUniform.new()
	uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE
	uniform.binding = 0
	uniform.add_id(output_texture_rid)
	
	var shader_file := load("res://Gremlings/ShaderBug.glsl")
	var shader_spirv: RDShaderSPIRV = shader_file.get_spirv()
	var shader := rdloc.shader_create_from_spirv(shader_spirv)
	uniform_set = rdloc.uniform_set_create([uniform], shader, 0)
	var compute_list := rdloc.compute_list_begin()
	pipeline = rdloc.compute_pipeline_create(shader)
	rdloc.compute_list_bind_compute_pipeline(compute_list, pipeline)
	rdloc.compute_list_bind_uniform_set(compute_list, uniform_set, 0)
	rdloc.compute_list_dispatch(compute_list, 1, 1, 1)
	rdloc.compute_list_end()
	rdloc.submit()

func _create_texture_format() -> RDTextureFormat:
	var format := RDTextureFormat.new()
	format.array_layers = 1
	format.depth = 1
	format.format = RenderingDevice.DATA_FORMAT_R32G32B32A32_SFLOAT 
	format.width = int(level_size.x)
	format.height = int(level_size.y)
	format.usage_bits = RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT \
	| RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT \
	| RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT \
	| RenderingDevice.TEXTURE_USAGE_STORAGE_BIT \
	| RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT
	return format
	


func _exit_tree() -> void:
	rdloc.free_rid(pipeline)
	rdloc.free_rid(uniform_set)
	rdmain.free_rid(level_texture.texture_rd_rid)
#[compute]
#version 450

layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
//layout(set = 0, binding = 0,rgba32f) uniform image2D Input_Image;

layout(set = 0, binding = 0,rgba32f) uniform image2D Input_Image;

void main(){

ivec2 position = ivec2(0,0);
vec4 color = imageLoad(Input_Image,ivec2(0,0));
//imageStore(Input_Image,position,vec4(1.0,0.0,0.0,1.0));

}

What do you mean by “crashing”? Are there any error messages?

No, that’s the problem. It launches, then closes just after the scene starts. At a couple points, it was Windows trying to close it.
I’m assuming it’s a problem in the compute shader itself causing a crash, and that the Godot editor doesn’t handle those.

It just silently crashes to desktop/editor?

Maybe this can help (Vulkan validation layer)

Or the big tools
RenderDoc:

On nvidia:

But I have never used any of these.

Correct. I wonder if I’ve somehow passed wrong data to the shader in a way Godot doesn’t catch, or if what I’m trying isn’t supported or is a bad implementation of what I read in another thread.

Edit: Going to just assume it’s something with GPU and violations; rendering server runs independently of processing code, so I probably have the local device trying to access the same data as the main device at the same time.
conz3d probably has the right solution- checking with more validation steps, etc., especially since removing the local device and running everything on the main rendering device works perfectly fine.
I tried a few bits of code to see if I can run the compute shader on a local device between rendering calls/frames, but I haven’t gotten it to work and that seems like I’d be digging myself into an even deeper hole.

What happens if you don’t use texture_create_from_extension() but instead just create the texture directly on the local rendering device?

Then it processes fine, but I can’t attach that texture to anything to have it drawn. Tried using a Texture2DRD, and get the same problem.
It may be possible to have it render from that local device, but that seems like a ton of extra steps just to recreate what the rendering server already handles.

Run the compute shader on the main device.

1 Like