mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-04-28 19:17:25 +00:00
[hlsl-out] reorder fields when composing structs
This commit is contained in:
parent
27e4ba59e4
commit
69b70f8cc3
@ -32,7 +32,7 @@ struct EpStructMember {
|
|||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
enum InterfaceKey {
|
enum InterfaceKey {
|
||||||
Location(u32),
|
Location(u32),
|
||||||
BuiltIn(crate::BuiltIn),
|
BuiltIn(crate::BuiltIn),
|
||||||
@ -49,6 +49,19 @@ impl InterfaceKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true for structures that need their members permuted,
|
||||||
|
// so that first come the user-defined varyings
|
||||||
|
// in ascending locations, and then built-ins. This allows VS and FS
|
||||||
|
// interfaces to match with regards to order.
|
||||||
|
fn needs_permutation(members: &[crate::StructMember]) -> bool {
|
||||||
|
//Note: this is a bit of a hack. We need to re-order the output fields, but we can only do this
|
||||||
|
// for non-layouted structures. It may be possible for an WGSL program can use the same struct
|
||||||
|
// for both host sharing and the interface. This case isn't supported here.
|
||||||
|
let has_layout = members.iter().any(|m| m.offset != 0);
|
||||||
|
let has_binding = members.iter().any(|m| m.binding.is_some());
|
||||||
|
has_binding && !has_layout
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
enum Io {
|
enum Io {
|
||||||
Input,
|
Input,
|
||||||
@ -563,21 +576,13 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||||||
write!(self.out, "struct {}", self.names[&NameKey::Type(handle)])?;
|
write!(self.out, "struct {}", self.names[&NameKey::Type(handle)])?;
|
||||||
writeln!(self.out, " {{")?;
|
writeln!(self.out, " {{")?;
|
||||||
|
|
||||||
let has_layout = original_members.iter().any(|m| m.offset != 0);
|
|
||||||
let has_binding = original_members.iter().any(|m| m.binding.is_some());
|
|
||||||
//TODO: avoid heap allocation
|
//TODO: avoid heap allocation
|
||||||
let mut members = original_members
|
let mut members = original_members
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, m)| (index, m.ty, m.binding.clone()))
|
.map(|(index, m)| (index, m.ty, m.binding.clone()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
//Note: this is a bit of a hack. We need to re-order the output fields, but we can only do this
|
if needs_permutation(original_members) {
|
||||||
// for non-layouted structures. It may be possible for an WGSL program can use the same struct
|
|
||||||
// for both host sharing and the interface. This case isn't supported here.
|
|
||||||
if has_binding && !has_layout {
|
|
||||||
// Sort the members so that first come the user-defined varyings
|
|
||||||
// in ascending locations, and then built-ins. This allows VS and FS
|
|
||||||
// interfaces to match with regards to order.
|
|
||||||
members.sort_by_key(|&(_, _, ref binding)| InterfaceKey::new(binding.as_ref()));
|
members.sort_by_key(|&(_, _, ref binding)| InterfaceKey::new(binding.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1240,24 +1245,45 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||||||
match *expression {
|
match *expression {
|
||||||
Expression::Constant(constant) => self.write_constant(module, constant)?,
|
Expression::Constant(constant) => self.write_constant(module, constant)?,
|
||||||
Expression::Compose { ty, ref components } => {
|
Expression::Compose { ty, ref components } => {
|
||||||
let braces_init = match module.types[ty].inner {
|
let (braces_init, permutation) = match module.types[ty].inner {
|
||||||
TypeInner::Struct { .. } | TypeInner::Array { .. } => true,
|
TypeInner::Struct { ref members, .. } => {
|
||||||
_ => false,
|
let permutation = if needs_permutation(members) {
|
||||||
|
//TODO: avoid heap allocation. We can pre-compute this at the module leve.
|
||||||
|
let mut permutation = members
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, m)| (index, InterfaceKey::new(m.binding.as_ref())))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
permutation.sort_by_key(|&(_, ref key)| key.clone());
|
||||||
|
Some(permutation)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
(true, permutation)
|
||||||
|
}
|
||||||
|
TypeInner::Array { .. } => (true, None),
|
||||||
|
_ => (false, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
if braces_init {
|
if braces_init {
|
||||||
write!(self.out, "{{ ")?;
|
write!(self.out, "{{ ")?;
|
||||||
} else {
|
} else {
|
||||||
self.write_type(module, ty)?;
|
self.write_type(module, ty)?;
|
||||||
write!(self.out, "(")?;
|
write!(self.out, "(")?;
|
||||||
}
|
}
|
||||||
for (index, component) in components.iter().enumerate() {
|
|
||||||
self.write_expr(module, *component, func_ctx)?;
|
for index in 0..components.len() {
|
||||||
// Only write a comma if isn't the last element
|
if index != 0 {
|
||||||
if index != components.len().saturating_sub(1) {
|
|
||||||
// The leading space is for readability only
|
// The leading space is for readability only
|
||||||
write!(self.out, ", ")?;
|
write!(self.out, ", ")?;
|
||||||
}
|
}
|
||||||
|
let comp_index = match permutation {
|
||||||
|
Some(ref perm) => perm[index].0,
|
||||||
|
None => index,
|
||||||
|
};
|
||||||
|
self.write_expr(module, components[comp_index], func_ctx)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if braces_init {
|
if braces_init {
|
||||||
write!(self.out, " }}")?
|
write!(self.out, " }}")?
|
||||||
} else {
|
} else {
|
||||||
|
@ -43,6 +43,6 @@ type10 main(VertexInput_main vertexinput_main)
|
|||||||
float _expr12 = perVertexStruct.gl_PointSize;
|
float _expr12 = perVertexStruct.gl_PointSize;
|
||||||
float _expr13[1] = perVertexStruct.gl_ClipDistance;
|
float _expr13[1] = perVertexStruct.gl_ClipDistance;
|
||||||
float _expr14[1] = perVertexStruct.gl_CullDistance;
|
float _expr14[1] = perVertexStruct.gl_CullDistance;
|
||||||
const type10 type10_ = { _expr10, _expr11, _expr12, _expr13, _expr14 };
|
const type10 type10_ = { _expr10, _expr11, _expr13, _expr14, _expr12 };
|
||||||
return type10_;
|
return type10_;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user