Compute shader wont compile

Godot Version

4.7

Question

Hi,

I need help getting compute shaders to compile, would be appreciated, cheers.

I am trying to find the min and max values in an array using a compute shader, but I can’t get this to compile - this is my first glsl compute shader, it is very basic, this is a fundamental reduction algorithm that i need to use in offline processing, so far from optimal. The shader window shows this when i click in the file browser

ERROR: 0:14: '=' :  cannot convert from ' temp highp 2-component vector of uint' to ' temp highp 2-component vector of int'
ERROR: 0:14: '' : compilation terminated 
ERROR: 2 compilation errors.  No code generated.

input texture is 512 * 512, global work group size is (64,64,1), local group size (4,4,1), shared memory size, 16.

#[compute]
#version 450

layout(set = 0, binding = 0, rgba8) uniform readnly image2D sourceImage;
layout(set = 0, binding = 1, rgba8) uniform writeonly image2D colorImage;
layout(local_size_x = 4, local_size_y = 4, local_size_z = 1) in;

shared int sdata[16];

void main() {

	ivec2 UV = gl_GlobalInvocationID.xy; 
	
	ivec2 UV_out = ivec2( int( float(UV.x) / 4.0), int( float(UV.y) / 4.0) );
	uint local_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4; 
	
sdata[local_index] =  (int)imageLoad(sourceImage, UV, ivec2(0, 0), ivec2(511, 511) ).r;
	
	memoryBarrierShared();
	barrier();
	
	int min_h =10000.0;
	int max_h = -10000.0;
	for(uint i = 0; i<16; i++){
		
		if( sdata[i] > max_h ){
			max_h = sdata[i];
		} 
		if( sdata[i] < min_h ){
			min_h = sdata[i];
		}
	}
	ivec4 output = ivec4( uint(min_h), uint(max_h), 0,0);

	
	imageStore(colorImage, UV_out, output);
}

What is the need to cast the int to uint when using in a signed vector? Does it work if you just pass ivec4(min_h, max_h, 0, 0)? Or ivec4(int(uint(min_h)), int(uint(max_h)), 0, 0)?

I cast to uint because the message seemed to say that a typecast to uint was the problem …

I ran both and the error is the same … The code has changed … I meant to use 64 in the local group, so its

(8,8,1) instead of (4,4,1)

#[compute]
#version 450

layout(set = 0, binding = 0, rgba8) uniform readnly image2D sourceImage;
layout(set = 0, binding = 1, rgba8) uniform writeonly image2D colorImage;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

shared int sdata[64];

void main() {

	ivec2 UV = gl_GlobalInvocationID.xy; 
	
	ivec2 UV_out = ivec2( int( float(UV.x) / 4.0), int( float(UV.y) / 4.0) );
	uint local_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4; 
	sdata[local_index] =  (int)imageLoad(sourceImage, UV, ivec2(0, 0), ivec2(511, 511) ).r;
	
	memoryBarrierShared();
	barrier();
	
	int min_h =10000.0;
	int max_h = -10000.0;
	for(uint i = 0; i<64; i++){
		
		if( sdata[i] > max_h ){
			max_h = sdata[i];
		} 
		if( sdata[i] < min_h ){
			min_h = sdata[i];
		}
	}
	ivec4 output = ivec4( min_h, max_h, 0,0);
	//ivec4 output = ivec4(int(uint(min_h)), int(uint(max_h)), 0, 0);
	
	imageStore(colorImage, UV_out, output);
}

Oh the issue is probably int min_h = 10000.0;, it should be int min_h = 10000;

I changed that, but the problem is still there

Oh it’s this ivec2 UV = gl_GlobalInvocationID.xy;, gl_GlobalInvocationID is uvec3 not ivec3

now the output says

Failed parse:
ERROR: 0:13: '' :  syntax error, unexpected RIGHT_PAREN, expecting LEFT_PAREN
ERROR: 1 compilation errors.  No code generated.

#[compute]
#version 450

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

layout(set = 0, binding = 0, rgba8) uniform image2D height_image;
layout(set = 0, binding = 1, rgba8) uniform image2D data_output_image;


shared int sdata[64];

void main() {

	ivec2 UV = ivec2( int(gl_GlobalInvocationID.x), int(gl_GlobalInvocationID.y) ); 
	
	ivec2 UV_out = ivec2( int( float(UV.x) / 4.0), int( float(UV.y) / 4.0) );
	uint local_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4; 
	
	sdata[local_index] =  int(imageLoad(height_image, UV, ivec2(0, 0), ivec2(511, 511) ).r);
	
	memoryBarrierShared();
	barrier();
	
	int min_h = 10000;
	int max_h = -10000;
	
	for (uint i = 0; i<64; i++){
		
		if ( sdata[i] > max_h ){
			max_h = sdata[i];
		} 
		if ( sdata[i] < min_h ){
			min_h = sdata[i];
		}
	}
	
	ivec4 output = ivec4( min_h, max_h, 0, 0);
	//ivec4 output = ivec4(int(uint(min_h)), int(uint(max_h)), 0, 0);
	
	imageStore(data_output_image, UV_out, output);
}

You don’t need to ask in a forum to proofread your code just go over it and check it

sorry …

the problem is that the editor is unreliable for this. I can’t see the output of the compiler for any shader codes that I am editing in the script window.

I was duplicating the file after each edit and then checking the result of importing the file.

You can do rightclick on the .glsl file and click “reimport” this will try to recompile the shader and give you error message. With small typo issues like this its often easier to just ask any LLM they will find the issue instantly.
what kind of image load command are you trying to do? Why are you passing two ivec2s?

I dont know I was just actually double checking the image load function … I just need a simple image load with the UV as the global thread index in x and y.

Or just proofread it, it’s not like it’s a lot of code and it’s important to learn how to do this yourself and not rely on lazy tools, or just use your IDE

remove the ivec2s from the command and see if it helps

I got this to compile … ‘output’ was a reserved word, so the variable is called “'output_data_vec”.

But … the program still says the compute pipeline isn’t valid …

#[compute]
#version 450

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

layout(set = 0, binding = 0, rgba8) uniform image2D height_image;
layout(set = 0, binding = 1, rgba8) uniform image2D data_output_image;


shared int sdata[64];

void main() {

	ivec2 UV = ivec2( int(gl_GlobalInvocationID.x), int(gl_GlobalInvocationID.y) ); 
	
	ivec2 UV_out = ivec2( int( float(UV.x) / 4.0), int( float(UV.y) / 4.0) );
	uint local_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4; 
	
	sdata[local_index] =  int(imageLoad(height_image, UV ).r);
	
	memoryBarrierShared();
	barrier();
	
	int min_h = 10000;
	int max_h = -10000;
	
	for (uint i = 0; i<64; i++){
		
		if ( sdata[i] > max_h ){
			max_h = sdata[i];
		} 
		if ( sdata[i] < min_h ){
			min_h = sdata[i];
		}
	}
	
	ivec4 output_data_vec = ivec4( min_h, max_h, 0, 0);
	//ivec4 output = ivec4(int(uint(min_h)), int(uint(max_h)), 0, 0);
	
	imageStore(data_output_image, UV_out, output_data_vec);
}

So the shader compiled? How are you executing the pipeline in gdscript?

I found an addon called EasyCompute …

EasyCompute - Godot Asset Library

So I’ve got a basic scene with the example.gd attached

And the script is modified … The error is now the texture I am trying to create from the noise.

extends Node

var compute: EasyCompute = EasyCompute.new()

func _ready() -> void:
	
	texture_fill()
	
@onready var sprite_2d: Sprite2D = $Sprite2D
## Fill a texture with a the specified color
func texture_fill():
	compute.load_shader("fill", "res://examples/fill9.glsl")
	
	var noise = FastNoiseLite.new()
	var image = noise.get_image(512,512,false,false,true)#   create(64, 64, false, Image.FORMAT_RGBA8)
	if image.is_compressed():
		image.decompress()
	var texture = ImageTexture.create_from_image(image)
	compute.register_texture("sourceImage", 0, 512, 512, image.get_data(), RenderingDevice.DATA_FORMAT_R8G8B8A8_UNORM)

	var output_image = Image.create(128, 128, false, Image.FORMAT_RGBA8)
	var texture2 = ImageTexture.create_from_image(output_image)
	compute.register_texture("colorImage", 1, 128, 128, output_image.get_data(), RenderingDevice.DATA_FORMAT_R8G8B8A8_UNORM)
	
	#var fill_color = PackedFloat32Array()#([1.0, 0.0, 0.0, 1.0]) # RGBA
	#fill_color.resize(16)
	#compute.register_storage_buffer("fill_color", 1, 0, fill_color.to_byte_array())

	compute.execute("fill", 64,64)
	compute.sync()

	var image_data = compute.fetch_texture("colorImage")
	output_image = Image.create_from_data(128, 128, false, Image.FORMAT_RGBA8, image_data)
	texture2.update(output_image)
	sprite_2d.texture = texture2


What does the error say? Does it say something about usage-bits? or RID’s?

The error is from the noise image … I think the format could be wrong … I changed the text name handle to the

`compute.register_texture(“height_image”, 0, 512, 512, image.get_data(), RenderingDevice.DATA_FORMAT_R8G8B8A8_UNORM)`

The problem might be that you are passing the format R8G8B8A8 eventhough you are using a noise-image which only has 1 channel. Try to use R8_UNORM