为什么Cg编译器的后期版本使用更多的指令生成着色器?



我有一个着色器,看起来像这样:

void main( in   float2              pos         : TEXCOORD0,
           in   uniform sampler2D   data        : TEXUNIT0,
           in   uniform sampler2D   palette     : TEXUNIT1,
           in   uniform float       c,
           in   uniform float       th0,
           in   uniform float       th1,
           in   uniform float       th2,
           in   uniform float4      BackGroundColor,
           out  float4              color       : COLOR
         )
{
    const float4 dataValue = tex2D( data, pos );
    const float vValue = dataValue.x;
    const float tValue = dataValue.y;
    color = BackGroundColor;
    if ( tValue <= th2 )
    {
        if ( tValue < th1 )
        {
            const float vRealValue = abs( vValue - 0.5 );
            if ( vRealValue > th0 )
            {
                // determine value and color
                const float power = ( c > 0.0 ) ? vValue : ( 1.0 - vValue );
                color = tex2D( palette, float2( power, 0.0 ) );
            }
        }
        else
        {
            color = float4( 0.0, tValue, 0.0, 1.0 );
        }
    }
}

我像这样编译它:

cgc -profile arbfp1 -strict -O3 -q sh.cg -o sh.asm

现在,不同版本的Cg编译器产生不同的输出。

  • cgc版本2.2.0006正在使用18条指令将着色器编译成汇编代码:

    !!ARBfp1.0
    PARAM c[6] = { program.local[0..4],{ 0, 1, 0.5 } };
    TEMP R0;
    TEMP R1;
    TEMP R2;
    TEX R0.xy, fragment.texcoord[0], texture[0], 2D;
    ADD R0.z, -R0.x, c[5].y;
    CMP R0.z, -c[0].x, R0.x, R0;
    MOV R0.w, c[5].x;
    TEX R1, R0.zwzw, texture[1], 2D;
    SLT R0.z, R0.y, c[2].x;
    ADD R0.x, R0, -c[5].z;
    ABS R0.w, R0.x;
    SGE R0.x, c[3], R0.y;
    MUL R2.x, R0, R0.z;
    SLT R0.w, c[1].x, R0;
    ABS R2.y, R0.z;
    MUL R0.z, R2.x, R0.w;
    CMP R0.w, -R2.y, c[5].x, c[5].y;
    CMP R1, -R0.z, R1, c[4];
    MUL R2.x, R0, R0.w;
    MOV R0.xzw, c[5].xyxy;
    CMP result.color, -R2.x, R0, R1;
    END
    # 18 instructions, 3 R-regs
    
  • cgc版本3.0.0016正在使用23条指令将着色器编译成汇编代码:

    !!ARBfp1.0
    PARAM c[6] = { program.local[0..4], { 0, 1, 0.5 } };
    TEMP R0;
    TEMP R1;
    TEMP R2;
    TEX R0.xy, fragment.texcoord[0], texture[0], 2D;
    ADD R1.y, R0.x, -c[5].z;
    MOV R1.z, c[0].x;
    ABS R1.y, R1;
    SLT R1.z, c[5].x, R1;
    SLT R1.x, R0.y, c[2];
    SGE R0.z, c[3].x, R0.y;
    MUL R0.w, R0.z, R1.x;
    SLT R1.y, c[1].x, R1;
    MUL R0.w, R0, R1.y;
    ABS R1.z, R1;
    CMP R1.y, -R1.z, c[5].x, c[5];
    MUL R1.y, R0.w, R1;
    ADD R1.z, -R0.x, c[5].y;
    CMP R1.z, -R1.y, R1, R0.x;
    ABS R0.x, R1;
    CMP R0.x, -R0, c[5], c[5].y;
    MOV R1.w, c[5].x;
    TEX R1, R1.zwzw, texture[1], 2D;
    CMP R1, -R0.w, R1, c[4];
    MUL R2.x, R0.z, R0;
    MOV R0.xzw, c[5].xyxy;
    CMP result.color, -R2.x, R0, R1;
    END
    # 23 instructions, 3 R-regs
    

奇怪的是,cg 3.0的优化水平似乎没有影响任何事情。

谁能解释一下这是怎么回事?为什么优化不起作用,为什么当我用cg 3.0编译时着色器更长?

请注意,我从编译的着色器中删除了注释。

这可能不是问题的真正答案,但可能会提供一些更多的见解。我检查了一下生成的汇编代码,并将其转换回高级代码。我试图尽可能地压缩它,并删除所有的副本和隐含地跟随高级操作的临时文件。我使用b变量作为临时bool,使用f变量作为临时float。第一个(2.2版本)是:

power = ( c > 0.0 ) ? vValue : ( 1.0 - vValue );
R1 = tex2D( palette, float2( power, 0.0 ) );
vRealValue = abs( vValue - 0.5 );
b1 = ( tValue < th1 );
b2 = ( tValue <= th2 );
b3 = b1;
b1 = b1 && b2 && ( vRealValue > th0 );
R1 = b1 ? R1 : BackGroundColor;
color = ( b2 && !b3 ) ? float4( 0.0, tValue, 0.0, 1.0 ) : R1;

,第二个(带3.0)是:

vRealValue = abs( vValue - 0.5 );
f0 = c;
b0 = ( 0 < f0 );
b1 = ( tValue < th1 );
b2 = ( tValue <= th2 );
b4 = b1 && b2 && ( vRealValue > th0 );
b0 = b0;
b3 = b1;
power = ( b4 && !b0 ) ? ( 1.0 - vValue ) : vValue;
R1 = tex2D( palette, float2( power, 0.0 ) );
R1 = b4 ? R1 : BackGroundColor;
color = ( b2 && !b3 ) ? float4( 0.0, tValue, 0.0, 1.0 ) : R1;

大多数部分本质上是相同的。第二个程序做一些不必要的操作。它将c变量复制到临时变量中,而不是直接使用它。而且它在算力的时候把vValue1-vValue切换了,所以需要否定b0(导致多出一个CMP),而第一个根本不使用临时(直接使用CMP而不是SLTCMP)。它还在此计算中使用b4,这是完全不必要的,因为当b4为假时,纹理访问的结果无论如何都是无关的。这导致了多一个&&(用MUL实现)。还有从b1b3的不必要的复制(在第一个程序中是必要的,但在第二个程序中不是)。以及从b0复制到自身的极其无用的复制(伪装成ABS,但由于值来自SLT,它只能是0.0或1.0,并且ABS退化为MOV)。

所以第二个程序与第一个程序非常相似,只是有一些额外的,但IMHO完全无用的指令。与之前的(!)版本相比,优化器似乎做得更差。由于Cg编译器是nVidia的产品(而不是来自其他未命名的图形公司),这种行为真的很奇怪。

相关内容

  • 没有找到相关文章

最新更新