我最近在使用修改(并复制出)其中一个输入参数的GLSL函数时遇到了一些困惑。让我们假设这是函数:
float v(inout uint idx) {
return 3.14 * idx++;
}
现在让我们以一种可能模糊的方式使用该功能:
uint idx = 0;
const vec4 values = vec4(v(idx), v(idx), v(idx), v(idx));
我们可以合理地假设在调用vec4
构造函数返回后,我们的向量values
应该等于{0.00, 3.14, 6.28, 9.42}
而idx
应该等于4
。但是,我想知道GLSL中的函数参数的评估顺序是否定义得很好,如果是,那么上面假定的顺序是否正确。或者,这是否会导致(依赖于实现)未定义的行为?
当然,我咨询了GLSL spec (v4.6, rev3, §6.1.1, p116, "Function Calling Conventions"),其中有以下内容:
所有参数都是在呼叫时评估,从左到右按顺序评估一次。
到目前为止一切顺利。但接下来的页面更远:
输出参数被复制回调用者的顺序是未定义的。
我并不完全清楚这第二个陈述的重要性。
float doWork(inout uint v1, inout uint v2) {...}
是否意味着v1
和v2
被复制的顺序是不确定的?如果您执行的操作类似于传递相同的局部变量来代替两个参数,那么这很重要。idx
的更新顺序未定义,因此values
的顺序也未定义?不言而喻,在vec4
构造函数调用之前使用多个变量来保存这些值可以完全避免这个问题,但这不是重点。相反,我想知道标准的这一部分是如何解释的,以及我的第一个例子是否会导致idx
包含未定义的值。