澄清GLSL函数调用约定

时间:2018-02-23 04:19:28

标签: opengl glsl shader gpgpu

我最近在使用修改(并复制出)其中一个输入参数的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) {...}是否意味着v1v2被复制的顺序是不确定的?如果您执行的操作类似于传递相同的局部变量来代替两个参数,那么这很重要。
  • 或者,它是否意味着在前面的示例中,变量idx的更新顺序未定义,因此values的顺序也未定义?
  • 或许这两种情况都未定义?也就是说,整个代码行上的所有复制操作可能都是以无序的方式发生的?

不言而喻,在vec4构造函数调用之前使用多个变量来保存这些值可以完全避免这个问题,但这不是重点。相反,我想知道标准的这一部分是如何解释的,以及我的第一个例子是否会导致idx包含未定义的值。

0 个答案:

没有答案