From 9afa9b86b6b10701b977619f75211c812aa329ca Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 2 Mar 2021 09:57:49 -0800 Subject: [PATCH] Add encoding of flags into tag Add a `TagFlags` type. You can write enum variants as `Variant(TagFlags, Content)` and this will encode a u16 into the top 16 bits of the tag word. --- piet-gpu-derive/src/derive.rs | 28 ++++++++++++++++++++++------ piet-gpu-derive/src/glsl.rs | 34 ++++++++++++++++++++++++++++------ piet-gpu-derive/src/layout.rs | 2 +- piet-gpu-derive/src/parse.rs | 3 +++ 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/piet-gpu-derive/src/derive.rs b/piet-gpu-derive/src/derive.rs index 3b4c478..f5f78f3 100644 --- a/piet-gpu-derive/src/derive.rs +++ b/piet-gpu-derive/src/derive.rs @@ -73,18 +73,31 @@ fn gen_derive_def(name: &str, size: usize, def: &LayoutTypeDef) -> proc_macro2:: let mut args = Vec::new(); let mut field_encoders = proc_macro2::TokenStream::new(); - for (i, (offset, _ty)) in payload.iter().enumerate() { + let mut tag_field = None; + for (i, (offset, ty)) in payload.iter().enumerate() { let field_id = format_ident!("f{}", i); - let field_encoder = quote! { - #field_id.encode_to(&mut buf[#offset..]); - }; - field_encoders.extend(field_encoder); + if matches!(ty.ty, GpuType::Scalar(GpuScalar::TagFlags)) { + tag_field = Some(field_id.clone()); + } else { + let field_encoder = quote! { + #field_id.encode_to(&mut buf[#offset..]); + }; + field_encoders.extend(field_encoder); + } args.push(field_id); } let tag = variant_ix as u32; + let tag_encode = match tag_field { + None => quote! { + buf[0..4].copy_from_slice(&#tag.to_le_bytes()); + }, + Some(tag_field) => quote! { + buf[0..4].copy_from_slice(&(#tag | ((*#tag_field as u32) << 16)).to_le_bytes()); + }, + }; let case = quote! { #name_id::#variant_id(#(#args),*) => { - buf[0..4].copy_from_slice(&#tag.to_le_bytes()); + #tag_encode #field_encoders } }; @@ -139,12 +152,15 @@ fn gen_derive_scalar_ty(ty: &GpuScalar) -> proc_macro2::TokenStream { GpuScalar::U8 => quote!(u8), GpuScalar::U16 => quote!(u16), GpuScalar::U32 => quote!(u32), + GpuScalar::TagFlags => quote!(u16), } } fn gen_encode_field(name: &str, offset: usize, ty: &GpuType) -> proc_macro2::TokenStream { let name_id = format_ident!("{}", name); match ty { + // encoding of flags into tag word is handled elsewhere + GpuType::Scalar(GpuScalar::TagFlags) => quote! {}, GpuType::Scalar(s) => { let end = offset + s.size(); quote! { diff --git a/piet-gpu-derive/src/glsl.rs b/piet-gpu-derive/src/glsl.rs index ce862b0..eb9b7fb 100644 --- a/piet-gpu-derive/src/glsl.rs +++ b/piet-gpu-derive/src/glsl.rs @@ -8,7 +8,11 @@ use crate::parse::{GpuScalar, GpuType}; pub fn gen_glsl(module: &LayoutModule) -> String { let mut r = String::new(); - writeln!(&mut r, "// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense\n").unwrap(); + writeln!( + &mut r, + "// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense\n" + ) + .unwrap(); writeln!(&mut r, "// Code auto-generated by piet-gpu-derive\n").unwrap(); // Note: GLSL needs definitions before uses. We could do a topological sort here, // but easiest for now to just require that in spec. @@ -147,8 +151,19 @@ fn gen_enum_read( } writeln!(r, "}}\n").unwrap(); for (var_name, payload) in variants { - if payload.len() == 1 { - if let GpuType::InlineStruct(structname) = &payload[0].1.ty { + let payload_ix = if payload.len() == 1 { + Some(0) + } else if payload.len() == 2 { + if matches!(payload[0].1.ty, GpuType::Scalar(GpuScalar::TagFlags)) { + Some(1) + } else { + None + } + } else { + None + }; + if let Some(payload_ix) = payload_ix { + if let GpuType::InlineStruct(structname) = &payload[payload_ix].1.ty { if is_mem { writeln!( r, @@ -257,6 +272,7 @@ fn gen_extract_scalar(offset: usize, ty: &GpuScalar) -> String { GpuScalar::F16 | GpuScalar::F32 => extract_fbits(offset, ty.size()), GpuScalar::U8 | GpuScalar::U16 | GpuScalar::U32 => extract_ubits(offset, ty.size()), GpuScalar::I8 | GpuScalar::I16 | GpuScalar::I32 => extract_ibits(offset, ty.size()), + GpuScalar::TagFlags => format!("0 /* TODO */"), } } @@ -455,6 +471,7 @@ fn gen_pack_bits_scalar(ty: &GpuScalar, offset: usize, inner: &str) -> String { } } GpuScalar::I32 => format!("uint({})", inner), + GpuScalar::TagFlags => format!("0"), }; if shift == 0 { bits @@ -473,7 +490,12 @@ fn gen_enum_write( for (var_name, payload) in variants { if payload.is_empty() { if is_mem { - writeln!(r, "void {}_{}_write(Alloc a, {}Ref ref) {{", name, var_name, name).unwrap(); + writeln!( + r, + "void {}_{}_write(Alloc a, {}Ref ref) {{", + name, var_name, name + ) + .unwrap(); writeln!( r, " write_mem(a, ref.offset >> 2, {}_{});", @@ -566,7 +588,7 @@ fn glsl_scalar(s: &GpuScalar) -> &'static str { match s { GpuScalar::F16 | GpuScalar::F32 => "float", GpuScalar::I8 | GpuScalar::I16 | GpuScalar::I32 => "int", - GpuScalar::U8 | GpuScalar::U16 | GpuScalar::U32 => "uint", + GpuScalar::U8 | GpuScalar::U16 | GpuScalar::U32 | GpuScalar::TagFlags => "uint", } } @@ -574,7 +596,7 @@ fn glsl_vecname(s: &GpuScalar) -> &'static str { match s { GpuScalar::F16 | GpuScalar::F32 => "vec", GpuScalar::I8 | GpuScalar::I16 | GpuScalar::I32 => "ivec", - GpuScalar::U8 | GpuScalar::U16 | GpuScalar::U32 => "uvec", + GpuScalar::U8 | GpuScalar::U16 | GpuScalar::U32 | GpuScalar::TagFlags => "uvec", } } diff --git a/piet-gpu-derive/src/layout.rs b/piet-gpu-derive/src/layout.rs index aef0048..47f1dcb 100644 --- a/piet-gpu-derive/src/layout.rs +++ b/piet-gpu-derive/src/layout.rs @@ -240,5 +240,5 @@ impl Size { } fn align_padding(offset: usize, alignment: usize) -> usize { - offset.wrapping_neg() & (alignment - 1) + offset.wrapping_neg() & (alignment.max(1) - 1) } diff --git a/piet-gpu-derive/src/parse.rs b/piet-gpu-derive/src/parse.rs index 9461338..1598987 100644 --- a/piet-gpu-derive/src/parse.rs +++ b/piet-gpu-derive/src/parse.rs @@ -20,6 +20,7 @@ pub enum GpuScalar { U8, U16, U32, + TagFlags, } /// An algebraic datatype. @@ -59,6 +60,7 @@ impl GpuScalar { "u8" => Some(GpuScalar::U8), "u16" => Some(GpuScalar::U16), "u32" => Some(GpuScalar::U32), + "TagFlags" => Some(GpuScalar::TagFlags), _ => None, }) } @@ -72,6 +74,7 @@ impl GpuScalar { GpuScalar::F32 | GpuScalar::I32 | GpuScalar::U32 => 4, GpuScalar::I8 | GpuScalar::U8 => 1, GpuScalar::F16 | GpuScalar::I16 | GpuScalar::U16 => 2, + GpuScalar::TagFlags => 0, } } }