views:

36

answers:

1

I came across a weird behavior of HLSL. I am trying to use an array that is contained within a struct, like this (Pixel Shader code):

struct VSOUT {
    float4 projected : SV_POSITION;
    float3 pos: POSITION;
    float3 normal : NORMAL;
};


struct Something  {
    float a[17];
};


float4 shMain (VSOUT input) : SV_Target {
    Something s;

    for (int i = 0; i < (int)(input.pos.x * 800); ++i)
        s.a[(int)input.pos.x] = input.pos.x;

    return col * s.a[(int)input.pos.x];
}

The code makes no sense logically, it's just a sample. The problem is that when I try to compile this code, I get the following error (line 25 is the for-loop line):

(25,7): error X3511: Forced to unroll loop, but unrolling failed.

However, when I put the array outside the struct (just declare float a[17] in shMain), everything works as expected.

My question is, why is DirectX trying to unroll the (unrollable) for-loop when using the struct? Is this a documented behavior? Is there any available workaround except for putting the array outside the struct?

I am using shader model 4.0, DirectX 10 SDK from June 2010.

EDIT: For clarification I am adding the working code, it only replaces usage of the struct Something with plain array:

struct VSOUT {
    float4 projected : SV_POSITION;
    float3 pos: POSITION;
    float3 normal : NORMAL;
};


float4 shMain (VSOUT input) : SV_Target {
    float a[17];  // Direct declaration of the array

    for (int i = 0; i < (int)(input.pos.x * 800); ++i)
        a[(int)input.pos.x] = input.pos.x;

    return col * a[(int)input.pos.x];
}

This code compiles and works as expected. It works even if I add [loop] attribute in front of the for-loop which means it is not unrolled (which is a correct behavior).

+1  A: 

I'm not sure but what I know is that the hardware schedule and process fragments by block of 2x2 (for computing derivatives). This could be a reason that fxc try to unroll the for loop so that the shader program is executed in lockstep mode.

Also did you try to use [loop] attribute for generating code that uses flow control?

Stringer Bell
Thanks for your reply. I actually do not use the VSOUT structure to store the array, it's the struct named `Something` that makes trouble. I edited my post to show also the working code. I tried packing the array to float4 but the behavior is the same. `[loop]` just gives a slightly different message: Cannot unroll loop market with `[loop]`. I am also not using any ddx/ddy/sampler functions (at least not intentionally) that would require computation of the derivatives.
dark_charlie
Ah I see now, this is strange. So this has nothing to do with register usage then. About ddx/ddy I think this doesn't matter if you use it or not, hardware will always process fragments by quad because of efficiency reasons. You should ask microsoft. Maybe it's just a `fxc` compiler limitation.
Stringer Bell
After some more testing there really seems to be no other option than to put my arrays outside the struct.
dark_charlie