Hacker News new | ask | show | jobs
by spicyjpeg 1039 days ago
> The PSX devkits came with a library called LIBGPU, which handled the rendering. Since the PSX GPU didn't have a z-buffer, all primitives you wanted to draw (triangles, quads and sprites) needed to be submitted into an “ordering table” or OT for short. This table had (typically) 8192 slots allowing for 8192 different z-levels. The GPU would then rasterize the list back to front. The result would not be perfect (in some situations neither of two polygons will have all pixels in front of the other one), but close enough.

This is actually implemented in a slightly funky way on the PS1. The DMA unit responsible for sending commands to the GPU allows for a display list to be built in memory as a linked list of variable-length packets, each of which can hold zero or more commands. What Sony's libraries do is essentially generating the ordering table as an array of 8192 empty packets linked to each other, then allowing actual command packets to be allocated elsewhere (typically using a simple bump allocator) and "spliced" into the link from one empty packet to the next one. The PS1's vertex transformation coprocessor, the GTE, also keeps track of the Z coordinates of the last 4 vertices processed and has an instruction to quickly average them out so that the resulting value can be used as an index into the ordering table.

I wrote a few SDK-less bare metal C examples showing how to build an ordering table [1] and leverage it for 3D polygon sorting [2], should anybody want to check those out.

[1] https://github.com/spicyjpeg/ps1-bare-metal/blob/main/src/07...

[2] https://github.com/spicyjpeg/ps1-bare-metal/blob/main/src/08...

2 comments

So when you're drawing triangles on the PSX, do you basically get the GTE hardware to figure out your coordinates, before putting those into the appropriately indexed packet?

I'm guessing this explains the PSX-specific artefacts you would see when rotated triangles would "clip" into each other at the seams of models. The ordering would just come from the average Z coord of the plane.

You are right: unlike modern platforms with vertex shading capabilities, the geometry pipeline runs entirely on the CPU and GTE. The GPU is a "black box" that operates exclusively in screen space and only gets access to transformed X/Y coordinates, which is also why it cannot calculate the depth of each pixel and use it to apply perspective correction to projected textures [1].

[1] https://en.wikipedia.org/wiki/Texture_mapping#Affine_texture...

I wonder how perspective corrected texture mapping works on emulators.

Maybe the coordinate values passed from GTE to GPU are "shadowed" with extra data about the transformation, that is then retrieved further down the pipeline

I suppose there could be multiple approaches

Huh. I never thought about this. One of the advantage of some of these emulators is being able to fix the perspective issue on the texture-mapping, but of course most 90s games were doing the texture-mapping in 2D and the 3D points had already been projected into screen space.

This isn't an easy problem to solve. I can't think of a way you could back figure the Z from the rendered data. The only other solution I can think of is to somehow break the models up into smaller polys as they are loaded into memory. If you break them up the individual triangles will be smaller and the lack of perspective won't show.

There actually is a relatively simple, if hacky, way to accomplish this: the emulated GTE can push the Z coordinate (and optionally the full-precision X/Y coordinates) of each processed vertex into a private key-value store, using the rounded X/Y result returned to the game as a key. The emulated GPU can then look up the coordinates provided by the game - assuming they were passed as-is from the GTE, which is the case for the vast majority of games - in the same store to obtain the Z values.

This does not seem to be a new approach, as PC ports of PS1 games used similar tricks all the way back in 2000 [1].

[1] https://news.ycombinator.com/item?id=3581350 https://news.ycombinator.com/item?id=29493242

I really like your project there - ps1 dev without psy-q!