vulkano/TROUBLES.md
2016-04-28 16:39:54 +02:00

4.3 KiB

Troubles encountered with Rust during the making of this library

  • No way to store an object and its borrowing in the same struct. This is the reason why the whole API uses Arcs.

  • No pointer-to-struct-member. When you request the GPU to perform an operation on some data, you have to give a pointer to the data that must be manipulated. However regular Rust pointers can't be used, as the buffers are not necessarily in the memory accessible from your program. Instead vulkano provides its own pointer-like struct named BufferSlice. The problem is that there is no way to safely convert a BufferSlice<Foo> (equivalent of a virtual &Foo), where struct Foo { a: i32 }, into a BufferSlice<i32> (equivalent of a virtual &i32) pointing to the a member.

  • Lack of plugins means that you have to use a build script to compile your shaders instead of inlining them directly where they are used. In addition to this, lots of existing macros would be much simpler to implement with plugins. The code generated by macros is currently inefficient because using the efficient way would make the code very difficult to read.

  • Having a trait that defines which types can be put inside buffers is very annoying, as users have to implement it for every single struct they create. The best solution would be to use impl BufferContent for ... {}, but this syntax is still unstable. Vulkano currently doesn't enforce any trait for buffers contents, but that's unsafe.

  • When T is unsized, there's no way to create a *mut T pointer from a *mut c_void and a size. This had to be implemented in a hacky (and very dangerous) way with a custom trait.

  • https://github.com/rust-lang/rust/issues/29701 The fact that is legal to implement Deref and make deref() return a different object every time means that it is dangerous to interface with a Foo through a P where P: Deref<Foo>. That P could return several different Foos every time you deref it, and the implementation can't rely on the fact that the object will be the same every time.

  • This library was designed with specialization in mind. There are several is_compatible trait methods that perform deep comparisons between layouts. With specialization available, these methods could be specialized as true for layouts that are known to always be compatible.

  • https://github.com/rust-lang/rust/issues/29328

  • "Source trait is private" errors when traits are declared in private modules but reexported publicly from a parent module. Not sure if that's a bug or a feature from the privacy system, but in both cases it's annoying.

  • Some trait implementations have an associated type that looks like type T = (Arc<Foo>, Arc<Bar>);. HKTs would allow this parameter to take references to the Arcs instead, and avoid having to clone them. This problem could by bypassed by making the code more ugly, but it's not worth it just to avoid cloning some Arcs.

  • Visibility rules mean that you can't write struct Error; pub mod foo { pub struct Foo; impl From<Error> for Foo { ... } }. Rustc complains that Error is private and exported in Foo's signature, even though that's in the author's opinion a totally legitimate usage.

  • This repository contains the vulkano-shaders library, which generates Rust code that uses the vulkano library. If the API of vulkano gets a breaking change, there is no way to enforce or to check the fact that the user uses a correct combination of versions for vulkano-shaders and vulkano. Procedural macros declared in vulkano itself would solve this (https://github.com/rust-lang/rfcs/pull/1566).

  • No way to set the alignment of a struct member, or to force the size of a struct to be a multiple of a certain size. Some parts of the Vulkan API enforce some limitations regarding the alignment, and either the user or the vulkano-shaders code generator currently has to manually add dummy padding fields.

  • No way to create dynamic-sized arrays on the stack. A lot of Vulkan functions require passing an array of small elements (small structs or integers). Building such an array with a Vec can be expensive, especially when most of the time the array only contains a single element. This is currently solved with the SmallVec type, but doing so wastes memory.