You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is for explaining how Piston-Graphics work.
Pipeline
When rendering 2D, the information goes through various stages of transformation:
API level - The geometric descriptions of the things we want to render (e.g. a rectangle)
Triangulation input - A mathematical reduction from geometry to some simpler representation (e.g. quad edges or points on the edge of a polygon)
Triangulation output - A chunk of triangle information, the size of chunk set to optimize for common CPU cache
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.
The text was updated successfully, but these errors were encountered:
@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!
This issue is for explaining how Piston-Graphics work.
Pipeline
When rendering 2D, the information goes through various stages of transformation:
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 intof32
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 wheref64
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.
The text was updated successfully, but these errors were encountered: