This proposal argues for introduction of the builder pattern for most of the structs of the public API. It is a reaction to the recent introduction of the usage of Cow in the API which results in quite a lot of noise.
Consider the following example:
let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
bind_group_layouts: Borrowed(&[&camera_bind_group_layout, &per_molecule_bind_group_layout]),
push_constant_ranges: Borrowed(&[]),
});
versus
let pipeline_layout = device.create_pipeline_layout(PipelineLayoutDescriptor::new()
.bind_group_layouts(&[&camera_bind_group_layout, &per_molecule_bind_group_layout])
);
Notice several things:
... Default::default().Borrowed can be omitted. This is taken from article https://jwilm.io/blog/from-str-to-cow/ and would be done by annotating setter functions with Input: Into<Cow<ActualInput>.All of this creates, in my opinion: cleaner, more readable, easily writable(especially Borrowed could be confusing for beginners to Rust) WebGPU code.
This builder pattern is inspired by the Ash crate.
Thank you for filing this!
Benefits:
wgpu-types struct no longer need to be generic (since wgpu-rs API would no longer try to reuse them)Downsides: more code
Note that that setter API is not actually going to work: If you accept a Input: Into<Cow<'a, [T]>, then passing an &[T; N] argument will not do a deref coercion. That is in fact why we used Borrowed() there: If you tried to use From or Into, you would have to explicitly slice the array literal with [..] as well.
See here for an example.
Something that might be interesting to note is that even though &[T; N] does not coerce to Cow<'a, [T]>, Vec<T> does coerce to Cow<'a, [T]>, therefore the vec! macro could be used. An example of this is shown in the following example.
The only difference of using Vec instead of an array slices is that a Cow::Owned<'a, [T]> is passed instead of Cow::Borrow<'a, [T]>.
I don't think this approach will have any runtime penalty because the Vec is moved but I am not sure about it.
We've also been hinted that we could use our own trait bound instead of Into<Cow<>. The benefit of that would be the ability to manually implement it for &[T; 1], &[T; 2], etc, meaning that the regular slice syntax is used on the user side, and they don't really have to know about the trait.
We've also been hinted that we could use our own trait bound instead of
Into<Cow<>. The benefit of that would be the ability to manually implement it for&[T; 1],&[T; 2], etc, meaning that the regular slice syntax is used on the user side, and they don't really have to know about the trait.
I quite like this solution. And when const generics will come, we can just implement it for &[T; S] right?
Closed in https://github.com/gfx-rs/wgpu/pull/840 and then removed.
Most helpful comment
We've also been hinted that we could use our own trait bound instead of
Into<Cow<>. The benefit of that would be the ability to manually implement it for&[T; 1],&[T; 2], etc, meaning that the regular slice syntax is used on the user side, and they don't really have to know about the trait.