Skip to content

Commit

Permalink
Swizzle expression (gfx-rs#734)
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark authored Apr 21, 2021
1 parent b08dfe5 commit 5d1746b
Show file tree
Hide file tree
Showing 28 changed files with 545 additions and 366 deletions.
11 changes: 11 additions & 0 deletions src/back/dot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,17 @@ fn write_fun(
edges.insert("value", value);
(Cow::Owned(format!("Splat{:?}", size)), 3)
}
E::Swizzle {
size,
vector,
pattern,
} => {
edges.insert("vector", vector);
(
Cow::Owned(format!("Swizzle{:?}", &pattern[..size as usize])),
3,
)
}
E::Compose { ref components, .. } => {
payload = Some(Payload::Arguments(components));
(Cow::Borrowed("Compose"), 3)
Expand Down
3 changes: 2 additions & 1 deletion src/back/glsl/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ impl<'a, W> Writer<'a, W> {
interpolation,
sampling,
..
}) = binding {
}) = binding
{
if interpolation == Some(Interpolation::Linear) {
self.features.request(Features::NOPERSPECTIVE_QUALIFIER);
}
Expand Down
35 changes: 26 additions & 9 deletions src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ use crate::{
ImageClass, Interpolation, LocalVariable, Module, RelationalFunction, Sampling, ScalarKind,
ScalarValue, ShaderStage, Statement, StorageAccess, StorageClass, StorageFormat, StructMember,
Type, TypeInner, UnaryOperator,

};
use features::FeaturesManager;
use std::{
Expand All @@ -72,6 +71,8 @@ pub const SUPPORTED_CORE_VERSIONS: &[u16] = &[330, 400, 410, 420, 430, 440, 450]
pub const SUPPORTED_ES_VERSIONS: &[u16] = &[300, 310, 320];
const INDENT: &str = " ";

const COMPONENTS: &[char] = &['x', 'y', 'z', 'w'];

/// glsl version
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Version {
Expand Down Expand Up @@ -797,7 +798,11 @@ impl<'a, W: Write> Writer<'a, W> {
}
_ => {
let (location, interpolation, sampling) = match binding {
Some(&Binding::Location { location, interpolation, sampling }) => (location, interpolation, sampling),
Some(&Binding::Location {
location,
interpolation,
sampling,
}) => (location, interpolation, sampling),
_ => return Ok(()),
};

Expand All @@ -818,10 +823,7 @@ impl<'a, W: Write> Writer<'a, W> {

// Write the storage class
if self.options.version.supports_explicit_locations() {
write!(
self.out,
"layout(location = {}) ",
location)?;
write!(self.out, "layout(location = {}) ", location)?;
}

// Write the sampling auxiliary qualifier.
Expand All @@ -847,7 +849,11 @@ impl<'a, W: Write> Writer<'a, W> {
// Finally write the global name and end the global with a `;` and a newline
// Leading space is important
let vname = VaryingName {
binding: &Binding::Location { location, interpolation: None, sampling: None },
binding: &Binding::Location {
location,
interpolation: None,
sampling: None,
},
stage: self.entry_point.stage,
output,
};
Expand Down Expand Up @@ -1507,6 +1513,18 @@ impl<'a, W: Write> Writer<'a, W> {
self.write_expr(value, ctx)?;
write!(self.out, ")")?
}
// `Swizzle` adds a few letters behind the dot.
Expression::Swizzle {
size,
vector,
pattern,
} => {
self.write_expr(vector, ctx)?;
write!(self.out, ".")?;
for &sc in pattern[..size as usize].iter() {
write!(self.out, "{}", COMPONENTS[sc as usize])?;
}
}
// `Compose` is pretty simple we just write `type(components)` where `components` is a
// comma separated list of expressions
Expression::Compose { ty, ref components } => {
Expand Down Expand Up @@ -1728,14 +1746,13 @@ impl<'a, W: Write> Writer<'a, W> {
write!(self.out, ")",)?;
}
crate::ImageQuery::NumLayers => {
let selector = ['x', 'y', 'z', 'w'];
let fun_name = match class {
ImageClass::Sampled { .. } | ImageClass::Depth => "textureSize",
ImageClass::Storage(_) => "imageSize",
};
write!(self.out, "{}(", fun_name)?;
self.write_expr(image, ctx)?;
write!(self.out, ",0).{}", selector[components])?;
write!(self.out, ",0).{}", COMPONENTS[components])?;
}
crate::ImageQuery::NumSamples => {
// assumes ARB_shader_texture_image_samples
Expand Down
23 changes: 12 additions & 11 deletions src/back/msl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,11 @@ impl Options {
) -> Result<ResolvedBinding, Error> {
match *binding {
crate::Binding::BuiltIn(built_in) => Ok(ResolvedBinding::BuiltIn(built_in)),
crate::Binding::Location { location, interpolation, sampling } => match mode {
crate::Binding::Location {
location,
interpolation,
sampling,
} => match mode {
LocationMode::VertexInput => Ok(ResolvedBinding::Attribute(location)),
LocationMode::FragmentOutput => Ok(ResolvedBinding::Color(location)),
LocationMode::Intermediate => Ok(ResolvedBinding::User {
Expand Down Expand Up @@ -351,21 +355,18 @@ impl ResolvedBinding {
}

impl ResolvedInterpolation {
fn from_binding(interpolation: crate::Interpolation,
sampling: crate::Sampling)
-> Self
{
fn from_binding(interpolation: crate::Interpolation, sampling: crate::Sampling) -> Self {
use crate::Interpolation as I;
use crate::Sampling as S;

match (interpolation, sampling) {
(I::Perspective, S::Center) => Self::CenterPerspective,
(I::Perspective, S::Center) => Self::CenterPerspective,
(I::Perspective, S::Centroid) => Self::CentroidPerspective,
(I::Perspective, S::Sample) => Self::SamplePerspective,
(I::Linear, S::Center) => Self::CenterNoPerspective,
(I::Linear, S::Centroid) => Self::CentroidNoPerspective,
(I::Linear, S::Sample) => Self::SampleNoPerspective,
(I::Flat, _) => Self::Flat,
(I::Perspective, S::Sample) => Self::SamplePerspective,
(I::Linear, S::Center) => Self::CenterNoPerspective,
(I::Linear, S::Centroid) => Self::CentroidNoPerspective,
(I::Linear, S::Sample) => Self::SampleNoPerspective,
(I::Flat, _) => Self::Flat,
}
}

Expand Down
17 changes: 14 additions & 3 deletions src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ impl<W: Write> Writer<W> {
crate::Expression::Splat { size, value } => {
let scalar_kind = match *context.resolve_type(value) {
crate::TypeInner::Scalar { kind, .. } => kind,
_ => return Err(Error::Validation)
_ => return Err(Error::Validation),
};
let scalar = scalar_kind_string(scalar_kind);
let size = vector_size_string(size);
Expand All @@ -620,6 +620,17 @@ impl<W: Write> Writer<W> {
self.put_expression(value, context, true)?;
write!(self.out, ")")?;
}
crate::Expression::Swizzle {
size,
vector,
pattern,
} => {
self.put_expression(vector, context, is_scoped)?;
write!(self.out, ".")?;
for &sc in pattern[..size as usize].iter() {
write!(self.out, "{}", COMPONENTS[sc as usize])?;
}
}
crate::Expression::Compose { ty, ref components } => {
let inner = &context.module.types[ty].inner;
match *inner {
Expand Down Expand Up @@ -2168,8 +2179,8 @@ fn test_stack_size() {
}
let stack_size = addresses.end - addresses.start;
// check the size (in debug only)
// last observed macOS value: 20336
if stack_size < 19000 || stack_size > 21000 {
// last observed macOS value: 21584
if stack_size < 20000 || stack_size > 22000 {
panic!("`put_expression` stack size {} has changed!", stack_size);
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/back/spv/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,26 @@ impl super::Instruction {
instruction
}

pub(super) fn vector_shuffle(
result_type_id: Word,
id: Word,
v1_id: Word,
v2_id: Word,
components: &[Word],
) -> Self {
let mut instruction = Self::new(Op::VectorShuffle);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(v1_id);
instruction.add_operand(v2_id);

for &component in components {
instruction.add_operand(component);
}

instruction
}

//
// Arithmetic Instructions
//
Expand Down
29 changes: 27 additions & 2 deletions src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,8 @@ impl Writer {
}

fn decorate(&mut self, id: Word, decoration: spirv::Decoration, operands: &[Word]) {
self.annotations.push(Instruction::decorate(id, decoration, operands));
self.annotations
.push(Instruction::decorate(id, decoration, operands));
}

fn write_function(
Expand Down Expand Up @@ -1090,7 +1091,11 @@ impl Writer {
use spirv::{BuiltIn, Decoration};

match *binding {
crate::Binding::Location { location, interpolation, sampling } => {
crate::Binding::Location {
location,
interpolation,
sampling,
} => {
self.decorate(id, Decoration::Location, &[location]);

match interpolation {
Expand Down Expand Up @@ -1459,6 +1464,26 @@ impl Writer {
));
id
}
crate::Expression::Swizzle {
size,
vector,
pattern,
} => {
let vector_id = self.cached[vector];
self.temp_list.clear();
for &sc in pattern[..size as usize].iter() {
self.temp_list.push(sc as Word);
}
let id = self.id_gen.next();
block.body.push(Instruction::vector_shuffle(
result_type_id,
id,
vector_id,
vector_id,
&self.temp_list,
));
id
}
crate::Expression::Compose {
ty: _,
ref components,
Expand Down
47 changes: 44 additions & 3 deletions src/front/glsl/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub enum ConstantSolvingError {
InvalidUnaryOpArg,
#[error("Cannot apply the binary op to the arguments")]
InvalidBinaryOpArgs,
#[error("Splat type is not registered")]
SplatType,
#[error("Splat/swizzle type is not registered")]
DestinationTypeNotFound,
}

impl<'a> ConstantSolver<'a> {
Expand Down Expand Up @@ -83,11 +83,52 @@ impl<'a> ConstantSolver<'a> {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: ty.ok_or(ConstantSolvingError::SplatType)?,
//TODO: register the new type if needed
ty: ty.ok_or(ConstantSolvingError::DestinationTypeNotFound)?,
components: vec![tgt; size as usize],
},
}))
}
Expression::Swizzle {
size,
vector: src_vector,
pattern,
} => {
let tgt = self.solve(src_vector)?;
let (ty, src_components) = match self.constants[tgt].inner {
ConstantInner::Scalar { .. } => (None, &[][..]),
ConstantInner::Composite {
ty,
components: ref src_components,
} => match self.types[ty].inner {
crate::TypeInner::Vector {
size: _,
kind,
width,
} => {
let dst_ty = self.types.fetch_if(|t| {
t.inner == crate::TypeInner::Vector { size, kind, width }
});
(dst_ty, &src_components[..])
}
_ => (None, &[][..]),
},
};
let components = pattern
.iter()
.map(|&sc| src_components[sc as usize])
.collect();

Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
//TODO: register the new type if needed
ty: ty.ok_or(ConstantSolvingError::DestinationTypeNotFound)?,
components,
},
}))
}
Expression::Compose { ty, ref components } => {
let components = components
.iter()
Expand Down
3 changes: 2 additions & 1 deletion src/front/spv/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
if let Some(crate::Binding::Location {
interpolation: ref mut interpolation @ None,
..
}) = arg.binding {
}) = arg.binding
{
*interpolation = Some(crate::Interpolation::Perspective);
// default
}
Expand Down
Loading

0 comments on commit 5d1746b

Please sign in to comment.