Remove MemberOrigin in favor of spans

This commit is contained in:
Dzmitry Malyshau
2020-12-18 00:33:22 -05:00
committed by Dzmitry Malyshau
parent fca72fd333
commit b95346877a
10 changed files with 79 additions and 167 deletions

View File

@@ -6,7 +6,7 @@ all:
clean:
rm *.metal *.air *.metallib *.vert *.frag *.comp
%.metal: test-data/%.wgsl $(wildcard src/*.rs src/**/*.rs examples/*.rs)
%.metal: tests/snapshots/in/%.wgsl $(wildcard src/*.rs src/**/*.rs examples/*.rs)
cargo run --example convert --features wgsl-in,msl-out -- $< $@
%.air: %.metal

View File

@@ -57,20 +57,15 @@ pub enum Error {
IO(IoError),
Utf8(FromUtf8Error),
Type(ResolveError),
UnexpectedLocation,
MissingBinding(Handle<crate::GlobalVariable>),
MissingBindTarget(BindSource),
InvalidImageAccess(crate::StorageAccess),
MutabilityViolation(Handle<crate::GlobalVariable>),
BadName(String),
UnexpectedGlobalType(Handle<crate::Type>),
UnimplementedBindTarget(BindTarget),
UnsupportedCompose(Handle<crate::Type>),
UnsupportedBinaryOp(crate::BinaryOperator),
UnexpectedSampleLevel(crate::SampleLevel),
UnsupportedCall(String),
UnsupportedDynamicArrayLength,
UnableToReturnValue(Handle<crate::Expression>),
/// The source IR is not valid.
Validation,
}
@@ -115,12 +110,12 @@ impl Options {
fn resolve_binding(
&self,
stage: crate::ShaderStage,
binding: &crate::Binding,
var: &crate::GlobalVariable,
mode: LocationMode,
) -> Result<ResolvedBinding, Error> {
match *binding {
crate::Binding::BuiltIn(built_in) => Ok(ResolvedBinding::BuiltIn(built_in)),
crate::Binding::Location(index) => match mode {
match var.binding {
Some(crate::Binding::BuiltIn(built_in)) => Ok(ResolvedBinding::BuiltIn(built_in)),
Some(crate::Binding::Location(index)) => match mode {
LocationMode::VertexInput => Ok(ResolvedBinding::Attribute(index)),
LocationMode::FragmentOutput => Ok(ResolvedBinding::Color(index)),
LocationMode::Intermediate => Ok(ResolvedBinding::User {
@@ -131,9 +126,15 @@ impl Options {
},
index,
}),
LocationMode::Uniform => Err(Error::UnexpectedLocation),
LocationMode::Uniform => {
log::error!(
"Unexpected Binding::Location({}) for the Uniform mode",
index
);
Err(Error::Validation)
}
},
crate::Binding::Resource { group, binding } => {
Some(crate::Binding::Resource { group, binding }) => {
let source = BindSource {
stage,
group,
@@ -145,6 +146,10 @@ impl Options {
.map(ResolvedBinding::Resource)
.ok_or(Error::MissingBindTarget(source))
}
None => {
log::error!("Missing binding for {:?}", var.name);
Err(Error::Validation)
}
}
}
}

View File

@@ -1,4 +1,4 @@
use super::{keywords::RESERVED, Error, LocationMode, Options, ResolvedBinding, TranslationInfo};
use super::{keywords::RESERVED, Error, LocationMode, Options, TranslationInfo};
use crate::{
arena::Handle,
proc::{EntryPointIndex, NameKey, Namer, ResolveContext, Typifier},
@@ -740,18 +740,7 @@ impl<W: Write> Writer<W> {
for (index, member) in members.iter().enumerate() {
let member_name = &self.names[&NameKey::StructMember(handle, index as u32)];
let base_name = &self.names[&NameKey::Type(member.ty)];
write!(self.out, "\t{} {}", base_name, member_name)?;
match member.origin {
crate::MemberOrigin::Empty => {}
crate::MemberOrigin::BuiltIn(built_in) => {
ResolvedBinding::BuiltIn(built_in)
.try_fmt_decorated(&mut self.out, "")?;
}
crate::MemberOrigin::Offset(_) => {
//TODO
}
}
writeln!(self.out, ";")?;
writeln!(self.out, "\t{} {};", base_name, member_name)?;
}
write!(self.out, "}}")?;
}
@@ -932,7 +921,6 @@ impl<W: Write> Writer<W> {
crate::ShaderStage::Vertex | crate::ShaderStage::Fragment => {
// make dedicated input/output structs
writeln!(self.out, "struct {} {{", location_input_name)?;
for ((handle, var), &usage) in
module.global_variables.iter().zip(&fun.global_usage)
{
@@ -941,36 +929,20 @@ impl<W: Write> Writer<W> {
{
continue;
}
// if it's a struct, lift all the built-in contents up to the root
if let crate::TypeInner::Struct {
block: _,
ref members,
} = module.types[var.ty].inner
{
for (index, member) in members.iter().enumerate() {
if let crate::MemberOrigin::BuiltIn(built_in) = member.origin {
let name =
&self.names[&NameKey::StructMember(var.ty, index as u32)];
let ty_name = &self.names[&NameKey::Type(member.ty)];
write!(self.out, "\t{} {}", ty_name, name)?;
ResolvedBinding::BuiltIn(built_in)
.try_fmt_decorated(&mut self.out, ";\n")?;
}
}
} else if let Some(ref binding @ crate::Binding::Location(_)) = var.binding
{
let tyvar = TypedGlobalVariable {
module,
names: &self.names,
handle,
usage: crate::GlobalUse::empty(),
};
let resolved = options.resolve_binding(stage, binding, in_mode)?;
write!(self.out, "\t")?;
tyvar.try_fmt(&mut self.out)?;
resolved.try_fmt_decorated(&mut self.out, ";\n")?;
if let Some(crate::Binding::BuiltIn(_)) = var.binding {
// MSL disallows built-ins in input structs
continue;
}
let tyvar = TypedGlobalVariable {
module,
names: &self.names,
handle,
usage: crate::GlobalUse::empty(),
};
write!(self.out, "\t")?;
tyvar.try_fmt(&mut self.out)?;
let resolved = options.resolve_binding(stage, var, in_mode)?;
resolved.try_fmt_decorated(&mut self.out, ";\n")?;
}
writeln!(self.out, "}};")?;
@@ -983,43 +955,17 @@ impl<W: Write> Writer<W> {
{
continue;
}
// if it's a struct, lift all the built-in contents up to the root
if let crate::TypeInner::Struct {
block: _,
ref members,
} = module.types[var.ty].inner
{
for (index, member) in members.iter().enumerate() {
let name =
&self.names[&NameKey::StructMember(var.ty, index as u32)];
let ty_name = &self.names[&NameKey::Type(member.ty)];
match member.origin {
crate::MemberOrigin::Empty => {}
crate::MemberOrigin::BuiltIn(built_in) => {
write!(self.out, "\t{} {}", ty_name, name)?;
ResolvedBinding::BuiltIn(built_in)
.try_fmt_decorated(&mut self.out, ";\n")?;
}
crate::MemberOrigin::Offset(_) => {
//TODO
}
}
}
} else {
let tyvar = TypedGlobalVariable {
module,
names: &self.names,
handle,
usage: crate::GlobalUse::empty(),
};
write!(self.out, "\t")?;
tyvar.try_fmt(&mut self.out)?;
if let Some(ref binding) = var.binding {
let resolved = options.resolve_binding(stage, binding, out_mode)?;
resolved.try_fmt_decorated(&mut self.out, "")?;
}
writeln!(self.out, ";")?;
}
let tyvar = TypedGlobalVariable {
module,
names: &self.names,
handle,
usage: crate::GlobalUse::empty(),
};
write!(self.out, "\t")?;
tyvar.try_fmt(&mut self.out)?;
let resolved = options.resolve_binding(stage, var, out_mode)?;
resolved.try_fmt_decorated(&mut self.out, ";\n")?;
}
writeln!(self.out, "}};")?;
@@ -1062,8 +1008,7 @@ impl<W: Write> Writer<W> {
}
_ => LocationMode::Uniform,
};
let resolved =
options.resolve_binding(stage, var.binding.as_ref().unwrap(), loc_mode)?;
let resolved = options.resolve_binding(stage, var, loc_mode)?;
let tyvar = TypedGlobalVariable {
module,
names: &self.names,

View File

@@ -10,7 +10,7 @@ pomelo! {
Arena, BinaryOperator, Binding, Block, Constant,
ConstantInner, EntryPoint, Expression,
Function, GlobalVariable, Handle, Interpolation,
LocalVariable, MemberOrigin, SampleLevel, ScalarKind,
LocalVariable, SampleLevel, ScalarKind,
Statement, StorageAccess, StorageClass, StructMember,
SwitchCase, Type, TypeInner, UnaryOperator,
};
@@ -745,7 +745,7 @@ pomelo! {
if let Some(ty) = t {
sdl.iter().map(|name| StructMember {
name: Some(name.clone()),
origin: MemberOrigin::Empty,
span: None,
ty,
}).collect()
} else {

View File

@@ -204,32 +204,6 @@ impl Decoration {
_ => None,
}
}
fn get_origin(&self) -> Result<crate::MemberOrigin, Error> {
match *self {
Decoration {
location: Some(_), ..
}
| Decoration {
desc_set: Some(_), ..
}
| Decoration {
desc_index: Some(_),
..
} => Err(Error::MissingDecoration(spirv::Decoration::Offset)),
Decoration {
built_in: Some(built_in),
offset: None,
..
} => Ok(crate::MemberOrigin::BuiltIn(built_in)),
Decoration {
built_in: None,
offset: Some(offset),
..
} => Ok(crate::MemberOrigin::Offset(offset)),
_ => Ok(crate::MemberOrigin::Empty),
}
}
}
bitflags::bitflags! {
@@ -2028,6 +2002,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
inst.expect_at_least(2)?;
let id = self.next()?;
let parent_decor = self.future_decor.remove(&id);
let block_decor = parent_decor.as_ref().and_then(|decor| decor.block.clone());
let mut members = Vec::with_capacity(inst.wc as usize - 2);
let mut member_type_ids = Vec::with_capacity(members.capacity());
@@ -2039,15 +2014,13 @@ impl<I: Iterator<Item = u32>> Parser<I> {
.future_member_decor
.remove(&(id, i))
.unwrap_or_default();
let origin = decor.get_origin()?;
members.push(crate::StructMember {
name: decor.name,
origin,
span: None, //TODO
ty,
});
}
let block_decor = parent_decor.as_ref().and_then(|decor| decor.block.clone());
let inner = crate::TypeInner::Struct {
block: block_decor.is_some(),
members,

View File

@@ -82,8 +82,6 @@ pub enum Error<'a> {
UnknownFunction(&'a str),
#[error("unknown storage format: `{0}`")]
UnknownStorageFormat(&'a str),
#[error("missing offset for structure member `{0}`")]
MissingMemberOffset(&'a str),
#[error("array stride must not be 0")]
ZeroStride,
#[error("not a composite type: {0:?}")]
@@ -1131,7 +1129,7 @@ impl Parser {
let mut members = Vec::new();
lexer.expect(Token::Paren('{'))?;
loop {
let mut offset = !0;
let mut span = 0;
if lexer.skip(Token::DoubleParen('[')) {
self.scopes.push(Scope::Decoration);
let mut ready = true;
@@ -1143,9 +1141,10 @@ impl Parser {
Token::Separator(',') if !ready => {
ready = true;
}
Token::Word("offset") if ready => {
Token::Word("span") if ready => {
lexer.expect(Token::Paren('('))?;
offset = lexer.next_uint_literal()?;
//Note: 0 is not handled
span = lexer.next_uint_literal()?;
lexer.expect(Token::Paren(')'))?;
ready = false;
}
@@ -1159,15 +1158,12 @@ impl Parser {
Token::Paren('}') => return Ok(members),
other => return other.unexpected("field name"),
};
if offset == !0 {
return Err(Error::MissingMemberOffset(name));
}
lexer.expect(Token::Separator(':'))?;
let (ty, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
lexer.expect(Token::Separator(';'))?;
members.push(crate::StructMember {
name: Some(name.to_owned()),
origin: crate::MemberOrigin::Offset(offset),
span: NonZeroU32::new(span),
ty,
});
}

View File

@@ -23,13 +23,6 @@ fn parse_types() {
parse_str("var t: texture_multisampled_2d<u32>;").unwrap();
parse_str("var t: [[access(write)]] texture_storage_1d<rgba8uint>;").unwrap();
parse_str("var t: [[access(read)]] texture_storage_3d<r32float>;").unwrap();
parse_str(
"
[[block]] struct Foo { [[offset(0)]] x: i32; };
var s: [[access(read_write)]] Foo;
",
)
.unwrap();
}
#[test]
@@ -46,6 +39,19 @@ fn parse_type_cast() {
.unwrap();
}
#[test]
fn parse_struct() {
parse_str(
"
[[block]] struct Foo { x: i32; };
struct Bar { [[span(16)]] x: vec2<i32>; };
struct Empty {};
var s: [[access(read_write)]] Foo;
",
)
.unwrap();
}
#[test]
fn parse_standard_fun() {
parse_str(

View File

@@ -201,19 +201,6 @@ pub enum ArraySize {
Dynamic,
}
/// Describes where a struct member is placed.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum MemberOrigin {
/// Member is local to the shader.
Empty,
/// Built-in shader variable.
BuiltIn(BuiltIn),
/// Offset within the struct.
Offset(u32),
}
/// The interpolation qualifier of a binding or struct field.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
@@ -245,7 +232,7 @@ pub enum Interpolation {
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct StructMember {
pub name: Option<String>,
pub origin: MemberOrigin,
pub span: Option<NonZeroU32>,
pub ty: Handle<Type>,
}

View File

@@ -39,24 +39,24 @@ fn main() {
# compute shader
[[block]]
struct Particle {
[[offset(0)]] pos : vec2<f32>;
[[offset(8)]] vel : vec2<f32>;
[[span(8)]] pos : vec2<f32>;
[[span(8)]] vel : vec2<f32>;
};
[[block]]
struct SimParams {
[[offset(0)]] deltaT : f32;
[[offset(4)]] rule1Distance : f32;
[[offset(8)]] rule2Distance : f32;
[[offset(12)]] rule3Distance : f32;
[[offset(16)]] rule1Scale : f32;
[[offset(20)]] rule2Scale : f32;
[[offset(24)]] rule3Scale : f32;
deltaT : f32;
rule1Distance : f32;
rule2Distance : f32;
rule3Distance : f32;
rule1Scale : f32;
rule2Scale : f32;
rule3Scale : f32;
};
[[block]]
struct Particles {
[[offset(0)]] particles : [[stride(16)]] array<Particle, 5>;
particles : [[stride(16)]] array<Particle, 5>;
};
[[group(0), binding(0)]] var<uniform> params : SimParams;

View File

@@ -5,8 +5,8 @@ var<out> out_position: vec4<f32>;
#[[block]]
struct Data {
[[offset(0)]] proj_inv: mat4x4<f32>;
[[offset(64)]] view: mat4x4<f32>;
proj_inv: mat4x4<f32>;
view: mat4x4<f32>;
};
[[group(0), binding(0)]]
var r_data: Data;