Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a way to fix struct offsets automatically #52

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::iter;
use std::{iter, mem::MaybeUninit};

use crate::shader::ENTRY_FS_MAIN;
use futures::executor::block_on;
Expand Down Expand Up @@ -143,6 +143,7 @@ impl<'a> State<'a> {
label: Some("uniforms"),
contents: bytemuck::cast_slice(&[shader::Uniforms {
color_rgb: [1.0, 1.0, 1.0, 1.0],
_pad_color_rgb: []
}]),
usage: wgpu::BufferUsages::UNIFORM,
});
Expand Down
5 changes: 3 additions & 2 deletions example/src/shader.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// File automatically generated by build.rs.
// Changes made to this file will not be saved.
#[repr(C)]
#[repr(C, packed)]
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct VertexInput {
pub position: [f32; 3],
}
#[repr(C)]
#[repr(C, packed)]
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Uniforms {
pub color_rgb: [f32; 4],
pub _pad_color_rgb: [u8; 16 - 0 - core::mem::size_of::<[f32; 4]>()],
}
const _: () = assert!(
std::mem::size_of:: < Uniforms > () == 16, "size of Uniforms does not match WGSL"
Expand Down
41 changes: 30 additions & 11 deletions wgsl_to_wgpu/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,16 @@ fn rust_struct(
const _: () = assert!(std::mem::size_of::<#struct_name>() == #struct_size, #assert_size_text);
};

// Assume types used in global variables are host shareable and require validation.
// This includes storage, uniform, and workgroup variables.
// This also means types that are never used will not be validated.
// Structs used only for vertex inputs do not require validation on desktop platforms.
// Vertex input layout is handled already by setting the attribute offsets and types.
// This allows vertex input field types without padding like vec3 for positions.
let is_host_shareable = global_variable_types.contains(&t_handle);

let has_rts_array = struct_has_rts_array_member(members, module);
let members = struct_members(members, module, options);
let members = struct_members(members, module, options, layout.size as usize, is_host_shareable);
let mut derives = Vec::new();

derives.push(quote!(Debug));
Expand All @@ -122,14 +130,6 @@ fn rust_struct(
derives.push(quote!(serde::Deserialize));
}

// Assume types used in global variables are host shareable and require validation.
// This includes storage, uniform, and workgroup variables.
// This also means types that are never used will not be validated.
// Structs used only for vertex inputs do not require validation on desktop platforms.
// Vertex input layout is handled already by setting the attribute offsets and types.
// This allows vertex input field types without padding like vec3 for positions.
let is_host_shareable = global_variable_types.contains(&t_handle);

let assert_layout = if options.derive_bytemuck && is_host_shareable {
// Assert that the Rust layout matches the WGSL layout.
// Enable for bytemuck since it uses the Rust struct's memory layout.
Expand All @@ -142,7 +142,7 @@ fn rust_struct(
};

let repr_c = if !has_rts_array {
quote!(#[repr(C)])
quote!(#[repr(C, packed)])
} else {
quote!()
};
Expand Down Expand Up @@ -180,6 +180,8 @@ fn struct_members(
members: &[naga::StructMember],
module: &naga::Module,
options: WriteOptions,
struct_size: usize,
enable_padding: bool,
) -> Vec<TokenStream> {
members
.iter()
Expand All @@ -204,8 +206,25 @@ fn struct_members(
pub #member_name: Vec<#element_type>
)
} else {
let member_type = rust_type(module, ty, options.matrix_vector_types);
let member_type = rust_type(module, ty, options.matrix_vector_types);
if !enable_padding {
quote!(pub #member_name: #member_type)
} else {
let current_offset = Index::from(member.offset as usize);

let next_offset = if index == members.len() - 1 {
Index::from(struct_size)
} else {
Index::from(members[index + 1].offset as usize)
};

let pad_member_name = Ident::new(&format!("_pad_{}", member_name), Span::call_site());

quote!(
pub #member_name: #member_type,
pub #pad_member_name: [u8; #next_offset - #current_offset - core::mem::size_of::<#member_type>()]
)
}
}
})
.collect()
Expand Down