mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-in] lower swizzle store to per-component stores
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::{
|
||||
proc::ResolveContext, Arena, BinaryOperator, Binding, Block, Constant, Expression, FastHashMap,
|
||||
Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, Module,
|
||||
RelationalFunction, ResourceBinding, Sampling, ScalarKind, ShaderStage, Statement,
|
||||
StorageClass, Type, TypeInner, UnaryOperator,
|
||||
StorageClass, SwizzleComponent, Type, TypeInner, UnaryOperator, VectorSize,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -625,10 +625,56 @@ impl<'function> Context<'function> {
|
||||
self.implicit_conversion(program, &mut value, value_meta, kind)?;
|
||||
}
|
||||
|
||||
self.emit_flush(body);
|
||||
self.emit_start();
|
||||
if let Expression::Swizzle {
|
||||
size,
|
||||
vector,
|
||||
pattern,
|
||||
} = self.expressions[pointer]
|
||||
{
|
||||
// Stores to swizzled values are not directly supported,
|
||||
// lower them as series of per-component stores.
|
||||
let size = match size {
|
||||
VectorSize::Bi => 2,
|
||||
VectorSize::Tri => 3,
|
||||
VectorSize::Quad => 4,
|
||||
};
|
||||
|
||||
body.push(Statement::Store { pointer, value });
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for index in 0..size {
|
||||
let dst = self.add_expression(
|
||||
Expression::AccessIndex {
|
||||
base: vector,
|
||||
index: match pattern[index] {
|
||||
SwizzleComponent::X => 0,
|
||||
SwizzleComponent::Y => 1,
|
||||
SwizzleComponent::Z => 2,
|
||||
SwizzleComponent::W => 3,
|
||||
},
|
||||
},
|
||||
body,
|
||||
);
|
||||
let src = self.add_expression(
|
||||
Expression::AccessIndex {
|
||||
base: value,
|
||||
index: index as u32,
|
||||
},
|
||||
body,
|
||||
);
|
||||
|
||||
self.emit_flush(body);
|
||||
self.emit_start();
|
||||
|
||||
body.push(Statement::Store {
|
||||
pointer: dst,
|
||||
value: src,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
self.emit_flush(body);
|
||||
self.emit_start();
|
||||
|
||||
body.push(Statement::Store { pointer, value });
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
Binding, Block, BuiltIn, Constant, Expression, GlobalVariable, Handle, ImageClass,
|
||||
Interpolation, LocalVariable, ScalarKind, StorageAccess, StorageClass, Type, TypeInner,
|
||||
VectorSize,
|
||||
Interpolation, LocalVariable, ScalarKind, StorageAccess, StorageClass, SwizzleComponent, Type,
|
||||
TypeInner, VectorSize,
|
||||
};
|
||||
|
||||
use super::ast::*;
|
||||
@@ -146,67 +146,60 @@ impl Program<'_> {
|
||||
))
|
||||
}
|
||||
// swizzles (xyzw, rgba, stpq)
|
||||
TypeInner::Vector { size, kind, width } => {
|
||||
TypeInner::Vector { size, .. } => {
|
||||
let check_swizzle_components = |comps: &str| {
|
||||
name.chars()
|
||||
.map(|c| {
|
||||
comps
|
||||
.find(c)
|
||||
.and_then(|i| if i < size as usize { Some(i) } else { None })
|
||||
})
|
||||
.fold(Some(Vec::<usize>::new()), |acc, cur| {
|
||||
cur.and_then(|i| {
|
||||
acc.map(|mut v| {
|
||||
v.push(i);
|
||||
v
|
||||
})
|
||||
})
|
||||
})
|
||||
.map(|c| comps.find(c).filter(|i| *i < size as usize))
|
||||
.collect::<Option<Vec<usize>>>()
|
||||
};
|
||||
|
||||
let indices = check_swizzle_components("xyzw")
|
||||
.or_else(|| check_swizzle_components("rgba"))
|
||||
.or_else(|| check_swizzle_components("stpq"));
|
||||
|
||||
if let Some(v) = indices {
|
||||
let components: Vec<Handle<Expression>> = v
|
||||
.iter()
|
||||
.map(|idx| {
|
||||
ctx.add_expression(
|
||||
Expression::AccessIndex {
|
||||
base: expression,
|
||||
index: *idx as u32,
|
||||
},
|
||||
body,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
if let Some(components) = indices {
|
||||
if components.len() == 1 {
|
||||
// only single element swizzle, like pos.y, just return that component
|
||||
Ok(components[0])
|
||||
} else {
|
||||
let size = match components.len() {
|
||||
2 => VectorSize::Bi,
|
||||
3 => VectorSize::Tri,
|
||||
4 => VectorSize::Quad,
|
||||
_ => {
|
||||
return Err(ErrorKind::SemanticError(
|
||||
meta,
|
||||
format!("Bad swizzle size for \"{:?}\": {:?}", name, v).into(),
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok(ctx.add_expression(
|
||||
Expression::Compose {
|
||||
ty: self.module.types.fetch_or_append(Type {
|
||||
name: None,
|
||||
inner: TypeInner::Vector { kind, width, size },
|
||||
}),
|
||||
components,
|
||||
return Ok(ctx.add_expression(
|
||||
Expression::AccessIndex {
|
||||
base: expression,
|
||||
index: components[0] as u32,
|
||||
},
|
||||
body,
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
let size = match components.len() {
|
||||
2 => VectorSize::Bi,
|
||||
3 => VectorSize::Tri,
|
||||
4 => VectorSize::Quad,
|
||||
_ => {
|
||||
return Err(ErrorKind::SemanticError(
|
||||
meta,
|
||||
format!("Bad swizzle size for \"{:?}\": {:?}", name, components)
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let mut pattern = [SwizzleComponent::X; 4];
|
||||
for (pat, index) in pattern.iter_mut().zip(components) {
|
||||
*pat = match index {
|
||||
0 => SwizzleComponent::X,
|
||||
1 => SwizzleComponent::Y,
|
||||
2 => SwizzleComponent::Z,
|
||||
_ => SwizzleComponent::W,
|
||||
};
|
||||
}
|
||||
|
||||
Ok(ctx.add_expression(
|
||||
Expression::Swizzle {
|
||||
size,
|
||||
vector: expression,
|
||||
pattern,
|
||||
},
|
||||
body,
|
||||
))
|
||||
} else {
|
||||
Err(ErrorKind::SemanticError(
|
||||
meta,
|
||||
|
||||
@@ -322,6 +322,17 @@ impl<'a> ResolveContext<'a> {
|
||||
kind,
|
||||
width,
|
||||
} => TypeResolution::Value(Ti::Vector { size, kind, width }),
|
||||
Ti::Pointer { base, .. } => match types[base].inner {
|
||||
Ti::Vector {
|
||||
size: _,
|
||||
kind,
|
||||
width,
|
||||
} => TypeResolution::Value(Ti::Vector { size, kind, width }),
|
||||
ref other => {
|
||||
log::error!("Vector pointer type {:?}", other);
|
||||
return Err(ResolveError::InvalidVector(vector));
|
||||
}
|
||||
},
|
||||
ref other => {
|
||||
log::error!("Vector type {:?}", other);
|
||||
return Err(ResolveError::InvalidVector(vector));
|
||||
|
||||
@@ -233,6 +233,13 @@ impl super::Validator {
|
||||
} => {
|
||||
let vec_size = match *resolver.resolve(vector)? {
|
||||
Ti::Vector { size: vec_size, .. } => vec_size,
|
||||
Ti::Pointer { base, .. } => match module.types[base].inner {
|
||||
Ti::Vector { size: vec_size, .. } => vec_size,
|
||||
ref other => {
|
||||
log::error!("Swizzle vector pointer type {:?}", other);
|
||||
return Err(ExpressionError::InvalidVectorType(vector));
|
||||
}
|
||||
},
|
||||
ref other => {
|
||||
log::error!("Swizzle vector type {:?}", other);
|
||||
return Err(ExpressionError::InvalidVectorType(vector));
|
||||
|
||||
Reference in New Issue
Block a user