PDA

View Full Version : Nested functions, aborting!



Zildjian
01-09-2011, 07:29 PM
Hi all -- I'm running into an odd error using NVIDIA drivers on Mac OS X Snow Leopard. The app actually exits during compile, with the following error text:


(0) : fatal error C9999: Nested functions, aborting!
Cg compiler terminated due to fatal error

This same shader code compiles and executes fine with NVIDIA's Windows driver, not even a warning. Only the OS X Snow Leopard drivers are the issue.

A little web search reveals the VTK project is encountering the same issue:
http://www.vtk.org/Bug/print_bug_page.php?bug_id=10716

Any ideas how I might work around this? It doesn't appear that Apple intends to provide a fix anytime soon.

My driver version appears to be 1.6.26 (as reported by GLView).

Alfonse Reinheart
01-09-2011, 08:03 PM
Are you nesting functions? What is your shader?

aqnuep
01-10-2011, 03:17 AM
If you really use nested functions then you should know that GLSL does not allow anything like that. The possible reason why it works on NVIDIA Windows drivers is because NVIDIA tends to not really care about the restrictions of GLSL as they use the same backend compiler for GLSL as they use for Cg, which have different syntax.

Zildjian
01-10-2011, 07:49 AM
Wow. Nesting functions isn't allowed, eh? I guess I'll have to read the spec a little closer, as this is news to me. Thanks.

Zildjian
01-10-2011, 08:26 AM
Just spent a bit going over the spec, and I don't see where nested functions are disallowed. Can you quote the relevant spec language, or point me to the section?

Here's what I read:

* A function call returning a value is an expression (section 5.9).
* A function-definition contains a statement-list, which contains a statement, which contains a simple-statement, which contains an expression-statement (section 6).

These definitions are consistent in spec versions 1.20 through 4.00.

I'll go back and check my shader to ensure that my nested functions actually return values; if they return void, that's the only way I can see that I might be in violation of the spec.

mbentrup
01-10-2011, 08:36 AM
A function definition may contain arbitrary function calls, but not (nested) function definitions.

aqnuep
01-10-2011, 09:11 AM
Yes, mbentrup is right. You confuse two different things:

- nested function calls, i.e. calling a function from another function is allowed (actually the main() is also a function so not allowing it would mean that there is no possibility to make user defined functions).

- nested functions (nested function definitions) which are not allowed neither in C nor in GLSL

Jan
01-10-2011, 09:36 AM
I was once told by someone from nVidia that C9999 errors are not supposed to happen and are considered to be compiler-errors.

I once had one myself, and nVidia was extremely quick to take a look at it, just because I had postet the "C9999" part in the topics headline, such that someone from nVidia saw it.

So, maybe post it in nVidias forum or something like that, maybe they ARE interested to see your particular shader.

Jan.

Alfonse Reinheart
01-10-2011, 09:43 AM
Just spent a bit going over the spec, and I don't see where nested functions are disallowed.

From the spec:


Recursion is not allowed, not even statically. Static recursion is present if the static function-call graph of
a program contains cycles. This includes all potential function calls through variables declared as subroutine uniform (described below).

I'm guessing that this is what the error meant by "nested functions."

aqnuep
01-10-2011, 11:21 AM
I'm guessing that this is what the error meant by "nested functions."
That makes sense. Anyway, you should believe much more in the MacOSX driver as there the OpenGL driver is developed by Apple and only the low level stuff is maybe provided by NVIDIA, but the GLSL compiler is definitely Apple's work. That's the difference, because NVIDIA GLSL compiler usually allows much more things than it is specified in the GL spec.

AFAIK NVIDIA supports recursion so maybe they exposed this not only for Cg and CUDA but also for GLSL. Still if this is the case, your GLSL code is invalid.

Zildjian
01-10-2011, 12:06 PM
Thanks, all. There is no recursion in my shader; the language spec is very clear that this is not allowed.

Yes, I might be confused on the difference between a "nested function definition" and a "nested function call". I know what the latter is, and I believe GLSL allows it.

But I'm not clear on what a "nested function definition" is. Can someone post an example?

Just taking a guess... Does the following qualify as a nested function definition?

void functionA();
void functionB()
{
}
void functionA()
{
}

My code has quite a bit of stuff like this.

Zildjian
01-10-2011, 02:24 PM
Well, I am not doing this:

void functionA()
{
void functionB()
{
}
}

Is that what is meant by "nested function definition"? If so, something else is to blame.

aqnuep
01-11-2011, 01:59 AM
The sample mentioned first is forward declaration, nested function definition is the one that you mentioned in your last post.

If you are not using that syntax then I'm not sure what's going on. Please post your shader so that we can check what could cause the issue.

Zildjian
01-11-2011, 08:31 AM
Thanks for confirming my suspicions.

I'm using shader composition with a scene graph. I'm dealing with several hundred lines of code in dozens of shader source files, individually compiled and combined / linked together into several different program objects. I agree it would be valuable to create a small OpenGL-only app that can reproduce the problem, it would be a great diagnostic tool for this project, but currently it doesn't exist.

In my first post on this thread, I included a link to a bug report from the VTK project. So that would be one way for people to obtain code that reproduces the issue.

Zildjian
01-11-2011, 01:14 PM
Just to put a cap on this... An associate noticed that the VTK issue seems to be related to use of discard. As an experiment, I commented out all calls to discard in my shaders. The compiler crash went away.

I'm now in the process of rearchitecting the project to use alpha test to discard fragments (instead of calling discard). This is undesirable for a number of reasons, but keeps the project moving forward rather than spending time writing reproducer code and waiting for a driver/compiler fix from (first) NVIDIA and (then) Apple.