Wouldn't it be better if instead of unified shaders on the GPU you had separate pixels and vertex shaders again and the vertex shaders together with the Z-buffer were on the CPU die instead of on the GPU? That way, like before, you could do the calculation of the polygon world directly on the CPU die and filter out the triangles that shouldn't be shown using the Z-buffer and then send only the triangles that should be shown to the GPU to fill the pixels?

Wouldn't this then save bandwidth from the CPU to the GPU and allow for much faster updating of 3D objects? In addition, the 3D world calculation would then be on the CPU, where the gameplay-critical physics calculation also takes place. (of course there are also physics calculations as an accessory, but these are the ones that don't affect the gameplay) In addition, these calculations would then be able to be calculated using the clock frequency of the CPU. And finally, there would also be a lot more RAM available, since a computer usually has more RAM than VRAM.

So why was this approach never pursued?

  • $\begingroup$ It was pursued, this is how it used to be done pre hardware T&L (Transform, Clipping & Lighting). The 'transform' is the triangle setup and MVP (model, view, projection operations). The 'clipping' includes occlusion (depth testing) as well as frustum clipping. Turns out to be a bit of a bottle-neck done this way. $\endgroup$
    – lfgtm
    Feb 26 at 16:13
  • 1
    $\begingroup$ If anything the industry is going in the opposite direction from this. Computing entire triangle visibility inside a compute shader, then sending that list off to be processed in the vertex shader. This allows triangle visibility on a per frame basis. For example, take the zbuffer from the last frame and use it to help determine if a triangle in the current frame is visible. Only the GPU has the parallel compute power to compute this sort of per frame info. $\endgroup$
    – pmw1234
    Feb 26 at 16:25
  • $\begingroup$ On the CPU we usually limit ourselves to bounding volume visibility checks, which may include "occluders" in the scene, like a mountain range or large buildings. Also, the question implies that vertex and fragment shaders are put into a single shader, this is not the case, the term "unified" shader refers to many different fragment shaders rolled into one large shader, or many different vertex shaders rolled into one large shader. Those two shaders will have a seperate entry point like "main" in glsl and may be written to work together but aren't written as a single execution unit. $\endgroup$
    – pmw1234
    Feb 26 at 16:56
  • $\begingroup$ @lfgtm Well, there were no parallel Vertex Shaders on the CPU die. Apart from the SIMD units (MMX and SSE), there was practically nothing, and in any case there were no hundreds of vertex shaders on the CPU, as is the case with a GPU today. $\endgroup$
    – Coder
    Feb 26 at 18:52
  • $\begingroup$ @Coder Ah I see what you are saying now :). It's probably not wise to use the (already starved) CPU to transform every vertex (GPU's can do it magnitudes faster, even with the transfer via PCIE). Also, geometry is not what bottlenecks the bandwidth, more texture thrashing, and since textures are used by the fragment shaders they still need to be thrown down the PCIE bus to the GPU. $\endgroup$
    – lfgtm
    Feb 27 at 10:03

1 Answer 1


… you could do the calculation of the polygon world directly on the CPU die and filter out the triangles that shouldn't be shown using the Z-buffer and then send only the triangles that should be shown to the GPU to fill the pixels?

The depth buffer (Z buffer) is tested per-fragment — it doesn't hide whole triangles but individual pixels of the triangles. That means that

  • The GPU's parallel processing is advantageous for this job. (Generally, all per-pixel operations should be done on the GPU.)
  • The depth test (which must happen after rasterization and before executing the fragment shader) is executed more like the fragment shader than the vertex shader.
  • If we did the depth tests on the CPU, then you wouldn't just be deciding which triangles to send to the GPU, but you'd have to send a list of individual pixels.

Also, if depth tests were done per-triangle, then you'd see lots of triangle-shaped artifacts whenever two objects slightly intersect. It's routine practice when putting together an environment to make overlaps, to save time on precisely modeling specific situations — for example, rocks might be placed slightly intersecting the terrain, or a door frame or arch intersecting the material of the wall it passes through. This only works because depth testing allows drawing intersecting objects near-perfectly.

Wouldn't this then save bandwidth … gameplay-critical physics calculation also takes place … calculated using the clock frequency of the CPU.

Separate from the triangles vs. pixels difference, another factor is that (in most applications) each object that the CPU tracks separately has a mesh which is made of many triangles. The CPU only has to process the object's position and rotation, then pass that to the GPU; the GPU handles (as directed by the vertex shader) transforming all the vertices of the mesh from their positions in the mesh data to their positions on screen. This operation benefits from being executed on the GPU because it is highly parallel, and because the GPU's triangle rasterizers take instructions directly from the outputs of the vertex shader.

The CPU never needs to calculate anything about thousands-to-millions of triangles, except for initially loading them from disk. That's a big advantage.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.