Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have this shader that works well on my computer (using an ATI HD 5700). I have a loop iterating between two constant values, which is, afaik, acceptable in a glsl shader. I write stuff in two arrays in this loop.

#define NB_POINT_LIGHT 2

...

varying vec3 vVertToLight[NB_POINT_LIGHT];
varying vec3 vVertToLightWS[NB_POINT_LIGHT];

...

void main()
{
    ...
    for (int i = 0; i < NB_POINT_LIGHT; ++i)
    {
        if (bPointLightUse[i])
        {
            vVertToLight[i] = ConvertToTangentSpace(ShPointLightData[i].Position - WorldPos.xyz);
            vVertToLightWS[i] = ShPointLightData[i].Position - WorldPos.xyz;
        }
    }
    ...
}

I tried my program on another computer equipped with an nVidia GTX 560 Ti, and it fails to compile my shader. I get the following errors (94 and 95 are the lines of the two affectations) when calling glLinkProgram:

Vertex info
-----------
0(94) : error C5025: lvalue in assignment too complex
0(95) : error C5025: lvalue in assignment too complex

I think my code is valid, I don't know if this comes from a compiler bug, a conversion of my shader to another format from the compiler (nvidia looks to convert it to CG), or if I just missed something.

I already tried to remove the if (bPointLightUse[i]) statement and I still have the same error. However, if I just write this:

vVertToLight[0] = ConvertToTangentSpace(ShPointLightData[0].Position - WorldPos.xyz);
vVertToLightWS[0] = ShPointLightData[0].Position - WorldPos.xyz;
vVertToLight[1] = ConvertToTangentSpace(ShPointLightData[1].Position - WorldPos.xyz);
vVertToLightWS[1] = ShPointLightData[1].Position - WorldPos.xyz;

Then I don't have the error anymore, but it's really unconvenient so I would prefer to keep something loop-based.

Here is the more detailled config that works:

Vendor: ATI Technologies Inc.
Renderer: ATI Radeon HD 5700 Series
Version: 4.1.10750 Compatibility Profile Context
Shading Language version: 4.10

And here is the more detailed config that doesn't work (should also be compatibility profile, although not indicated):

Vendor: NVIDIA Corporation
Renderer: GeForce GTX 560 Ti/PCI/SSE2
Version: 4.1.0
Shading Language version: 4.10 NVIDIA via Cg compiler
share|improve this question
    
Maybe try to add #pragma unroll just above the for loop. –  Sam Hocevar May 31 '12 at 7:04

1 Answer 1

up vote 2 down vote accepted

Doing some searching for "error C5025: lvalue in assignment too complex" suggests that GPUs don't like writing to scattered memory addresses that aren't determined til runtime.

Your shader compiling on one card, and not on the other may or may not be the result of different number of available registers.

Unrolling the loop manually, like you did, eliminates the problem. Ideally, the compiler should unroll small loops by itself, as this answer suggests the compiler may be unable to unroll the loop on it's own though. (which is strange, since NB_POINT_LIGHT is not a variable but a preprocessor definition, so at compile time the loop's extent should be known)

As Sam suggested, #pragma unroll might help to get the compiler to unroll the loop, however these directives can be different for nvidia and amd specific compilers, maybe also try #pragma optionNV(unroll all).

If that also doesn't help, maybe try replacing NB_POINT_LIGHT in your loop with 2, and if necessary combine with the unroll directives, again.

share|improve this answer
    
#pragma unroll didn't work, but #pragma optionNV(unroll all) fixed the problem. Thanks for the help! –  Benlitz Jun 1 '12 at 10:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.