The future of vertex + fragment programs

Hi,

my 3d engine is at a point where several decisions have to be made (which is also the reason for my shadow thread), so I guess I will ask some questions regarding this in the next time. One of the is this one.

The program uses ARB_vertex_program and NV_fragment_program for rendering, and I would like to stick with that… but as glSlang seems to be more fashionable, how future-proof are these extensions? Will everything be converted to glslang or will new hardware features (i.e., capabilities of vertex/fragment shaders) also be accessible from those assembler-style extensions?

Another little bit, for performance reasons, I use NV_fragment_program instead of ARB_fragment_program (and will probably change vertex program to use that, too), thus sacrificing the ability to use ati hardware. I guess with geforce 6, this will no longer be neccessary?

Another point on that, if the ARB approved way of vertex and fragment programs (ARB_…) is slower than the NV_ way of doing this (when using the high precision registers), I guess this will also apply to glslang? So on geforce fx, apart from the fact that they do not support glslang at the moment anyway (afaik), NV_… will still be faster?

You might consider abstracting your shader interface such that it’s not dependent on a particular implementation; the idea being that you can make your interface future proof, if not the implementation (nigh impossible). CGFX, for example, attempts to accpomplish this through ‘techniques’, and it’s not a bad idea. Scripts really come in handy for this kind of abstraction. I script everything that isn’t nailed to the floor, it just gives you so much insulation and flexibility.

how future-proof are these extensions?
My guess is that you will never see an update to either of these extensions again. Hardware may still support them, but you won’t be able to do what modern hardware can do.

Another little bit, for performance reasons, I use NV_fragment_program instead of ARB_fragment_program (and will probably change vertex program to use that, too), thus sacrificing the ability to use ati hardware. I guess with geforce 6, this will no longer be neccessary?
In what way? It wasn’t necessary to use it then either, since by sticking with NV_fp, you lose any hope of having ATi support (and, as I understand the state of things, more R300-based hardware was sold than NV30, so you picked the wrong horse).

If you’re talking about the performance thing, then yes, there is still a performance difference betwen 16-bit and 32-bit floating-point operations on NV40 hardware. It still is the same fragment program hardware, basically, but with key upgrades in performance-critical sections. Like having a bigger piece of memory for the quads, which helps mitigate the 16/32-bit performance issue.

Really, though, if you want to bury the whole thing, stick to glslang and ARB_fp. Doing that will force nVidia to eventually provide a solution that doesn’t care about the size of floats.

Another point on that, if the ARB approved way of vertex and fragment programs (ARB_…) is slower than the NV_ way of doing this (when using the high precision registers), I guess this will also apply to glslang?
Putting it the correct way, NV30 hardware is slower at doing what ARB_fp/glslang asks than ATi hardware. And yes, this applies to glslang.

So on geforce fx, apart from the fact that they do not support glslang at the moment anyway (afaik), NV_… will still be faster?
Probably. If you like cutting out a pretty hefty portion of the market for your product.

As an addendum, beta glslang support can be activated in drivers. Just do a search on the glslang forum.

Thanks :-).

I am actually writing classes for fragment at vertex program, the goal at the moment is to encapsulate the program itself and so getting rid of the neccessity that other parts of the application have to know wether it is an ARB or an NV program (loading calls differ a little etc.). Theses classes provide functions for loading, enabling, disabling, binding and setting parameters, so at least, once they work, I will be able to change from ARB to NV (and vice versa) easily.

I know nearly nothing about glslang at the moment, but I hope that this will fit into my classes, too… so that I have a flexible, future-proof design (the whole engine is at the moment re-designed to be just that, future-proof). Is there a chance of this being possible?

The neccessity to use NV_fp instead of ARB was in fact due to performance reasons, but at least, I would like my program running on ati, too (after changing everything from display lists to vbos) :wink: .

Marketing issues do not matter that much as the engine is for quite special situations and we are in the lucky position to be able to tell our clients what hardware they have to buy… but restricting it to nvidia hardware seems not a good idea simply because ati hardware might be better. I just want it to be as well designed as possible.

edit:

this is a piece of my code (only nv at the moment, arb still to come). does it look future-proof :wink: ?

enum Vendor { V_ARB, V_NV };

class FragmentProgram
{
public:
FragmentProgram(const char*, Vendor);

void Bind();
void SetProgramLocalParameter4f(int, float, float, float, float);

private:
void LoadNVFragmentProgram(const char*);
GLuint id;
Vendor vendor;
};

thx a lot…
Jan

Jan,

yeah, that should get you there :slight_smile: . It really depends on how much insulation you want. I mean, you could really get crazy with this…

class Program {
virtual void bind()=0;
virtual void* getHandle()=0;
virutal void setParameter( const char* name, int size, void* value )=0;

};

class VertexProgram : public Program {
vertex specific stuff

};

class FragmentProgram : public Program {
fragment specific stuff

};

// implementation specific
class ARBVertexProgram : public VertexProgram{

};

class ARBFragmentProgram : public FragmentProgram{

};

…and so on. There are a lot of possibilities here, but I don’t know how much good they will do you. You could couple this kind of framework with something like a .FX user script and kick back. :slight_smile:

The main thing I worry about in your snippet is the GLuint dependency. It’s awfully difficult to avoid some assumptions about an implementation, but I suggest minimizing where you can. Anyway, that’s my 2 cents.

Thanks. I also thought about creating a class hierarchy, maybe I will do that later. That would also solve the Gluint issue… The structure is sufficient for what I need at the moment (encapsulating ARB/NV…), I guess when I have to implement other shading languages, it will have to be expanded. But I will do that then :wink: . For now, I am happy with an interface structure that is at least expandable.

I think NV paths have been dropped in doom3 for the reasons that nv got their arb shaders up to speed to rival their nv ones. I don’t think arb shaders will get updated. Nv ones are.

How did they manage to do that, if the slower speed was due to having to use high precision registers with the ARB path? I tried both in my program, the same shader, as ARB and NV fragment program, with the latest/actual linux driver (5336), and the NV one was same speed as ARB with high precision and significantly faster (30-50%) when using low precision registers.

Nvidia is probably detecting Doom III and replacing the shaders with hand tuned assembly versions.

I would kick the NV_* programs and only support ARB_fp/vp and GLSL because nVidia offered some extensions which enable ARB_program extensions to use features of NV30 and NV40 simply by adding OPTIONS to the ARB_program code. So you just have to replace shader code. Features of future NV hardware will be exposed by similar extensions. You just need to have a current driver…

NV30
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_vertex_program2_option.txt
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_fragment_program_option.txt

NV40
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_vertex_program3.txt
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_fragment_program2.txt