For those unfamiliar, ultraviolet is a crate to do computer-graphics and games-related linear algebra, but fast, both in terms of productivity and in terms of runtime performance. In terms of productivity, ultraviolet uses no generics and is designed to be as straightforward of an interface as possible, resulting in fast compilation times and clear code. In addition, the lack of generics and Rust type-system "hacks" results in clear and concise errors that are easy to parse and fix for the user. In terms of runtime performance, ultraviolet was designed from the start with performance in mind. To do so, it provides two separate kinds of each type, one with usual scalar f32 values, and the other a 'wide' type which uses SIMD vector types for each value. Both kinds of each type provide essentially equivalent operations, while the wide types offer some functionality unique to them to facilitate performant SIMD algorithm design. This design is clearn and explicit in intent, and it also allows code to take full advantage of SIMD, offering the possibility of large performance gains for some workloads.
0.6 is the first major release since 0.4 several months ago; 0.5 was mostly incremental changes, though it did bring serde
support which was exciting.
The headlining features are
f64
feature, including f64x2
and f64x4
SIMD-accelerated types.These are two features that have been at the top of 'the wishlist' for some time now, and I'm excited to finally land them! 256-bit/AVX support is particularly exciting for me, as some workloads that I'm interested in (namely rayn, my pathtracing renderer) should be able to get a fairly significant performance boost. In a test of purely the ray-sphere intersection test (which may be used in a renderer), you can see this starting to take shape (glam here is used to represent an optimized 'scalar' implementation, i.e. SIMD accelerated but horizontally rather than vertically as ultraviolet does):
glam (f32x1)
- 917.0 usultraviolet_f32x4
- 170.3 usultraviolet_f32x8
- 100.9 usNote: this isn't an apples-to-apples comparison... the algorithm needed to use the wide ultraviolet types is different than the standard one which may be used by scalar types like glam's. So while there is a lot of potential performance on the table, it's not "free".
Note 2: benchmarks performed on an i5 Mid-2014 Macbook Pro, and may vary significantly per processor/computer
In addition, there's been various other improvements, bug fixes, and enhancements, including significant performance improvements for Rotor-transform-vector operations. Here's the relevant benchmark:
glam
- 6.4543 nsultraviolet
0.5 - 7.4728 nsultraviolet
0.6 - 6.1521 nsThis is an apples-to-apples comparison, all three just using standard scalar f32s, not wide-style SIMD types.
Finally, support for mint landed for most scalar types, which is great for interoperation between ultraviolet
and other Rust math crates, as well as making it easier to use ultraviolet
with ggez.
f64
feature. Naming convention is D[TypeName]
for the f64 versions.W[TypeName]
to [TypeName]x4
, allowing room for [TypeName]x8
.mint
for scalar typeswgpu
-specfic notes to projection
module (adds _wgpu
to some function names)Rotor3::rotate_vecs()
for improved performance on rotating multiple vecs with the same rotor[WideType]::merge()
to [WideType]::blend()
Into<Vec2; N> for Vec2xN
implementationsconst
MatN::determinant()
Mat2::inverse()
If you're interested, go check it out on crates.io, use it, and let me know if you have any issues or other feedback by visiting the GitHub issue tracker!