函数 'texelFetchOffset' 的参数 4 必须是常量表达式

Argument 4 to function 'texelFetchOffset' must be a constant expression

本文关键字:表达式 常量 参数 texelFetchOffset 函数      更新时间:2023-10-16

按照GLSL Cookbook中的示例,我使用以下代码:

vec4 Pass2(){
ivec2 pix = ivec2(gl_FragCoord.xy);
vec4 sum = texelFetch(texSampler, pix, 0) * weight[0];
for(int i = 1; i < 5; i++){
    ivec2 posPixOffs = ivec2(0, pixOffset[i]);
    ivec2 negPixOffs = ivec2(0, -pixOffset[i]);
    sum += texelFetchOffset(texSampler, pix, 0, posPixOffs) * weight[i];
    sum += texelFetchOffset(texSampler, pix, 0, negPixOffs) * weight[i];
}
return sum;
}

其中pixOffset[]定义为

uniform int pixOffset[5] = int[](0, 1, 2, 3, 4);

weight[]只是应用程序客户端的uniform float集合。

texelFetch函数在标题中产生错误。什么是合格的内容表达式,为什么它不被认为是内容表达式?

不应该给统一数组赋常量值。可能有用,但规格里没有。

常量表达式是这样的:

const int pixOffset[5] = int[](0, 1, 2, 3, 4);

这个偏移量应该是一个编译时常量。如果您通过索引传递从常量数组获得的值,则代码通常只有在循环可以展开时才能工作,因此单个texelFetchOffset调用最终会获得偏移量的常量。

在Nvidia上它通常工作,但AMD驱动程序通常不展开循环,可能是因为更有效的循环实现。在这种情况下,偏移量表达式不再是常量,并且使用texelFetchOffset的循环无法编译或链接。

首先回答你关于

的问题

什么符合常量表达式的条件,为什么不认为它是常量表达式?

根据Khronos网站,要被视为常量表达式,表达式必须遵循以下规则之一:

  • 文字值。
  • const限定变量(不是函数参数)使用显式初始化式,但仅当初始化式为自身时下列之一:
    • 常量表达式。
    • 一个初始化列表,它的组件本身就是常量表达式。初始化列表本身不是表达式。
  • 数组的length()函数的结果,但仅当数组有明确的大小时(who的大小必须是常量表达式)。
  • 大多数的结果操作符,只要所有操作数本身都是常量表达式。不在此列表中的操作符是任意赋值操作符(+=等)和逗号操作符。
  • 类型的构造函数的结果,但仅当构造函数的所有参数构造函数本身就是常量表达式。
  • 任何内置函数的返回值,但仅当函数的所有参数本身都是常量表达式时。不透明类型从来不是常量表达式。请注意,函数dFdx, dFdy, fwidth,以及它们的粗和细的变化将返回0,当给定一个常量表达式作为参数时。

同样,根据Khronos on制服,虽然制服是隐式const,但它们不是常量表达式。

pixOffset更改为const,正如David Karlsson上面所说的,应该可以修复它:

const int PixOffset[5] = int[](0,1,2,3,4);

如果没有,那么问题是你的GPU可能没有展开for-loop。因此,i变量不是常量,表达式ivec2(0, PixOffset[i])也不是常量。如果是这种情况,您要么必须手动展开它(就像我下面所做的那样),要么使用另一种策略(如sum += texelFetch(Texture0, pix + vec2(PixOffset[i], 0), 0) * Weight[0];)。

vec4 sum = texelFetch(textureUniform, ivec2(gl_FragCoord.xy), 0) * gaussianWeight[0];
sum += texelFetchOffset(textureUniform, ivec2(gl_FragCoord.xy), 0, ivec2( PixOffset[0], 0)) * gaussianWeight[0];
sum += texelFetchOffset(textureUniform, ivec2(gl_FragCoord.xy), 0, ivec2(-PixOffset[0], 0)) * gaussianWeight[0];
sum += texelFetchOffset(textureUniform, ivec2(gl_FragCoord.xy), 0, ivec2( PixOffset[1], 0)) * gaussianWeight[1];
sum += texelFetchOffset(textureUniform, ivec2(gl_FragCoord.xy), 0, ivec2(-PixOffset[1], 0)) * gaussianWeight[1];
...