Hacker News new | ask | show | jobs
by corysama 761 days ago
The pixel shading of the GameCube were slower than that of the OG Xbox. But, it was quite a bit more flexible. Specifically, the GameCube could load a couple textures, do a bit of math, then use that math to load some more texels. The Xbox could only load textures as the starting instructions before doing math and tried to make up for that with a few "do very specific math and load textures in a single instruction" ops.

But, still... Both GPUs were pretty well suited for this ubershader approach because they had a small, fixed limit on the number of instructions they could run. And, very strictly defined functionality for each instruction. They weren't really "shaders" as much as highly flexible fixed function stages that you could reasonably wedge in a text shader compiler as a front end and only get a moderate to high amount of complaints about how strict and limited the rules were for the assembly. I recall that both shading units could reasonably be fully specified as C structs that you manually packed into the GPU registers instead of using a shader compiler at all.

2 comments

> The Xbox could only load textures as the starting instructions before doing math and tried to make up for that with a few "do very specific math and load textures in a single instruction" ops.

If you look closely, the TEV actually shares the same limitation, it's just that the traditional representation interleaves the texture fetch and math instructions (Because the 3rd texture fetch "instruction" always feeds into the 3rd math "instruction", for example). There are two independent execution units, separated by a fifo and no way to backfeed from the math back to texture fetch.

The two GPUs are roughly equivalent. The only reason the OG Xbox is consider to "have pixel shaders" is that they were exposed with a pixel shader API, while TEV was only ever exposed with a "texture environment" based API. They are both clearly register combiners, with no control flow, but they sit right in the middle as GPUs were transitioning from register combiners to "proper" pixel shaders. The team that designed GameCube's GPU went on to develop the first DirectX 9 GPU.

I'm pretty sure the Xbox's pixel pipeline is slightly more capable as TEV doesn't have the Dot3 instruction (and it also has programmable vertex shaders). But developers all abandoned the xbox in 2005. TEV has a much better reputation for being flexible because TEV was used in the Wii all the way to ~2013. And graphics developers who were exposed to much better shaders on the Xbox, PS3 and PC got very good at back porting those modern techniques to the more limited Wii. More than one studio created un-offical shader compilers for the Wii, so they could share the same shaders across PS3/Xbox/Wii/PC.

> I recall that both shading units could reasonably be fully specified as C structs that you manually packed into the GPU registers instead of using a shader compiler at all.

Yeah, not that they ever exposed that API.

The GameCube had great support for recording display lists, so you could record a display list while you called the API commands to configure TEV and then call that display list later to quickly load the "shader". Some games even saved those display lists to disc (or maybe generated them from scratch with external tools) as a form of offline shader compilation.

You could definitely define pixel shaders on the Xbox using a combiner type struct. See the D3DPIXELSHADERDEF struct in the docs, from memory the equivalent of one of the NV register combiner extensions from OpenGL with additional access to a secret extra stage ordinarily reserved for some fixed function pipeeline stuff.
ISTR the GC pipeline being fixed-function while the Xbox had a full-fat GPU (GeForce 3 variant) -- one of the reasons why the Xbox absolutely smoked the other sixth-gen consoles in terms of performance. Was I wrong?
Extremely common misconception (even among developers on those platforms)

In reality, the OG Xbox and GameCube GPUs are almost identical in pixel shading capabilities (Though the gamecube's vertex shading pipeline is legitimately fixed function, but very flexible).

Despite their roughly equal capabilities, they were exposed with very different APIs. The xbox used the new-fangled "Shader" style API that Microsoft was introducing to the industry at the time, while TEV used a very extended version of the older "Texture Environment" style API that was introduced with DirectX 7 and OpenGL 1.3.

----------------

Edit: Actually, it might be better to explain from the other end:

In a true fixed function GPU like the Playstation 2 and Dreamcast (or OG Playstation... but not the N64, which is a two stage register combiner) the pixel pipeline is limited to just one basic equation. A single texture is sampled, and that sample is multiplied with a single color interpolated from the vertex colors (which were usually derived from lights). The flexibility is of the equation was limited to replacing each input with a fixed value, and then enabling a few optional post-processing stages like depth based fog, alpha cutout and/or blending with a few fixed blend equations.

But the results from that single texel * vertex_color equation are limiting. A common technique to produce better results on such GPUs was "multi-texturing". Graphics developers of the era would render the same triangles two or more times, but with different textures and vertex colours, blending the result into the frame buffer. This was commonly used to achieve the illusion of more detailed textures, or texture based light-maps. Or the reflections on cars in racing games.

But blending in the frame buffer is expensive as it wastes a lot of memory bandwidth. The PS2 is hyper-optimised for this approach, it has the VUs which can quickly generate multiple draws of the same geometry, and a fast, embedded dram with enough read/write ports that it can do blending "for free". But in the PC world, GPUs started adding features to combine these multiple draw call together and blend the result before writing to the frame buffer. The Voodoo 2 and Nvidia TnT (Twin Texel) from 1998 are examples of GPUs that supported this multi-pass texturing.

DirectX and OpenGL provided the "texture environment" APIs that automatically used these new single-pass multi-texturing features when available, or would fall back to multi-pass rendering on older GPUs.

But the actual hardware was often more flexible than what DirectX/OpenGL exposed, though vendors supplied "Register Combiner" OpenGL extensions that exposed the full functionality (This is why John Carmack used OpenGL, so he could create optimised per-gpu render paths for each GPU). And these Register Combiners could be "programmed" to produce pixel equations that were way more advanced that what could be achieved with multi-pass rendering, as they could pass more than one value between stages. And they started supported 4 or 8 textures plus enough math stages to combine the textures.

Microsoft gave up trying to expose the full capabilities of these register combiners though the older Texture Environment APIs and introduced Pixel Shaders with DirectX 8, but they were just providing a new API for the features GPUs already had. The register combine stages were simply renamed to "instructions".

The Xbox is a register combiner with 4 texture fetch stages and 8 combiner stages and Gamecube has 16 combiner stages and 8 texture fetches (well, it technically supports 16 texture fetches, but there are only 8 sets of UV coords)

The Xbox had fairly capable vertex shaders. But, phire's comment does a better job of explaining the pixel capabilities both machines than I did.