Can I perform atomic operations on a function parameter?

#1

Hi, I would like to pass a struct contained in a shader storage buffer to a function and perform some atomic additions on a uint member of the struct. However the shader won’t compile because:

A shader will fail to compile if the value passed to the mem argument of an atomic memory function does not correspond to a buffer or shared variable

I was wondering if there’s some variable qualifier to enforce a function parameter to be backed by a buffer. As far as I know in, out, inout and const in are the only available parameter qualifiers, but maybe I’m missing something here.

EDIT:

Actually, thinking about how GLSL functions copy arguments in and out, I’m guessing it’s not possible, is it?

#2

What GL driver (vendor/version) are you using?

I’m curious which one isn’t just inlining the function and automatically realizing what inputs back the function arguments?

Also, could you post a short shader that illustrates the problem? I (and maybe others too) would be interested in compiling it on a few drivers to see what behavior I get here.

#3

No, it isn’t. If the struct member is in an array, you could pass an array index. But that’s about it.

I don’t see how that matters. Atomic functions cannot be called on things that aren’t buffer variables (or shared variables). As such, this:

void func(inout SomeStruct val)
{
  atomicAdd(val.x, 5);
}

Is explicitly not allowed by the rules of GLSL, even if you call it by passing in a SomeStruct member of a buffer variable. Inlining cannot change those rules.

#4
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4

The (compute) shader is as simple as:

#version 450 core

struct Data
{
	uint numGeneratedVertices;

	// ... other stuff
};

layout(std430) buffer DataBuffer
{
	Data data;
};

void generateGeometry(/* inout? */ Data data, ivec3 index)
{
	// Bunch of stuff

	uint numVertices = atomicAdd(data.numGeneratedVertices, 3);
}

layout(local_size_x = 36, local_size_y = 1, local_size_z = 36) in;
void main()
{
	// ...
	generateGeometry(data, ivec3(gl_GlobalInvocationID));
}

I guessed so.