In theory, the Microsoft approach allows a single code path to support both brands of card, whereas under OpenGL the programmer had to write two separate systems. In reality, though, because of the limits on pixel processing of those early cards,
Pixel Shader 1.1 was nothing more than a
pseudo-assembly language version of the NVIDIA-specific OpenGL extensions. For the most part, the only cards that claimed PS 1.1 functionality were NVIDIA cards, and that is because they were built for it natively. When the Radeon 8500 was released, Microsoft released an update to Direct3D that included
Pixel Shader 1.4, which was nothing more than a
pseudo-assembly language version of the ATI-specific OpenGL extensions. The only cards that claimed PS 1.4 support were ATI cards because they were designed with the precise hardware necessary to make that functionality happen. In terms of early pixel shaders, Direct3D's attempt at a single code path fared no better than the OpenGL mechanism.
Fortunately, this situation only existed for a short time under both APIs. Second-generation pixel shading cards were
much more similar in functionality, with each architecture evolving towards the
same kind of pixel processing conclusion. As such,
Pixel Shader 2.0 allowed a unified code path under Direct3D. Around the same time OpenGL introduced its own ARB-approved vertex and pixel shader extensions (GL_ARB_vertex_program and GL_ARB_fragment_program),
and both sets of cards supported this standard as well.