simias / rustation

Playstation emulator in the Rust programing language
Other
554 stars 21 forks source link

Optimization: draw polygons front to back in the GPU when possible #20

Open simias opened 8 years ago

simias commented 8 years ago

Since the PSX doesn't have a z-buffer all the primitives are drawn from farthest to closest. This means massive amounts of overdraw as many polygons are drawn only to be hidden by a closer one later on.

This is basically the worst case as far as the OpenGL renderer is concerned, generally we'd prefer to render from front to back and ignore hidden pixels instead invoking our shader millions of time for fragments that will never make it to the screen.

Implementation

This shouldn't be too difficult to implement: when we receive primitives in the GPU we could store them in the vertex buffers in reverse order. We'd also need a way for the GPU to test which parts of the screen have already been drawn, I can think of two simple ways to do that:

There are a few limitations to this optimization however: semi-transparent polys will still have to be drawn back to front after all the opaque primitives for tranparency to work as expected. We'll probably need two passes, one for the opaque polys front-to-back and then one for the semi-transparent polys back-to-front. Maybe we could store the opaque vertex starting from the end of the vertex buffer and then decrementing while transparent primitives would be stored at the beginning and incrementing as it's currently done. Or we could use two buffers, not sure which is best.

Also we can't use this optimization when the "test mask bit" and "set mask bit" options are enabled since the order of the draws become significant for the end result regardless of the "depth" of the polygon. If it's the case we need to render everything in "native" order.