mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
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:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)?,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -284,10 +284,7 @@
|
||||
(
|
||||
name: Some("global_id"),
|
||||
ty: 4,
|
||||
binding: Some(BuiltIn(
|
||||
built_in: GlobalInvocationId,
|
||||
invariant: false,
|
||||
)),
|
||||
binding: Some(BuiltIn(GlobalInvocationId)),
|
||||
),
|
||||
],
|
||||
result: None,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user