ATI/Nvidia compatible code
category: general [glöplog]
I figure it would be handy to have a list of 'stuff to watch out for' if you want your demo to run on both vendors' cards. Stuff I've found lately:
- 16 bit rendering modes. ATI supports 16bit integer (RGBA16) and 16bit half float (RGBAh) in recent gpus, but nvidia only supports half float. Avoid RGBA16 if you're on ATI and you'll save a lot of headscratching.
- Floats and ints in GLSL: it seems ATI is a lot more fussy about having the right types. Making sure that you have floats (i.e. 1.0 not just 1) where floats are required might help compatibility.
- 16 bit rendering modes. ATI supports 16bit integer (RGBA16) and 16bit half float (RGBAh) in recent gpus, but nvidia only supports half float. Avoid RGBA16 if you're on ATI and you'll save a lot of headscratching.
- Floats and ints in GLSL: it seems ATI is a lot more fussy about having the right types. Making sure that you have floats (i.e. 1.0 not just 1) where floats are required might help compatibility.
Back in the days I had an ATI card having anything other than unsigned shorts in index buffers lead to some serious performance fuckery. Don't know if it's still the case tho.
- gl_LightSource[n].position seems to be void with ATI in glsl vertex shader
- ATI had problems reading some fog stuff in vertex shader so I had to do calculations in pixel shader.
- Steep parallax mapping loop crashed display drivers on 8800GTX+vista until I set maximum iterations. [while (h < b && counter < 100) { counter++; ...}
And finally the common knowledge that ATIs opengl syntax is more stricter than Nvidias. You can try to make you glsl code ATI compatible with Nvidia card by fixing all the warnings. However this doesn't guarantee your shaders work on ATI. I've noticed that newer ATIs seem to have better drivers regarding glsl compiling, so if you have a newer ATI you can't be sure if it works on older ones. If you can get it to work on ATI X1600 then it should work on every modern gfx card.
- ATI had problems reading some fog stuff in vertex shader so I had to do calculations in pixel shader.
- Steep parallax mapping loop crashed display drivers on 8800GTX+vista until I set maximum iterations. [while (h < b && counter < 100) { counter++; ...}
And finally the common knowledge that ATIs opengl syntax is more stricter than Nvidias. You can try to make you glsl code ATI compatible with Nvidia card by fixing all the warnings. However this doesn't guarantee your shaders work on ATI. I've noticed that newer ATIs seem to have better drivers regarding glsl compiling, so if you have a newer ATI you can't be sure if it works on older ones. If you can get it to work on ATI X1600 then it should work on every modern gfx card.
Regarding glsl ati's parser is basicly reference nowadays. The nvidia warnings warns too much about some things (like float/integer constants for glsl1.2) and still accepts other (well mostly relevant when you size optimize your glsl source ;)
If you're on nvidia hardware you can use the GPU ShaderAnalyzer (http://developer.amd.com/gpu/shader/Pages/default.aspx to check if your code (pixel shader at least) compiles on different ati drivers / hardware (ofcourse compiling is only part of it, but in most cases that's the problem).
If you're on nvidia hardware you can use the GPU ShaderAnalyzer (http://developer.amd.com/gpu/shader/Pages/default.aspx to check if your code (pixel shader at least) compiles on different ati drivers / hardware (ofcourse compiling is only part of it, but in most cases that's the problem).
when working in dx9 things are substantially easier, especially if you go for a ps3.0 baseline. for example, thankfully in dx9 the shader compiler isnt in the driver, its in d3dx. i.e. if it compiles on one, it should compile on the other.
however, there are a few differences to watch out for.
- ati and nvidia interpret depth textures in dx9 in different ways. ati does fetch4, nvidia does a compare. they also use different formats - in ATI x1xxx series and later you should use a 4cc format "DF24", and on nvidia you can use d24s8.
- alpha to coverage works on both but is exposed with different dirty renderstate hacks. (D3DRS_ADAPTIVETESS_Y and D3DRS_POINTSIZE)
- both cards have very different rendertarget format and vertex data format support. e.g. ati supports unsigned shorts and nvidia doesnt. to be absolutely safe, stick to d3dcolor and floats for vertex data. for rendertargets, nvidia has finally added 10.10.10.2 support but it wont work on older cards, so avoid it.
- instancing works on pre-ps3.0 ati cards, but it needs some renderstate hackery to work.
however, there are a few differences to watch out for.
- ati and nvidia interpret depth textures in dx9 in different ways. ati does fetch4, nvidia does a compare. they also use different formats - in ATI x1xxx series and later you should use a 4cc format "DF24", and on nvidia you can use d24s8.
- alpha to coverage works on both but is exposed with different dirty renderstate hacks. (D3DRS_ADAPTIVETESS_Y and D3DRS_POINTSIZE)
- both cards have very different rendertarget format and vertex data format support. e.g. ati supports unsigned shorts and nvidia doesnt. to be absolutely safe, stick to d3dcolor and floats for vertex data. for rendertargets, nvidia has finally added 10.10.10.2 support but it wont work on older cards, so avoid it.
- instancing works on pre-ps3.0 ati cards, but it needs some renderstate hackery to work.
(Score:5, Insightful)
(already mentioned this in some other thread)
gl: nv automatically shares texture/display list handles for different rendering contexts created by the same process, ati doesn't (you need to call wglShareLists).
d3d: (stumbled on this today and haven't had time to analyze it properly) on ati, you can generate miplevels for rendertargets "by hand" using stretchrect without problems (stretchblit from e.g. miplevel 0 to 1), on nvidia the same seems to fail silently. need this for a texture atlas i'm rendering to - AUTOGENMIPMAPS isn't viable since i need to have a certain number of mipmaps, not a full chain (after a certain number of mipmaps, different parts of the atlas blend together and i want to avoid that).
gl: nv automatically shares texture/display list handles for different rendering contexts created by the same process, ati doesn't (you need to call wglShareLists).
d3d: (stumbled on this today and haven't had time to analyze it properly) on ati, you can generate miplevels for rendertargets "by hand" using stretchrect without problems (stretchblit from e.g. miplevel 0 to 1), on nvidia the same seems to fail silently. need this for a texture atlas i'm rendering to - AUTOGENMIPMAPS isn't viable since i need to have a certain number of mipmaps, not a full chain (after a certain number of mipmaps, different parts of the atlas blend together and i want to avoid that).
ATI & openGL: forget about vertex texturing from other number of samplers than 1. Always initialize temporaries.
Cg + ATI + MRT + OpenGL. If you're using this combination then you won't be able to use GLSL for fragment programs. It's because ATI_draw_buffers issue which is still not fixed.
Cg + ATI + MRT + OpenGL. If you're using this combination then you won't be able to use GLSL for fragment programs. It's because ATI_draw_buffers issue which is still not fixed.