Compute shader "AtomicAdd" doesn't seem to work (at all)

Godot Version 4.3 stable

I’m new to compute shaders in Godot, only with a slight amount of experience in Unity compute shaders. I’m trying to use a compute shader to calculate some outlines on an image, but i’m not even close to that currently. I don’t understand what i’m doing or what the engine is doing.

So just to get a little hold of it, i am now trying to count the amount of red pixels in an image. But since i want to parse data to an array of vector3’s for what i really need, i have all my output parameters in a single buffer. But it’s like the shader can’t read a variable from the buffer.
(In the GLSL shader below): I don’t think it actually increments the nCells value, why?

I want to mention that the code has gotten gradually worse, as well as my sanity. So that’s why the functions are called “createThing” and “doThing”.

GLSL code ↓:

#[compute]
#version 430

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

layout(set = 0, binding = 0, std430) buffer outputBuffer {
    ivec3 cells[100];
    int nCells;
} outBuf;


layout(set = 0, binding = 1) uniform sampler2D tex;


void main() {
    if (texture(tex, vec2(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y)).r > 0.5) {
        atomicAdd(outBuf.cells[outBuf.nCells].z, 1); 
        atomicAdd(outBuf.nCells, 1);
    }
}

If it matters, here’s the GDscript code:

extends Node2D

@export var texture: Texture2D


 
var rd: RenderingDevice
var shader
var pipeline
var buffer
 
var buffer_uniform
var v_tex
var samp
var tex_uniform
 
var uniform_set 

# Called when the node enters the scene tree for the first time.
func doThing() -> void:
	var compute_list = rd.compute_list_begin()
	
	rd.compute_list_bind_compute_pipeline(compute_list, pipeline)
	
	rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0)
	
	rd.compute_list_dispatch(compute_list, texture.get_size().x/8, texture.get_size().y/8, 1)
	
	rd.compute_list_end()
	rd.submit()
	
	rd.sync()
	
	var byte_data = rd.buffer_get_data(buffer)
	var output := byte_data.to_int32_array()
	print("Output as int array: ", output)
	var nCellsOut = output[output.size() - 1]
	print("Number of cells: ", nCellsOut)
	
	var cellsArray = PackedVector3Array([])
	cellsArray.resize(100) 
	cellsArray = cellsArray.to_byte_array()
	var nCells = PackedInt32Array([0]).to_byte_array()
	
	var pbb = cellsArray+nCells
	
	rd.buffer_update(buffer, 0, pbb.size(), pbb)

func createThing() -> void:
	rd = RenderingServer.create_local_rendering_device()
	
	var shader_file = load("res://assets/scenes/WorldGenerator/outlines.glsl")
	var shader_spirv = shader_file.get_spirv()
	shader = rd.shader_create_from_spirv(shader_spirv)
	pipeline = rd.compute_pipeline_create(shader)
	
	var cellsArray = PackedVector3Array([])
	cellsArray.resize(100) 
	cellsArray = cellsArray.to_byte_array()
	var nCells = PackedInt32Array([0]).to_byte_array()
	
	var pba = cellsArray+nCells
	
	buffer = rd.storage_buffer_create(pba.size(),pba)
	
	buffer_uniform = RDUniform.new()
	buffer_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER
	buffer_uniform.binding = 0
	buffer_uniform.add_id(buffer)
	
	
	
	var img = texture.get_image()
	var img_pba = img.get_data()
	
	var fmt = RDTextureFormat.new()
	fmt.width = texture.get_size().x
	fmt.height = texture.get_size().y
	fmt.usage_bits = RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT | RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT
	fmt.format = RenderingDevice.DATA_FORMAT_R8G8B8A8_SRGB
	
	v_tex = rd.texture_create(fmt, RDTextureView.new(), [img_pba])
	
	var samp_state = RDSamplerState.new()
	samp_state.unnormalized_uvw = true
	samp = rd.sampler_create(samp_state)
	
	tex_uniform = RDUniform.new()
	tex_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE
	tex_uniform.binding = 1
	tex_uniform.add_id(samp)
	tex_uniform.add_id(v_tex)
	
	uniform_set = rd.uniform_set_create([buffer_uniform,tex_uniform], shader, 0)
	
	

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _ready() -> void:
	createThing()

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		var time = Time.get_ticks_msec()
		for i in 1:
			doThing()
		print("Done in ",str(Time.get_ticks_msec()-time)," milliseconds")