<blockquote>
<p>… 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?</p>
</blockquote>
<p>The depth buffer (Z buffer) is tested <em>per-fragment</em> — it doesn't hide whole triangles but individual pixels of the triangles. That means that</p>
<ul>
<li>The GPU's parallel processing is advantageous for this job. (Generally, all per-pixel operations should be done on the GPU.)</li>
<li>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.</li>
<li>If we did the depth tests on the CPU, then you wouldn't just be deciding which <em>triangles</em> to send to the GPU, but you'd have to send a list of individual pixels.</li>
</ul>
<p>Also, if depth tests <em>were</em> 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.</p>
<hr />
<blockquote>
<p>Wouldn't this then save bandwidth … gameplay-critical physics calculation also takes place … calculated using the clock frequency of the CPU.</p>
</blockquote>
<p>Separate from the triangles vs. pixels difference, another factor is that (in most applications) each object that the CPU tracks separately has a <em>mesh</em> 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 <em>all the vertices of the mesh</em> 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.</p>
<p>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.</p>

CC BY-SA 4.0
2024-02-26T15:49:32.300Z
2024-02-26T15:49:32.300Z
Kevin Reid
<p>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?</p>
<p>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.</p>
<p>So why was this approach never pursued?</p>

CC BY-SA 4.0
2024-02-26T16:13:09.930Z
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.
lfgtm
CC BY-SA 4.0
2024-02-26T16:25:13.283Z
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.
pmw1234
CC BY-SA 4.0
2024-02-26T16:56:38.683Z
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.
pmw1234
CC BY-SA 4.0
2024-02-26T18:52:12.873Z
@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.
Coder
CC BY-SA 4.0
2024-02-27T10:03:35.017Z
@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.
lfgtm
CC BY-SA 4.0
2024-02-27T10:03:47.247Z
Also note that a unified shader architecture allows the programs/driver to schedule more tailored command queues and pipelines so more SM's can be used at any given time (since they are not locked into any single domain, such as vertex, fragment, compute etc). Without the unified architecture they are less likely to be fully saturated and they would stall as the fragment shaders wait for the entirety of the vertex shader programs to execute. Where would the other shaders (e.g compute) execute?
lfgtm
CC BY-SA 4.0
2024-02-27T10:03:55.587Z
The other thing to bear in mind is during multipass rendering (which is pretty much the common standard these days), in which there can be multiple geometry passes that happen and these sometimes require feedback from the framebuffer. In these situations there would be an awful lot of data going back and forth before a single frame is even presented.
lfgtm
CC BY-SA 4.0
2024-02-27T12:05:47.397Z
@lfgtm What i mean is putting hundreds of vertex units (hardware) on the CPU die. Thus, the CPU will be able to do it on the vertex units all in parallel and then sent the calculated data to the GPU for rasterization.
Coder
<gpu><hardware>
Wouldn't it be better if the vertex shaders and Z-Buffer were on the CPU instead of the GPU?
Coder
# Wouldn't it be better if the vertex shaders and Z-Buffer were on the CPU instead of the GPU?

(Asked by: username_0 on 2024-02-26)

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?

**Tags:** gpu, hardware

> **Comments:**
> **username_1**: 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.  
> **username_2**: 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.  
> **username_2**: 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.  
> **username_0**: @username_1 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.  
> **username_1**: @username_0 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.  
> **username_1**: Also note that a unified shader architecture allows the programs/driver to schedule more tailored command queues and pipelines so more SM's can be used at any given time (since they are not locked into any single domain, such as vertex, fragment, compute etc). Without the unified architecture they are less likely to be fully saturated and they would stall as the fragment shaders wait for the entirety of the vertex shader programs to execute. Where would the other shaders (e.g compute) execute?  
> **username_1**: The other thing to bear in mind is during multipass rendering (which is pretty much the common standard these days), in which there can be multiple geometry passes that happen and these sometimes require feedback from the framebuffer. In these situations there would be an awful lot of data going back and forth before a single frame is even presented.  
> **username_0**: @username_1 What i mean is putting hundreds of vertex units (hardware) on the CPU die. Thus, the CPU will be able to do it on the vertex units all in parallel and then sent the calculated data to the GPU for rasterization.  

---

## 1 answers

### Answer by username_3 on 2024-02-26. Score: 3

> … 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.


---

