Interfaces like Cg 1.2

I don’t know if some of you have used Softimage XSI, or Maya. With both system you can create shader graph. Instead of a monolitic shader proposed by the OpenGL 2.0 API, you have many shaders and the output one connects to the uniform of an other.

Nvidia has some steps in advance for that type of advance shader, and I really hope that the ARB will soon fix this disparity.

I agree that interfaces are very powerful. They provide a nice way to separate material and light shaders. I hope that they will be also supported in glsl.
Is it or will it be possible to use Cg to compile to GLSL ? Then there should be no problem using Cg and even access advanced fragment shader features on future ATI hardware.

Glslang, and the glslang API, are uniquely suited to taking pieces of shaders and fusing them together. It even lets you compile shaders without a main, like C/C++ libraries, and link them together after the fact.

Yes you can link shader objects and functions are connected by name and parameters, but with interfaces you can select the linked set of functions individually for each instance of an interface type.

with interfaces you can select the linked set of functions individually for each instance of an interface type.
i’ll bet they pull this off with the equivalent of hlsl’s runtime pixel/vertex fragment linking (very lightweight). you can slap together some number of shader “fragments” to form a complete shader on the fly.

regards,
bonehead

I looked at the DX SDK and it is even written in the help that it’s very light weight to link shader fragments. But the glLinkProgram function in OpenGL is very slow with NVidia drivers. That makes it impossible to create a glsl shader dynamically.

But the glLinkProgram function in OpenGL is very slow with NVidia drivers. That makes it impossible to create a glsl shader dynamically.
Then complain to nVidia about how they implement the language. The ARB can’t force performance on an implementation; they can only require conformance.

glLinkProgram has interesting options for putting programs together, but it does not serve what Cg interfaces bring. It is obvious that the ones who wrote the GLSL were never in touch with object oriented language.

You cannot do for example:

foreach light
result_color += light.dot_nl() *
light.color() * color

where light is a dynamic array made of a mix of spot lights, point lights and directional lights. If there were interfaces of some sort, all instance of light would derive from a base_light.

A spot for example would return black if the illumination point is outside the cone, while the implementation of the point light is different.

This is unfortunately, not yet available.

The people who created GLSL, 3D labs, wanted to create a language that was simple enough. GLSL is not C++ or C. It’s a minimum high level language. Neverthless, there are structures in GLSL. Light objects are stored in structures, but there is no inheritance or the notion of public, private and protected. There is no polymorphism, operator overloading, …

They should have included (function) pointers for uniform variables. Changing such a variable obviously requires recompilation, but it would be very flexible.

You cannot do for example:
Last time I checked Cg (which, admittedly, was last year), it didn’t offer object oriented programming either.

Personally, I see the need to objectify everything to be simply wrongheaded. OOP is best used for large, potentially multi-coder systems. This does not in any way resemble shaders. Shaders do not need polymorphism. It might make some bits of the code slightly more elegant, but slight inelegance is preferable to nothing.

More importantly, without any hope of a hardware implentation of polymorphism (we don’t even have a stack in a shader, let alone function pointers), there’d be no real point in this feature.

They should have included (function) pointers for uniform variables. Changing such a variable obviously requires recompilation, but it would be very flexible.
Well, if it requires recompilation (particularly implicit recompilation), what good is it from a performance perspective? You may as well have just modified that shader yourself and recompiled/linked.

Originally posted by Korval:

we don’t even have a stack in a shader, let alone function pointers

FYI: NV has a stack in the vertex program.
http://oss.sgi.com/projects/ogl-sample/registry/NV/vertex_program3.txt

NV has a stack in the vertex program.
It has a stack for addresses. It does not have a stack that can be used for recursive function calls with parameters

Shaders do not need polymorphism.
Shaders must become modular and reusable.

Well, if it requires recompilation (particularly implicit recompilation), what good is it from a performance perspective? You may as well have just modified that shader yourself and recompiled/linked.
It could be optimized by the driver because it can reuse parts of the shader. I’m not sure, but doesn’t the GF embed all uniform variables as constants in the shader? Then changing a uniform also updates the shader.

Shaders must become modular and reusable.
Spoken like a born-again OOP programmer.

Modular and reusable code existed long before OOP and it will exist after OOP has been replaced by some other paradigm. OOP is not the only means of going about creating modular and reusable code.

I’m not sure, but doesn’t the GF embed all uniform variables as constants in the shader?
There’s a big difference between changing a few bytes in some compiled machine code and actually recompiling it from scratch.

Spoken like a born-again OOP programmer.

Modular and reusable code existed long before OOP and it will exist after OOP has been replaced by some other paradigm. OOP is not the only means of going about creating modular and reusable code.

I’ve never written that OOP is the only correct way, although it is probably not the worst. I mentioned that uniform pointers would be nice in the c-style glsl language.
Of course you can do it all by yourself emulating this functionality with macros or even doing some preprocessing, but glsl is a high level language and not a compile target.

There’s a big difference between changing a few bytes in some compiled machine code and actually recompiling it from scratch.

When changing a function pointer,only the call instruction must be changed.

but glsl is a high level language and not a compile target
In these days of heavy macro and template metaprogramming (let alone generating code via external tools), the difference between a “language” and a “compile target” is rather blury. It’s hardly unreasonable for glslang to actually be the expected compile target from a higher-level language. Renderman Shaders, for example, could be compiled into one or more glslang shaders.

When changing a function pointer,only the call instruction must be changed.
Unless this was a good compiler, in which case the function was never linked to begin with (dead-code elimination. Keeps down temporary and instruction count). At which point, you need to re-link and re-verify limits.

Also, a good compiler might inline that code if it was only used once. If it did, then you need to do a pretty hefty re-link process to move the new code into position.

Lastly, the functionality you’re asking for is crippled anyway. It’s compile-time/link-time binding rather than runtime (during the actual execution of the shader) binding. The “list of lights” example needs runtime binding of function pointers. It’s a far cry from even C-style function pointers, let alone polymorphism.

For function pointers, you cold just do

uniform int whichone;

switch(whichone)
{
case 1:
  Func1();
  break;
case 2:
  Func2();
  break;
}

If the driver is smart enough, it can generate 2 shaders and pick the right one to load as you change whichone.

Originally posted by V-man:
[b]For function pointers, you cold just do

uniform int whichone;

switch(whichone)
{
case 1:
Func1();
break;
case 2:
Func2();
break;
}

If the driver is smart enough, it can generate 2 shaders and pick the right one to load as you change whichone.[/b]

That’s what I was thinking, too. Just use conditional branches instead of demanding gasp function pointers.
Branches might even work reasonably well in hardware.