Move invariant bit from Binding::Builtin to Builtin::Position. (#1822)

Use the type system to enforce the rule that the invariant attribute
may only appear on `Position` builtins.
This commit is contained in:
Jim Blandy
2022-04-13 14:57:05 -07:00
committed by GitHub
parent 78975f25da
commit 170faab6db
26 changed files with 107 additions and 168 deletions

View File

@@ -404,7 +404,7 @@ impl<'a, W> Writer<'a, W> {
_ => {
if let Some(binding) = binding {
match *binding {
Binding::BuiltIn { built_in, .. } => match built_in {
Binding::BuiltIn(built_in) => match built_in {
crate::BuiltIn::ClipDistance => {
self.features.request(Features::CLIP_DISTANCE)
}

View File

@@ -336,7 +336,7 @@ impl fmt::Display for VaryingName<'_> {
};
write!(f, "_{}_location{}", prefix, location,)
}
crate::Binding::BuiltIn { built_in, .. } => {
crate::Binding::BuiltIn(built_in) => {
write!(f, "{}", glsl_built_in(built_in, self.output))
}
}
@@ -1170,11 +1170,8 @@ impl<'a, W: Write> Writer<'a, W> {
interpolation,
sampling,
} => (location, interpolation, sampling),
crate::Binding::BuiltIn {
built_in,
invariant,
} => {
if invariant {
crate::Binding::BuiltIn(built_in) => {
if let crate::BuiltIn::Position { invariant: true } = built_in {
writeln!(self.out, "invariant {};", glsl_built_in(built_in, output))?;
}
return Ok(());
@@ -1830,10 +1827,8 @@ impl<'a, W: Write> Writer<'a, W> {
for (index, member) in members.iter().enumerate() {
// TODO: handle builtin in better way
if let Some(crate::Binding::BuiltIn {
built_in: builtin,
..
}) = member.binding
if let Some(crate::Binding::BuiltIn(builtin)) =
member.binding
{
match builtin {
crate::BuiltIn::ClipDistance
@@ -3170,7 +3165,7 @@ fn glsl_built_in(built_in: crate::BuiltIn, output: bool) -> &'static str {
use crate::BuiltIn as Bi;
match built_in {
Bi::Position => {
Bi::Position { .. } => {
if output {
"gl_Position"
} else {

View File

@@ -151,7 +151,7 @@ impl crate::StorageFormat {
impl crate::BuiltIn {
pub(super) fn to_hlsl_str(self) -> Result<&'static str, Error> {
Ok(match self {
Self::Position => "SV_Position",
Self::Position { .. } => "SV_Position",
// vertex
Self::ClipDistance => "SV_ClipDistance",
Self::CullDistance => "SV_CullDistance",

View File

@@ -60,7 +60,7 @@ impl InterfaceKey {
fn new(binding: Option<&crate::Binding>) -> Self {
match binding {
Some(&crate::Binding::Location { location, .. }) => Self::Location(location),
Some(&crate::Binding::BuiltIn { built_in, .. }) => Self::BuiltIn(built_in),
Some(&crate::Binding::BuiltIn(built_in)) => Self::BuiltIn(built_in),
None => Self::Other,
}
}
@@ -309,9 +309,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
fn write_modifier(&mut self, binding: &crate::Binding) -> BackendResult {
match *binding {
crate::Binding::BuiltIn {
invariant: true, ..
} => {
crate::Binding::BuiltIn(crate::BuiltIn::Position { invariant: true }) => {
write!(self.out, "precise ")?;
}
crate::Binding::Location {
@@ -345,9 +343,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
stage: Option<(ShaderStage, Io)>,
) -> BackendResult {
match *binding {
crate::Binding::BuiltIn {
built_in: builtin, ..
} => {
crate::Binding::BuiltIn(builtin) => {
let builtin_str = builtin.to_hlsl_str()?;
write!(self.out, " : {}", builtin_str)?;
}
@@ -963,9 +959,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
if let Some(crate::FunctionResult {
binding:
Some(
ref binding @ crate::Binding::BuiltIn {
invariant: true, ..
},
ref binding @ crate::Binding::BuiltIn(crate::BuiltIn::Position {
invariant: true,
}),
),
..
}) = func.result

View File

@@ -96,14 +96,14 @@ impl<'a> FunctionCtx<'_> {
match self.expressions[expression] {
crate::Expression::FunctionArgument(arg_index) => {
return match ep_function.arguments[arg_index as usize].binding {
Some(crate::Binding::BuiltIn { built_in: bi, .. }) => Some(bi),
Some(crate::Binding::BuiltIn(bi)) => Some(bi),
_ => built_in,
};
}
crate::Expression::AccessIndex { base, index } => {
match *self.info[base].ty.inner_with(&module.types) {
crate::TypeInner::Struct { ref members, .. } => {
if let Some(crate::Binding::BuiltIn { built_in: bi, .. }) =
if let Some(crate::Binding::BuiltIn(bi)) =
members[index as usize].binding
{
built_in = Some(bi);

View File

@@ -100,10 +100,7 @@ impl ops::Index<crate::ShaderStage> for PerStageMap {
}
enum ResolvedBinding {
BuiltIn {
built_in: crate::BuiltIn,
invariant: bool,
},
BuiltIn(crate::BuiltIn),
Attribute(u32),
Color(u32),
User {
@@ -241,20 +238,20 @@ impl Options {
mode: LocationMode,
) -> Result<ResolvedBinding, Error> {
match *binding {
crate::Binding::BuiltIn {
built_in,
invariant,
} => {
if invariant && self.lang_version < (2, 1) {
return Err(Error::UnsupportedAttribute("invariant".to_string()));
crate::Binding::BuiltIn(mut built_in) => {
if let crate::BuiltIn::Position { ref mut invariant } = built_in {
if *invariant && self.lang_version < (2, 1) {
return Err(Error::UnsupportedAttribute("invariant".to_string()));
}
// The 'invariant' attribute may only appear on vertex
// shader outputs, not fragment shader inputs.
if !matches!(mode, LocationMode::VertexOutput) {
*invariant = false;
}
}
// The 'invariant' attribute can only appear on vertex
// shader outputs, but not fragment shader inputs.
Ok(ResolvedBinding::BuiltIn {
built_in,
invariant: invariant && matches!(mode, LocationMode::VertexOutput),
})
Ok(ResolvedBinding::BuiltIn(built_in))
}
crate::Binding::Location {
location,
@@ -369,13 +366,11 @@ impl ResolvedBinding {
fn try_fmt<W: Write>(&self, out: &mut W) -> Result<(), Error> {
write!(out, " [[")?;
match *self {
Self::BuiltIn {
built_in,
invariant,
} => {
Self::BuiltIn(built_in) => {
use crate::BuiltIn as Bi;
let name = match built_in {
Bi::Position => "position",
Bi::Position { invariant: false } => "position",
Bi::Position { invariant: true } => "position, invariant",
// vertex
Bi::BaseInstance => "base_instance",
Bi::BaseVertex => "base_vertex",
@@ -401,10 +396,6 @@ impl ResolvedBinding {
}
};
write!(out, "{}", name)?;
if invariant {
write!(out, ", invariant")?;
}
}
Self::Attribute(index) => write!(out, "attribute({})", index)?,
Self::Color(index) => write!(out, "color({})", index)?,

View File

@@ -2136,19 +2136,13 @@ impl<W: Write> Writer<W> {
for (index, member) in members.iter().enumerate() {
match member.binding {
Some(crate::Binding::BuiltIn {
built_in: crate::BuiltIn::PointSize,
..
}) => {
Some(crate::Binding::BuiltIn(crate::BuiltIn::PointSize)) => {
has_point_size = true;
if !context.pipeline_options.allow_point_size {
continue;
}
}
Some(crate::Binding::BuiltIn {
built_in: crate::BuiltIn::CullDistance,
..
}) => {
Some(crate::Binding::BuiltIn(crate::BuiltIn::CullDistance)) => {
log::warn!("Ignoring CullDistance built-in");
continue;
}
@@ -3437,10 +3431,7 @@ impl<W: Write> Writer<W> {
match *binding {
// Point size is only supported in VS of pipelines with
// point primitive topology.
crate::Binding::BuiltIn {
built_in: crate::BuiltIn::PointSize,
..
} => {
crate::Binding::BuiltIn(crate::BuiltIn::PointSize) => {
has_point_size = true;
if !pipeline_options.allow_point_size {
continue;
@@ -3450,10 +3441,7 @@ impl<W: Write> Writer<W> {
// But we can't return UnsupportedBuiltIn error to user.
// Because otherwise we can't generate msl shader from any glslang SPIR-V shaders.
// glslang generates gl_PerVertex struct with gl_CullDistance builtin inside by default.
crate::Binding::BuiltIn {
built_in: crate::BuiltIn::CullDistance,
..
} => {
crate::Binding::BuiltIn(crate::BuiltIn::CullDistance) => {
log::warn!("Ignoring CullDistance BuiltIn");
continue;
}

View File

@@ -144,7 +144,7 @@ impl Writer {
body.push(Instruction::store(res_member.id, member_value_id, None));
match res_member.built_in {
Some(crate::BuiltIn::Position)
Some(crate::BuiltIn::Position { .. })
if self.flags.contains(WriterFlags::ADJUST_COORDINATE_SPACE) =>
{
self.write_epilogue_position_y_flip(res_member.id, body)?;

View File

@@ -38,7 +38,7 @@ pub(super) fn contains_builtin(
arena: &UniqueArena<crate::Type>,
built_in: crate::BuiltIn,
) -> bool {
if let Some(&crate::Binding::BuiltIn { built_in: bi, .. }) = binding {
if let Some(&crate::Binding::BuiltIn(bi)) = binding {
bi == built_in
} else if let crate::TypeInner::Struct { ref members, .. } = arena[ty].inner {
members

View File

@@ -398,11 +398,8 @@ impl Writer {
let mut has_point_size = false;
let class = spirv::StorageClass::Output;
if let Some(ref binding) = result.binding {
has_point_size |= *binding
== crate::Binding::BuiltIn {
built_in: crate::BuiltIn::PointSize,
invariant: false,
};
has_point_size |=
*binding == crate::Binding::BuiltIn(crate::BuiltIn::PointSize);
let type_id = self.get_type_id(LookupType::Handle(result.ty));
let varying_id =
self.write_varying(ir_module, class, None, result.ty, binding)?;
@@ -419,11 +416,8 @@ impl Writer {
let type_id = self.get_type_id(LookupType::Handle(member.ty));
let name = member.name.as_ref().map(AsRef::as_ref);
let binding = member.binding.as_ref().unwrap();
has_point_size |= *binding
== crate::Binding::BuiltIn {
built_in: crate::BuiltIn::PointSize,
invariant: false,
};
has_point_size |=
*binding == crate::Binding::BuiltIn(crate::BuiltIn::PointSize);
let varying_id =
self.write_varying(ir_module, class, name, member.ty, binding)?;
iface.varying_ids.push(varying_id);
@@ -1180,13 +1174,14 @@ impl Writer {
}
}
}
crate::Binding::BuiltIn {
built_in,
invariant,
} => {
crate::Binding::BuiltIn(built_in) => {
use crate::BuiltIn as Bi;
let built_in = match built_in {
Bi::Position => {
Bi::Position { invariant } => {
if invariant {
self.decorate(id, Decoration::Invariant, &[]);
}
if class == spirv::StorageClass::Output {
BuiltIn::Position
} else {
@@ -1234,10 +1229,6 @@ impl Writer {
};
self.decorate(id, Decoration::BuiltIn, &[built_in as u32]);
if invariant {
self.decorate(id, Decoration::Invariant, &[]);
}
}
}
@@ -1365,13 +1356,7 @@ impl Writer {
crate::TypeInner::Struct { ref members, .. } => members.iter().any(|member| {
has_view_index_check(ir_module, member.binding.as_ref(), member.ty)
}),
_ => {
binding
== Some(&crate::Binding::BuiltIn {
built_in: crate::BuiltIn::ViewIndex,
invariant: false,
})
}
_ => binding == Some(&crate::Binding::BuiltIn(crate::BuiltIn::ViewIndex)),
}
}

View File

@@ -402,7 +402,7 @@ impl<W: Write> Writer<W> {
writeln!(self.out)?;
for (index, member) in members.iter().enumerate() {
// Skip struct member with unsupported built in
if let Some(crate::Binding::BuiltIn { built_in, .. }) = member.binding {
if let Some(crate::Binding::BuiltIn(built_in)) = member.binding {
if builtin_str(built_in).is_none() {
log::warn!("Skip member with unsupported builtin {:?}", built_in);
continue;
@@ -1747,7 +1747,7 @@ impl<W: Write> Writer<W> {
// Write the comma separated constants
for (index, constant) in components.iter().enumerate() {
if let Some(&crate::Binding::BuiltIn { built_in, .. }) =
if let Some(&crate::Binding::BuiltIn(built_in)) =
members.and_then(|members| members.get(index)?.binding.as_ref())
{
if builtin_str(built_in).is_none() {
@@ -1849,7 +1849,7 @@ fn builtin_str(built_in: crate::BuiltIn) -> Option<&'static str> {
match built_in {
Bi::VertexIndex => Some("vertex_index"),
Bi::InstanceIndex => Some("instance_index"),
Bi::Position => Some("position"),
Bi::Position { .. } => Some("position"),
Bi::FrontFacing => Some("front_facing"),
Bi::FragDepth => Some("frag_depth"),
Bi::LocalInvocationId => Some("local_invocation_id"),
@@ -1977,11 +1977,8 @@ fn map_binding_to_attribute(
scalar_kind: Option<crate::ScalarKind>,
) -> Vec<Attribute> {
match *binding {
crate::Binding::BuiltIn {
built_in,
invariant,
} => {
if invariant {
crate::Binding::BuiltIn(built_in) => {
if let crate::BuiltIn::Position { invariant: true } = built_in {
vec![Attribute::BuiltIn(built_in), Attribute::Invariant]
} else {
vec![Attribute::BuiltIn(built_in)]
@@ -2017,8 +2014,7 @@ fn access_to_unsupported_builtin(
{
// Let's check that we try to access a struct member with unsupported built-in and skip it.
if let TypeInner::Struct { ref members, .. } = module.types[pointer_base_handle].inner {
if let Some(crate::Binding::BuiltIn { built_in, .. }) = members[index as usize].binding
{
if let Some(crate::Binding::BuiltIn(built_in)) = members[index as usize].binding {
if builtin_str(built_in).is_none() {
log::warn!("Skip component with unsupported builtin {:?}", built_in);
return true;

View File

@@ -67,10 +67,7 @@ impl Parser {
let idx = self.entry_args.len();
self.entry_args.push(EntryArg {
name: None,
binding: Binding::BuiltIn {
built_in: data.builtin,
invariant: false,
},
binding: Binding::BuiltIn(data.builtin),
handle,
storage: data.storage,
});
@@ -120,7 +117,7 @@ impl Parser {
kind: ScalarKind::Float,
width: 4,
},
builtin: BuiltIn::Position,
builtin: BuiltIn::Position { invariant: false },
mutable: true,
storage: StorageQualifier::Output,
},
@@ -130,7 +127,7 @@ impl Parser {
kind: ScalarKind::Float,
width: 4,
},
builtin: BuiltIn::Position,
builtin: BuiltIn::Position { invariant: false },
mutable: false,
storage: StorageQualifier::Input,
},
@@ -240,11 +237,10 @@ impl Parser {
) {
if let Some(var) = self.lookup_variable(ctx, body, name, meta) {
if let Some(index) = var.entry_arg {
if let Binding::BuiltIn { built_in, .. } = self.entry_args[index].binding {
self.entry_args[index].binding = Binding::BuiltIn {
built_in,
invariant: built_in == BuiltIn::Position,
};
if let Binding::BuiltIn(BuiltIn::Position { ref mut invariant }) =
self.entry_args[index].binding
{
*invariant = true;
}
}
}

View File

@@ -121,10 +121,10 @@ pub(super) fn map_width(word: spirv::Word) -> Result<crate::Bytes, Error> {
.map_err(|_| Error::InvalidTypeWidth(word))
}
pub(super) fn map_builtin(word: spirv::Word) -> Result<crate::BuiltIn, Error> {
pub(super) fn map_builtin(word: spirv::Word, invariant: bool) -> Result<crate::BuiltIn, Error> {
use spirv::BuiltIn as Bi;
Ok(match spirv::BuiltIn::from_u32(word) {
Some(Bi::Position) | Some(Bi::FragCoord) => crate::BuiltIn::Position,
Some(Bi::Position) | Some(Bi::FragCoord) => crate::BuiltIn::Position { invariant },
Some(Bi::ViewIndex) => crate::BuiltIn::ViewIndex,
// vertex
Some(Bi::BaseInstance) => crate::BuiltIn::BaseInstance,

View File

@@ -377,7 +377,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
} => {
for (index, sm) in sub_members.iter().enumerate() {
match sm.binding {
Some(crate::Binding::BuiltIn { built_in, .. }) => {
Some(crate::Binding::BuiltIn(built_in)) => {
// Cull unused builtins to preserve performances
if !self.builtin_usage.contains(&built_in) {
continue;
@@ -414,10 +414,9 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
for (member_index, member) in members.iter().enumerate() {
match member.binding {
Some(crate::Binding::BuiltIn {
built_in: crate::BuiltIn::Position,
..
}) if self.options.adjust_coordinate_space => {
Some(crate::Binding::BuiltIn(crate::BuiltIn::Position { .. }))
if self.options.adjust_coordinate_space =>
{
let mut emitter = Emitter::default();
emitter.start(&function.expressions);
let global_expr = components[member_index];

View File

@@ -235,10 +235,7 @@ impl Decoration {
location: None,
invariant,
..
} => map_builtin(built_in).map(|built_in| crate::Binding::BuiltIn {
built_in,
invariant: invariant && built_in == crate::BuiltIn::Position,
}),
} => Ok(crate::Binding::BuiltIn(map_builtin(built_in, invariant)?)),
Decoration {
built_in: None,
location: Some(location),
@@ -1475,7 +1472,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
span,
);
if let Some(crate::Binding::BuiltIn { built_in, .. }) =
if let Some(crate::Binding::BuiltIn(built_in)) =
members[index as usize].binding
{
self.builtin_usage.insert(built_in);
@@ -4646,7 +4643,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
ExtendedClass::Input => {
let mut binding = dec.io_binding()?;
let mut unsigned_ty = effective_ty;
if let crate::Binding::BuiltIn { built_in, .. } = binding {
if let crate::Binding::BuiltIn(built_in) = binding {
let needs_inner_uint = match built_in {
crate::BuiltIn::BaseInstance
| crate::BuiltIn::BaseVertex
@@ -4699,7 +4696,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
// For output interface blocks, this would be a structure.
let mut binding = dec.io_binding().ok();
let init = match binding {
Some(crate::Binding::BuiltIn { built_in, .. }) => {
Some(crate::Binding::BuiltIn(built_in)) => {
match null::generate_default_built_in(
Some(built_in),
effective_ty,
@@ -4722,9 +4719,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
.iter()
.map(|member| {
let built_in = match member.binding {
Some(crate::Binding::BuiltIn { built_in, .. }) => {
Some(built_in)
}
Some(crate::Binding::BuiltIn(built_in)) => Some(built_in),
_ => None,
};
(built_in, member.ty)

View File

@@ -121,7 +121,7 @@ pub fn generate_default_built_in(
span: crate::Span,
) -> Result<Handle<crate::Constant>, Error> {
let inner = match built_in {
Some(crate::BuiltIn::Position) => {
Some(crate::BuiltIn::Position { .. }) => {
let zero = constant_arena.fetch_or_append(
crate::Constant {
name: None,

View File

@@ -16,7 +16,7 @@ pub fn map_address_space(word: &str, span: Span) -> Result<crate::AddressSpace,
pub fn map_built_in(word: &str, span: Span) -> Result<crate::BuiltIn, Error<'_>> {
Ok(match word {
"position" => crate::BuiltIn::Position,
"position" => crate::BuiltIn::Position { invariant: false },
// vertex
"vertex_index" => crate::BuiltIn::VertexIndex,
"instance_index" => crate::BuiltIn::InstanceIndex,

View File

@@ -1254,16 +1254,14 @@ impl BindingParser {
sampling,
}))
}
(None, Some(crate::BuiltIn::Position), None, None, true) => {
Ok(Some(crate::Binding::BuiltIn {
built_in: crate::BuiltIn::Position,
invariant: true,
}))
(None, Some(crate::BuiltIn::Position { .. }), None, None, invariant) => {
Ok(Some(crate::Binding::BuiltIn(crate::BuiltIn::Position {
invariant,
})))
}
(None, Some(built_in), None, None, false) => {
Ok(Some(crate::Binding::BuiltIn(built_in)))
}
(None, Some(built_in), None, None, false) => Ok(Some(crate::Binding::BuiltIn {
built_in,
invariant: false,
})),
(_, _, _, _, _) => Err(Error::InconsistentBinding(span)),
}
}

View File

@@ -325,7 +325,7 @@ pub enum AddressSpace {
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum BuiltIn {
Position,
Position { invariant: bool },
ViewIndex,
// vertex
BaseInstance,
@@ -748,11 +748,7 @@ pub enum ConstantInner {
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum Binding {
/// Built-in shader variable.
BuiltIn {
built_in: BuiltIn,
/// can only be `true` for [`BuiltIn::Position`]
invariant: bool,
},
BuiltIn(BuiltIn),
/// Indexed location.
///

View File

@@ -390,7 +390,7 @@ impl crate::Constant {
impl crate::Binding {
pub fn to_built_in(&self) -> Option<crate::BuiltIn> {
match *self {
crate::Binding::BuiltIn { built_in, .. } => Some(built_in),
crate::Binding::BuiltIn(built_in) => Some(built_in),
Self::Location { .. } => None,
}
}

View File

@@ -455,7 +455,7 @@ impl FunctionInfo {
E::FunctionArgument(index) => {
let arg = &resolve_context.arguments[index as usize];
let uniform = match arg.binding {
Some(crate::Binding::BuiltIn { built_in, .. }) => match built_in {
Some(crate::Binding::BuiltIn(built_in)) => match built_in {
// per-polygon built-ins are uniform
crate::BuiltIn::FrontFacing
// per-work-group built-ins are uniform

View File

@@ -103,7 +103,7 @@ struct VaryingContext<'a> {
output: bool,
types: &'a UniqueArena<crate::Type>,
location_mask: &'a mut BitSet,
built_in_mask: u32,
built_ins: &'a mut crate::FastHashSet<crate::BuiltIn>,
capabilities: Capabilities,
}
@@ -115,12 +115,19 @@ impl VaryingContext<'_> {
let ty_inner = &self.types[self.ty].inner;
match *binding {
crate::Binding::BuiltIn { built_in, .. } => {
let bit = 1 << built_in as u32;
if self.built_in_mask & bit != 0 {
crate::Binding::BuiltIn(built_in) => {
// Ignore the `invariant` field for the sake of duplicate checks,
// but use the original in error messages.
let canonical = if let crate::BuiltIn::Position { .. } = built_in {
crate::BuiltIn::Position { invariant: false }
} else {
built_in
};
if self.built_ins.contains(&canonical) {
return Err(VaryingError::DuplicateBuiltIn(built_in));
}
self.built_in_mask |= bit;
self.built_ins.insert(canonical);
let width = 4;
let (visible, type_good) = match built_in {
@@ -153,7 +160,7 @@ impl VaryingContext<'_> {
width,
},
),
Bi::Position => (
Bi::Position { .. } => (
match self.stage {
St::Vertex => self.output,
St::Fragment => !self.output,
@@ -457,7 +464,7 @@ impl super::Validator {
}
self.location_mask.clear();
let mut argument_built_ins = 0;
let mut argument_built_ins = crate::FastHashSet::default();
// TODO: add span info to function arguments
for (index, fa) in ep.function.arguments.iter().enumerate() {
let mut ctx = VaryingContext {
@@ -466,23 +473,23 @@ impl super::Validator {
output: false,
types: &module.types,
location_mask: &mut self.location_mask,
built_in_mask: argument_built_ins,
built_ins: &mut argument_built_ins,
capabilities: self.capabilities,
};
ctx.validate(fa.binding.as_ref())
.map_err_inner(|e| EntryPointError::Argument(index as u32, e).with_span())?;
argument_built_ins = ctx.built_in_mask;
}
self.location_mask.clear();
if let Some(ref fr) = ep.function.result {
let mut result_built_ins = crate::FastHashSet::default();
let mut ctx = VaryingContext {
ty: fr.ty,
stage: ep.stage,
output: true,
types: &module.types,
location_mask: &mut self.location_mask,
built_in_mask: 0,
built_ins: &mut result_built_ins,
capabilities: self.capabilities,
};
ctx.validate(fr.binding.as_ref())

View File

@@ -284,10 +284,7 @@
(
name: Some("global_id"),
ty: 4,
binding: Some(BuiltIn(
built_in: GlobalInvocationId,
invariant: false,
)),
binding: Some(BuiltIn(GlobalInvocationId)),
),
],
result: None,

View File

@@ -17,8 +17,8 @@ OpMemberDecorate %14 2 Offset 8
OpDecorate %16 ArrayStride 4
OpMemberDecorate %18 0 Offset 0
OpMemberDecorate %19 0 Offset 0
OpDecorate %22 BuiltIn FragCoord
OpDecorate %22 Invariant
OpDecorate %22 BuiltIn FragCoord
OpDecorate %25 Location 1
OpDecorate %28 BuiltIn FrontFacing
OpDecorate %31 BuiltIn SampleId

View File

@@ -18,8 +18,8 @@ OpDecorate %21 BuiltIn VertexIndex
OpDecorate %24 BuiltIn InstanceIndex
OpDecorate %26 Location 10
OpDecorate %26 Flat
OpDecorate %28 BuiltIn Position
OpDecorate %28 Invariant
OpDecorate %28 BuiltIn Position
OpDecorate %30 Location 1
OpDecorate %32 BuiltIn PointSize
%2 = OpTypeVoid

View File

@@ -16,8 +16,8 @@ OpMemberDecorate %18 0 Offset 0
OpMemberDecorate %19 0 Offset 0
OpDecorate %24 BuiltIn VertexIndex
OpDecorate %28 BuiltIn InstanceIndex
OpDecorate %30 BuiltIn Position
OpDecorate %30 Invariant
OpDecorate %30 BuiltIn Position
OpDecorate %32 BuiltIn PointSize
%2 = OpTypeVoid
%4 = OpTypeFloat 32