323 lines
7.9 KiB
Rust
323 lines
7.9 KiB
Rust
|
|
use variadics_please::all_tuples_with_size;
|
||
|
|
use wgpu::{BindGroupEntry, BindingResource};
|
||
|
|
|
||
|
|
use super::{Sampler, TextureView};
|
||
|
|
|
||
|
|
/// Helper for constructing bindgroups.
|
||
|
|
///
|
||
|
|
/// Allows constructing the descriptor's entries as:
|
||
|
|
/// ```ignore (render_device cannot be easily accessed)
|
||
|
|
/// render_device.create_bind_group(
|
||
|
|
/// "my_bind_group",
|
||
|
|
/// &my_layout,
|
||
|
|
/// &BindGroupEntries::with_indices((
|
||
|
|
/// (2, &my_sampler),
|
||
|
|
/// (3, my_uniform),
|
||
|
|
/// )),
|
||
|
|
/// );
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// instead of
|
||
|
|
///
|
||
|
|
/// ```ignore (render_device cannot be easily accessed)
|
||
|
|
/// render_device.create_bind_group(
|
||
|
|
/// "my_bind_group",
|
||
|
|
/// &my_layout,
|
||
|
|
/// &[
|
||
|
|
/// BindGroupEntry {
|
||
|
|
/// binding: 2,
|
||
|
|
/// resource: BindingResource::Sampler(&my_sampler),
|
||
|
|
/// },
|
||
|
|
/// BindGroupEntry {
|
||
|
|
/// binding: 3,
|
||
|
|
/// resource: my_uniform,
|
||
|
|
/// },
|
||
|
|
/// ],
|
||
|
|
/// );
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// or
|
||
|
|
///
|
||
|
|
/// ```ignore (render_device cannot be easily accessed)
|
||
|
|
/// render_device.create_bind_group(
|
||
|
|
/// "my_bind_group",
|
||
|
|
/// &my_layout,
|
||
|
|
/// &BindGroupEntries::sequential((
|
||
|
|
/// &my_sampler,
|
||
|
|
/// my_uniform,
|
||
|
|
/// )),
|
||
|
|
/// );
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// instead of
|
||
|
|
///
|
||
|
|
/// ```ignore (render_device cannot be easily accessed)
|
||
|
|
/// render_device.create_bind_group(
|
||
|
|
/// "my_bind_group",
|
||
|
|
/// &my_layout,
|
||
|
|
/// &[
|
||
|
|
/// BindGroupEntry {
|
||
|
|
/// binding: 0,
|
||
|
|
/// resource: BindingResource::Sampler(&my_sampler),
|
||
|
|
/// },
|
||
|
|
/// BindGroupEntry {
|
||
|
|
/// binding: 1,
|
||
|
|
/// resource: my_uniform,
|
||
|
|
/// },
|
||
|
|
/// ],
|
||
|
|
/// );
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// or
|
||
|
|
///
|
||
|
|
/// ```ignore (render_device cannot be easily accessed)
|
||
|
|
/// render_device.create_bind_group(
|
||
|
|
/// "my_bind_group",
|
||
|
|
/// &my_layout,
|
||
|
|
/// &BindGroupEntries::single(my_uniform),
|
||
|
|
/// );
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// instead of
|
||
|
|
///
|
||
|
|
/// ```ignore (render_device cannot be easily accessed)
|
||
|
|
/// render_device.create_bind_group(
|
||
|
|
/// "my_bind_group",
|
||
|
|
/// &my_layout,
|
||
|
|
/// &[
|
||
|
|
/// BindGroupEntry {
|
||
|
|
/// binding: 0,
|
||
|
|
/// resource: my_uniform,
|
||
|
|
/// },
|
||
|
|
/// ],
|
||
|
|
/// );
|
||
|
|
/// ```
|
||
|
|
pub struct BindGroupEntries<'b, const N: usize = 1> {
|
||
|
|
entries: [BindGroupEntry<'b>; N],
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'b, const N: usize> BindGroupEntries<'b, N> {
|
||
|
|
#[inline]
|
||
|
|
pub fn sequential(resources: impl IntoBindingArray<'b, N>) -> Self {
|
||
|
|
let mut i = 0;
|
||
|
|
Self {
|
||
|
|
entries: resources.into_array().map(|resource| {
|
||
|
|
let binding = i;
|
||
|
|
i += 1;
|
||
|
|
BindGroupEntry { binding, resource }
|
||
|
|
}),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[inline]
|
||
|
|
pub fn with_indices(indexed_resources: impl IntoIndexedBindingArray<'b, N>) -> Self {
|
||
|
|
Self {
|
||
|
|
entries: indexed_resources
|
||
|
|
.into_array()
|
||
|
|
.map(|(binding, resource)| BindGroupEntry { binding, resource }),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'b> BindGroupEntries<'b, 1> {
|
||
|
|
pub fn single(resource: impl IntoBinding<'b>) -> [BindGroupEntry<'b>; 1] {
|
||
|
|
[BindGroupEntry {
|
||
|
|
binding: 0,
|
||
|
|
resource: resource.into_binding(),
|
||
|
|
}]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'b, const N: usize> core::ops::Deref for BindGroupEntries<'b, N> {
|
||
|
|
type Target = [BindGroupEntry<'b>];
|
||
|
|
|
||
|
|
fn deref(&self) -> &[BindGroupEntry<'b>] {
|
||
|
|
&self.entries
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub trait IntoBinding<'a> {
|
||
|
|
fn into_binding(self) -> BindingResource<'a>;
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for &'a TextureView {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::TextureView(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for &'a wgpu::TextureView {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::TextureView(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for &'a [&'a wgpu::TextureView] {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::TextureViewArray(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for &'a Sampler {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::Sampler(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for &'a [&'a wgpu::Sampler] {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::SamplerArray(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for BindingResource<'a> {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
self
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for wgpu::BufferBinding<'a> {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::Buffer(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'a> IntoBinding<'a> for &'a [wgpu::BufferBinding<'a>] {
|
||
|
|
#[inline]
|
||
|
|
fn into_binding(self) -> BindingResource<'a> {
|
||
|
|
BindingResource::BufferArray(self)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub trait IntoBindingArray<'b, const N: usize> {
|
||
|
|
fn into_array(self) -> [BindingResource<'b>; N];
|
||
|
|
}
|
||
|
|
|
||
|
|
macro_rules! impl_to_binding_slice {
|
||
|
|
($N: expr, $(#[$meta:meta])* $(($T: ident, $I: ident)),*) => {
|
||
|
|
$(#[$meta])*
|
||
|
|
impl<'b, $($T: IntoBinding<'b>),*> IntoBindingArray<'b, $N> for ($($T,)*) {
|
||
|
|
#[inline]
|
||
|
|
fn into_array(self) -> [BindingResource<'b>; $N] {
|
||
|
|
let ($($I,)*) = self;
|
||
|
|
[$($I.into_binding(), )*]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
all_tuples_with_size!(
|
||
|
|
#[doc(fake_variadic)]
|
||
|
|
impl_to_binding_slice,
|
||
|
|
1,
|
||
|
|
32,
|
||
|
|
T,
|
||
|
|
s
|
||
|
|
);
|
||
|
|
|
||
|
|
pub trait IntoIndexedBindingArray<'b, const N: usize> {
|
||
|
|
fn into_array(self) -> [(u32, BindingResource<'b>); N];
|
||
|
|
}
|
||
|
|
|
||
|
|
macro_rules! impl_to_indexed_binding_slice {
|
||
|
|
($N: expr, $(($T: ident, $S: ident, $I: ident)),*) => {
|
||
|
|
impl<'b, $($T: IntoBinding<'b>),*> IntoIndexedBindingArray<'b, $N> for ($((u32, $T),)*) {
|
||
|
|
#[inline]
|
||
|
|
fn into_array(self) -> [(u32, BindingResource<'b>); $N] {
|
||
|
|
let ($(($S, $I),)*) = self;
|
||
|
|
[$(($S, $I.into_binding())), *]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
all_tuples_with_size!(impl_to_indexed_binding_slice, 1, 32, T, n, s);
|
||
|
|
|
||
|
|
pub struct DynamicBindGroupEntries<'b> {
|
||
|
|
entries: Vec<BindGroupEntry<'b>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'b> Default for DynamicBindGroupEntries<'b> {
|
||
|
|
fn default() -> Self {
|
||
|
|
Self::new()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'b> DynamicBindGroupEntries<'b> {
|
||
|
|
pub fn sequential<const N: usize>(entries: impl IntoBindingArray<'b, N>) -> Self {
|
||
|
|
Self {
|
||
|
|
entries: entries
|
||
|
|
.into_array()
|
||
|
|
.into_iter()
|
||
|
|
.enumerate()
|
||
|
|
.map(|(ix, resource)| BindGroupEntry {
|
||
|
|
binding: ix as u32,
|
||
|
|
resource,
|
||
|
|
})
|
||
|
|
.collect(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn extend_sequential<const N: usize>(
|
||
|
|
mut self,
|
||
|
|
entries: impl IntoBindingArray<'b, N>,
|
||
|
|
) -> Self {
|
||
|
|
let start = self.entries.last().unwrap().binding + 1;
|
||
|
|
self.entries.extend(
|
||
|
|
entries
|
||
|
|
.into_array()
|
||
|
|
.into_iter()
|
||
|
|
.enumerate()
|
||
|
|
.map(|(ix, resource)| BindGroupEntry {
|
||
|
|
binding: start + ix as u32,
|
||
|
|
resource,
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
self
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn new_with_indices<const N: usize>(entries: impl IntoIndexedBindingArray<'b, N>) -> Self {
|
||
|
|
Self {
|
||
|
|
entries: entries
|
||
|
|
.into_array()
|
||
|
|
.into_iter()
|
||
|
|
.map(|(binding, resource)| BindGroupEntry { binding, resource })
|
||
|
|
.collect(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn new() -> Self {
|
||
|
|
Self {
|
||
|
|
entries: Vec::new(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn extend_with_indices<const N: usize>(
|
||
|
|
mut self,
|
||
|
|
entries: impl IntoIndexedBindingArray<'b, N>,
|
||
|
|
) -> Self {
|
||
|
|
self.entries.extend(
|
||
|
|
entries
|
||
|
|
.into_array()
|
||
|
|
.into_iter()
|
||
|
|
.map(|(binding, resource)| BindGroupEntry { binding, resource }),
|
||
|
|
);
|
||
|
|
self
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<'b> core::ops::Deref for DynamicBindGroupEntries<'b> {
|
||
|
|
type Target = [BindGroupEntry<'b>];
|
||
|
|
|
||
|
|
fn deref(&self) -> &[BindGroupEntry<'b>] {
|
||
|
|
&self.entries
|
||
|
|
}
|
||
|
|
}
|