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

时间:2014-08-22 05:28:48

标签: c++ opengl glsl gaussian

根据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函数会在标题中产生错误。 什么是有限的表达,为什么这不被认为是一个?

3 个答案:

答案 0 :(得分:2)

您不应该为统一数组指定常量值。它可能有效,但它不是规范的一部分。

常量表达式如下:

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

答案 1 :(得分:0)

偏移量应该是编译时常量。如果通过索引传递从常量数组​​获得的值,则代码通常仅在循环可以展开时才起作用,以便单个texelFetchOffset调用最终为偏移量的常量。

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

答案 2 :(得分:0)

首先,在

上回答您的问题
  

什么是常量表达式?为什么不将其视为常量表达式?

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

  
      
  • 文字值。
  •   
  • 一个const限定变量(不是函数参数)   使用显式初始化程序,但仅当初始化程序本身是   以下之一:      
        
    • 一个常量表达式。
    •   
    • 初始化程序列表,其组成部分本身是常量表达式。初始化程序列表本身不是表达式。
    •   
  •   
  • 数组的length()函数的结果,但仅当数组具有显式的大小(其大小必须为常量表达式)时。
  •   
  • 大多数的结果   运算符,只要所有操作数本身都是常量   表达式。不在此列表中的运算符是任何分配   运算符(+ =等)和逗号运算符。
  •   
  • 一个类型的构造函数的结果,但仅当   构造函数本身就是常量表达式。
  •   
  • 任何内置函数的返回值,但前提是该函数的所有参数本身都是常量表达式。不透明类型绝不是常量表达式。请注意,当给定常量表达式作为参数时,函数dFdx,dFdy,fwidth及其粗略和精细变化将返回0。
  •   

此外,根据Uniforms的Khronos,尽管Uniforms是隐式const,但它们不是常量表达式。

如上文David Karlsson所述,将pixOffset更改为const应该解决:

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];
...