Skip to content

Typesafe initialization with BindGroup0::from_data() #28

Description

@JMLX42

Hi there!

Great project!

As someone who struggled a lot to have proper shader <=> CPU bindings, I really love the idea to leverage Rust code generation + strong typing to make this easier.

To make it even easier, would it make sense to implement a BindGroup0::from_data() method relying on encase to create the bind group directly from the uniform data:

             pub fn from_data(device: &wgpu::Device, #(#fields),*) -> Self {
                use wgpu::util::DeviceExt;
                use encase::ShaderType;

                let mut buffer = encase::DynamicUniformBuffer::new(Vec::new());
                #(
                    buffer.write(#field_names).unwrap();
                    buffer.set_offset(device.limits().min_uniform_buffer_offset_alignment as u64);
                )*
                let bytes = buffer.into_inner();
                let uniform_bufer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
                    label: None,
                    contents: &bytes,
                    usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
                });
                
                Self::from_bindings(
                    device,
                    #bind_group_layout_name {
                        #(#bindings),*
                    },
                )
            }

Example of output:

        pub fn from_data(
            device: &wgpu::Device,
            material: &super::Material,
            alpha: &super::Alpha,
        ) -> Self {
            use wgpu::util::DeviceExt;
            use encase::ShaderType;
            let mut buffer = encase::DynamicUniformBuffer::new(Vec::new());
            buffer.write(material).unwrap();
            buffer
                .set_offset(device.limits().min_uniform_buffer_offset_alignment as u64);
            buffer.write(alpha).unwrap();
            buffer
                .set_offset(device.limits().min_uniform_buffer_offset_alignment as u64);
            let bytes = buffer.into_inner();
            let uniform_bufer = device
                .create_buffer_init(
                    &wgpu::util::BufferInitDescriptor {
                        label: None,
                        contents: &bytes,
                        usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
                    },
                );
            Self::from_bindings(
                device,
                BindGroupLayout0 {
                    material: wgpu::BufferBinding {
                        buffer: &uniform_bufer,
                        offset: 0,
                        size: Some(super::Material::min_size()),
                    },
                    alpha: wgpu::BufferBinding {
                        buffer: &uniform_bufer,
                        offset: (1u32
                            * device.limits().min_uniform_buffer_offset_alignment)
                            as u64,
                        size: Some(super::Alpha::min_size()),
                    },
                },
            )
        }

Usage example:

let material = shader::Material {
  color: nalgebra::Vector3::new(1.0, 1.0, 0.0),
};
let alpha = shader::Alpha { value: 1.0 };
let bind_group0 = shader::bind_groups::BindGroup0::from_data(&device, &material, &alpha);

If that makes sense I'll open a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions