Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Piston-Graphics design #1043

Open
bvssvni opened this issue May 19, 2016 · 3 comments
Open

Piston-Graphics design #1043

bvssvni opened this issue May 19, 2016 · 3 comments

Comments

@bvssvni
Copy link
Member

bvssvni commented May 19, 2016

This issue is for explaining how Piston-Graphics work.

Pipeline

When rendering 2D, the information goes through various stages of transformation:

  1. API level - The geometric descriptions of the things we want to render (e.g. a rectangle)
  2. Triangulation input - A mathematical reduction from geometry to some simpler representation (e.g. quad edges or points on the edge of a polygon)
  3. Triangulation output - A chunk of triangle information, the size of chunk set to optimize for common CPU cache
  4. Graphics back-end - The chunks are written to a large buffer to reduce draw calls to the GPU, or using other optimization techniques depending on target

The triangulation module is the core of the library, which does the transformation from 2 to 3. The rest of the library consists of convenient structures for representing geometrical objects, and change matrix transformation.

Going through 2-3 is the default process, but the graphics back-end can override this to make it faster, if there is a quicker way from the geometric description to the data ends up in the triangle buffer.

Simplicity is the key to Piston-Graphics' design. The Graphics trait requires back-ends authors to implement only 4 methods to support the whole 2D Piston ecosystem. The goal is not to create a sophisticated API or with fancy features, but to make as much as possible generic code reusable across projects. For example, if 90% of the 2D code is just doing simple stuff, then we try to design a reusable abstraction for this and then handle the 10% by making the abstraction optional and modular.

Testing

When we write a new back-end, we start simple by doing the least amount required to get stuff up and running. Then, we do optimization based on real world usage (CPUs and GPUs are complex, so optimizing for single benchmark does not always give good results). This is done by running a game in "benchmark mode", which means the game loop runs without sleeps or user input for getting as deterministic behavior as possible. In Piston, this can be enabled with .set_bench_mode(true) on the event iterator.

Piston-Graphics uses f64 precision by default, because the transformation happens on the CPU, and then get packed into f32 chunks. This is designed for meeting requirements for animation software, where matrices can be sensitive in large and complex scenes, and for easy transition to file formats where f64 is standard.

In the future, when we start testing Piston-Graphics more closely on real world cases, we might change some types to f32, if memory bandwidth is a problem. However, until there is a use case where this is critical, we optimize the design for precision.

Alternative designs: Immediate vs Retained API

Piston-Graphics is immediate API, it means there is no state and any draw command can change the settings completely. However, the draw state does not change while chunks are streamed, so if a geometrical object requires sending a lot of data, it can do so with the back-end knowing what optimizations can be done.

Immediate API design is flexible and cover a lot of use cases, which is suitable for generic code meant to be reused, but not fully optimized for a particular situation. A retained API on the other hand, can take advantage of knowing all the information about what to render before doing the rendering. This makes it possible to do more sophisticated optimizations, such as building trees and doing transformations in parallel. A lot of this work can be moved over to the GPU.

The advantage Piston-Graphics with the current design is that there are less constraints on how you describe the geometry. For example, if we made a retained API doing a particular optimization by exploiting a property of the most common objects, it might not work when combined with other shapes. Piston-Graphics is also not constrained to linear transformations, but can do non-linear because the triangulation pipeline is flexible, but without depending on particular hardware features.

@echochamber
Copy link
Contributor

@bvssvni Do you have a recommended reading or source for better understand the theory behind rendering graphics via triangulation. The Rust code itself is easy enough to follow, the theory not so much 😄 . Thanks in advance!

@bvssvni
Copy link
Member Author

bvssvni commented May 27, 2016

@echochamber Google "triange list" and "triangle strip".

@echochamber
Copy link
Contributor

@bvssvni Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants