Tag Archives: shader

A cumbersome bug in the Catalyst 7.12

The latest Catalyst version is the 7.12 (the Cat7.12 internal number is 8.442.0.0). But exactly like the Cat7.11, these drivers have a bug in the management of dynamic lights in GLSL. But this time, I searhed for the source of bug because this bug is a little bit cumbersome in Demoniak3D demos. And we can’t use a previous version since Cat7.11+ are required to drive the radeon 3k (HD 3870/3850). Then I’ve coded a small Demoniak3D script that shows the bug. This script displays a mesh plane lit by a single dynamic light. The key SPACE allows to switch the GLSL shader: from the bug-ridden to the fixed and inversely.

– The following image shows the plane enlightened with the fixed shader:

– The following image shows the plane lit with the bug-ridden shader:

Okay that’s cool, but where does the bug come from ? After a little time spent on shaders tweaking, my conclusion is that the bug is localized in the value of the built-in uniform variable gl_LightSource[0].position. In the vertex shader, this variable should contain the light position in camera space. It’s OpenGL that does this transformation, and we, poor developers, just need to specify somwhere in the C++ app the light position in world coordinates. In the vertex shader, gl_LightSource[0].position helps us to get the light direction used later in the pixel shader:

	lightDir = gl_LightSource[0].position.xyz - vVertex;

With the Catalyst 7.11 and 7.12, the value stored in gl_LightSource[0].position is wrong. Then, one workaround, until the ATI driver team fix the bug, is to manually compute the light pos in camera space by passing to the vertex shader the camera view matrix and the light pos in world coord:

	vec3 lightPosEye = vec3(mv * vec4(-150.0, 50.0, 0.0, 1.0));
	lightDir = lightPosEye - vVertex;

mv is the 4×4 view matrix and vec4(-150.0, 50.0, 0.0, 1.0) is the hard coded light pos in world coord.

In the fixed pipeline, dynamic lights are well handled as shown in the next image:

In the Demoniak3D demo, the bug-ridden GLSL shader is called OneDynLightShader and the fixed one OneDynLightShader_Fixed. The demo source code is localized in the OneDynLightTest.xml file. To start the demo, unzip the archive in a directory and launch
DEMO_Catalyst_Bug.exe.

The demo is downloadable here: Demoniak3D Catalyst 7.11/7.12 Bug

This bug seems to affect all radeons BUT under Windows XP only. Seems as if ATI is forcing people to switch to Vista. Not cool… Or maybe ATI begins to implement OpenGL 3.0 in the Win XP drivers. Do not forget that with OpenGL 3.0 as with DX10, the fixed functions of the 3D pipeline like the management of dynamic lights will be removed.

Les Catalyst 7.12 toujours à la sauce “Bug-Inside”

Les derniers pilotes Catalyst ont la version 7.12 (le numéro interne des Cat7.12 est le 8.442.0.0 – c’est pas un téléphone ok!). Mais exactement comme les 7.11, ces drivers ont un bug dans la gestion des lumières dynamiques en GLSL. Mais cette fois-ci, je me suis mis à la recherche du bug car il est un peu, voire très génant pour les demos Demoniak3D. J’ai donc pondu un petit script Demoniak3D qui met en évidence ce bug. Ce script montre un mesh plan éclairé par une lumière dynamique. Un appui sur la touche SPACE permet de changer de shader GLSL: on passe du shader bogué au shader corrigé et inversement.

– L’image suivante montre le plan éclairé avec le shader corrigé:

– L’image suivante montre le plan éclairé avec le shader bogué:

okay tout ceci est bien, mais d’oû vient le bug? Après avoir passé un peu de temps à tweaker les shaders, j’en suis arrivé à la conclusion que le bug se situe au niveau de la valeur contenue dans la variable uniforme built-in gl_LightSource[0].position. Au niveau du vertex shader, cette variable contient la position de la lumière exprimée l’espace de la caméra. C’est OpenGL qui effectue cette transformation, à notre niveau il suffit de spécifier la position de la lumière en coordonnées du monde. Au niveau du vertex shader, gl_LightSource[0].position nous permet de calculer la direction de la lumière utilisée plus tard dans le pixel shader:

	lightDir = gl_LightSource[0].position.xyz - vVertex;

Avec la Radeon HD 3870 et les Catalyst 7.11 et 7.12, la valeur contenue dans gl_LightSource[0].position est fausse.
Donc le workaround que je propose en attendant que la driver team d’ATI corrige le bug, est de passer au vertex shader la position de la lumière exprimée dans les coordonnées du monde ainsi que la matrice de vue de la camera et de faire la transformation à la main:

	vec3 lightPosEye = vec3(mv * vec4(-150.0, 50.0, 0.0, 1.0));
	lightDir = lightPosEye - vVertex;

mv représente la matrice 4×4 de vue de la caméra et vec4(-150.0, 50.0, 0.0, 1.0) représente la position de la lumière en coordonnées du monde.

Au niveau pipeline fixe, les lumières dynamiques sont bien gérées comme le montre l’image suivante:

Au niveau de la démo Demoniak3D, le shader GLSL bogué est appelé OneDynLightShader et celui corrigé OneDynLightShader_Fixed. Le code source de la démo Demoniak3D se trouve dans le fichier OneDynLightTest.xml. Pour lancer la demo, dézippez l’archive dans un répertoire
et lancez DEMO_Catalyst_Bug.exe.

La démo est téléchargeable ici: Demoniak3D Catalyst 7.11/7.12 Bug

Ce bug affecte toutes les radeons MAIS sous Windows XP uniquement. On dirait qu’ATI nous force un peu la main pour passer sous Vista. Pas trop sympa… Ou alors ATI commence à implémenter OpenGL 3.0 dans les drivers XP. Car n’oublions pas qu’avec OpenGL 3.0, tout comme avec DX10, les fonctions fixes du pipelines 3D comme la gestion des lumières dynamiques sont supprimées.

Je voudrais remercier la communauté WorldPCSpecs pour les tests. Merci les gars!

Catalyst 7.9, Radeon 2900 and Surface Deformer

From oZone3D.Net Forums, the Catalyst 7.9 seems to unleash ATI Radeon 2900 GPU. The Surface Deformer benchmark is a benchmark that requires a lot of vertex processing horse power. With Catalyst prior to 7.9, the score of an ATI 2900 was around 8000 o3Marks (that was already high). Now with Catalyst 7.9, the 2900 gets a score of 15000 o3Marks. Incredible!!! Why such a big big jump in OpenGL performance ?

My first thought is that ATI has managed to use correctly the unified arch of the R600 gpu. With unified arch, the workload is distribued over all shaders processors no matter the type of the shader prog (vertex or pixel). So if the vertex shader needs more processing power than the pixel shader, more shaders processors will be used for the vertex shader. My second thought: unified arch has involved new kernel code for catalyst and simply ATI has optimized the R600 codepath. A driver for a modern GPU like the R600 is a very complex piece of code and optimizing such a code is a huge task….

Embedded Your Shader Souce Code In Your C/C++ Apps

The NVIDIA developer blog shows a way to include shaders codes to your
windows exe: blogs.nvidia.com/developers/2007/03/inlining_shader.html.

But this example is not fully operational. I slightly modified the code to make it totally operational (I compiled it on vc++ 6.0):

1) Add a define to your resource.h file:
#define IDF_SHADEFILE 1000

2) Add an entry in your resource.rc file:
IDF_SHADERFILE RCDATA DISCARDABLE "myShader.glsl"

3) Use the resource in your code:
HMODULE hModule = GetModuleHandle(NULL);
HRSRC hResource = FindResource(hModule, (LPCTSTR)IDF_SHADERFILE, RT_RCDATA);
if(hResource) 
{
  DWORD dwSize = SizeofResource(hModule, hResource);
  HGLOBAL hGlobal = LoadResource(hModule, hResource);
  if(hGlobal) 
  {
    LPVOID pData = LockResource(hGlobal);
    if(pData) 
    {
	// Cast pData to a char * and you have your shader
	char *shader_code = (char *)pData;
	
        // Now do whatever you want with shader_code pointer. 
	// Do not forget that shader_code is not a zero-terminated string!
	// Use dwSize to handle that.
			
    }
  }
}