Table Of Contents

Previous topic

30.1. Known Issues

Next topic

30.3. Running in Process

This Page

30.2. nVidia Driver - Multiple Render Targets

The nVidia drivers (version 8.17.12.7061 - 8.17.12.7533) contain an OpenGL bug that causes multiple render targets to render the output for the first target to all target textures. nVidia have now fixed this bug in the latest driver download on their website. The current work around for shaders generated with cgfx2json is to reorder any writes to gl_FragData so they are in order.

30.2.1. Example

This is the result of cgfx2json when run on a multiple render targets shader:

{
    "version": 1,
    "name": "rendertarget.cgfx",
    "parameters": { },
    "techniques": {
        "rendertarget": [
            {
                "semantics": [
                    "POSITION"
                ]
                "states": {
                    "DepthTestEnable": false
                    "DepthMask": true
                    "CullFaceEnable": false
                    "BlendEnable": false
                }
                "programs": [
                    "vp_rendertarget"
                    "fp_rendertarget"
                ]
            }
        ]
    }
    "programs": {
        "fp_rendertarget": {
            "type": "fragment"
            "code": "#extension GL_ARB_draw_buffers:enable #ifdef GL_ES precision mediump float;precision mediump int; #endif void main() {gl_FragData[1]=vec4(0.0,1.0,0.0,1.0);gl_FragData[2]=vec4(0.0,0.0,1.0,1.0);gl_FragData[3]=vec4(1.0,1.0,1.0,1.0);gl_FragData[0]=vec4(1.0,0.0,0.0,1.0);}"
        }
        "vp_rendertarget": {
            "type": "vertex"
            "code": "#ifdef GL_ES precision mediump float;precision mediump int; #endif attribute vec4 ATTR0; struct VP_RENDERTARGET_OUT{vec4 _Position;};void main() {VP_RENDERTARGET_OUT _OUT;_OUT._Position=vec4(ATTR0.x,ATTR0.y,0.0,1.0);gl_Position=_OUT._Position;}"
        }
    }
}

To fix this shader for nVidia driver 8.17.12.7533 you should do the following:

Take the programs.fp_rendertarget.code string:

#extension GL_ARB_draw_buffers:enable #ifdef GL_ES precision mediump float;precision mediump int; #endif void main() {gl_FragData[1]=vec4(0.0,1.0,0.0,1.0);gl_FragData[2]=vec4(0.0,0.0,1.0,1.0);gl_FragData[3]=vec4(1.0,1.0,1.0,1.0);gl_FragData[0]=vec4(1.0,0.0,0.0,1.0);}

and expand it:

...
void main() {
    gl_FragData[1]=vec4(0.0,1.0,0.0,1.0);
    gl_FragData[2]=vec4(0.0,0.0,1.0,1.0);
    gl_FragData[3]=vec4(1.0,1.0,1.0,1.0);
    gl_FragData[0]=vec4(1.0,0.0,0.0,1.0);
}

Notice that the assignments to gl_FragData are out of order. The nVidia driver fails to handle this out of order assignment correctly. We can alter the code manually reordering the gl_FragData so that it is written to sequentially:

...
void main() {
    gl_FragData[0]=vec4(1.0,0.0,0.0,1.0);
    gl_FragData[1]=vec4(0.0,1.0,0.0,1.0);
    gl_FragData[2]=vec4(0.0,0.0,1.0,1.0);
    gl_FragData[3]=vec4(1.0,1.0,1.0,1.0);
}

Then manually compact it:

#extension GL_ARB_draw_buffers:enable #ifdef GL_ES precision mediump float;precision mediump int; #endif void main() {gl_FragData[0]=vec4(1.0,0.0,0.0,1.0);gl_FragData[1]=vec4(0.0,1.0,0.0,1.0);gl_FragData[2]=vec4(0.0,0.0,1.0,1.0);gl_FragData[3]=vec4(1.0,1.0,1.0,1.0);}

and copy it back into the JSON file. The nVidia driver bug should no longer appear.

Note

You will have to do this every time that the shaders are rebuilt.