mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-23 15:23:33 +00:00
Swizzle expression (#734)
This commit is contained in:
parent
b08dfe5146
commit
5d1746b0b4
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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::{
|
||||
@ -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 {
|
||||
@ -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(()),
|
||||
};
|
||||
|
||||
@ -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.
|
||||
@ -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,
|
||||
};
|
||||
@ -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 } => {
|
||||
@ -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
|
||||
|
@ -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 {
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
@ -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 {
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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(
|
||||
@ -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 {
|
||||
@ -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,
|
||||
|
@ -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> {
|
||||
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -256,7 +256,11 @@ impl Decoration {
|
||||
interpolation,
|
||||
sampling,
|
||||
..
|
||||
} => Ok(crate::Binding::Location { location, interpolation, sampling }),
|
||||
} => Ok(crate::Binding::Location {
|
||||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
}),
|
||||
_ => Err(Error::MissingDecoration(spirv::Decoration::Location)),
|
||||
}
|
||||
}
|
||||
@ -1438,41 +1442,78 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
|
||||
let v1_lexp = self.lookup_expression.lookup(v1_id)?;
|
||||
let v1_lty = self.lookup_type.lookup(v1_lexp.type_id)?;
|
||||
let v1_handle = v1_lexp.handle;
|
||||
let n1 = match type_arena[v1_lty.handle].inner {
|
||||
crate::TypeInner::Vector { size, .. } => size as u8,
|
||||
crate::TypeInner::Vector { size, .. } => size as u32,
|
||||
_ => return Err(Error::InvalidInnerType(v1_lexp.type_id)),
|
||||
};
|
||||
let v1_handle = v1_lexp.handle;
|
||||
let v2_lexp = self.lookup_expression.lookup(v2_id)?;
|
||||
let v2_lty = self.lookup_type.lookup(v2_lexp.type_id)?;
|
||||
let v2_handle = v2_lexp.handle;
|
||||
let n2 = match type_arena[v2_lty.handle].inner {
|
||||
crate::TypeInner::Vector { size, .. } => size as u8,
|
||||
crate::TypeInner::Vector { size, .. } => size as u32,
|
||||
_ => return Err(Error::InvalidInnerType(v2_lexp.type_id)),
|
||||
};
|
||||
let v2_handle = v2_lexp.handle;
|
||||
|
||||
let mut components = Vec::with_capacity(inst.wc as usize - 5);
|
||||
for _ in 0..components.capacity() {
|
||||
let index = self.next()?;
|
||||
let expr = if index < n1 as u32 {
|
||||
crate::Expression::AccessIndex {
|
||||
base: v1_handle,
|
||||
index,
|
||||
}
|
||||
} else if index < n1 as u32 + n2 as u32 {
|
||||
crate::Expression::AccessIndex {
|
||||
base: v2_handle,
|
||||
index: index - n1 as u32,
|
||||
}
|
||||
} else {
|
||||
return Err(Error::InvalidAccessIndex(index));
|
||||
};
|
||||
components.push(expressions.append(expr));
|
||||
self.temp_bytes.clear();
|
||||
let mut max_component = 0;
|
||||
for _ in 5..inst.wc as usize {
|
||||
let mut index = self.next()?;
|
||||
if index == !0 {
|
||||
// treat Undefined as X
|
||||
index = 0;
|
||||
}
|
||||
max_component = max_component.max(index);
|
||||
self.temp_bytes.push(index as u8);
|
||||
}
|
||||
let expr = crate::Expression::Compose {
|
||||
ty: self.lookup_type.lookup(result_type_id)?.handle,
|
||||
components,
|
||||
|
||||
// Check for swizzle first.
|
||||
let expr = if max_component < n1 {
|
||||
use crate::SwizzleComponent as Sc;
|
||||
let size = match self.temp_bytes.len() {
|
||||
2 => crate::VectorSize::Bi,
|
||||
3 => crate::VectorSize::Tri,
|
||||
_ => crate::VectorSize::Quad,
|
||||
};
|
||||
let mut pattern = [Sc::X; 4];
|
||||
for (pat, index) in pattern.iter_mut().zip(self.temp_bytes.drain(..)) {
|
||||
*pat = match index {
|
||||
0 => Sc::X,
|
||||
1 => Sc::Y,
|
||||
2 => Sc::Z,
|
||||
_ => Sc::W,
|
||||
};
|
||||
}
|
||||
crate::Expression::Swizzle {
|
||||
size,
|
||||
vector: v1_handle,
|
||||
pattern,
|
||||
}
|
||||
} else {
|
||||
// Fall back to access + compose
|
||||
let mut components = Vec::with_capacity(self.temp_bytes.len());
|
||||
for index in self.temp_bytes.drain(..).map(|i| i as u32) {
|
||||
let expr = if index < n1 {
|
||||
crate::Expression::AccessIndex {
|
||||
base: v1_handle,
|
||||
index,
|
||||
}
|
||||
} else if index < n1 + n2 {
|
||||
crate::Expression::AccessIndex {
|
||||
base: v2_handle,
|
||||
index: index - n1,
|
||||
}
|
||||
} else {
|
||||
return Err(Error::InvalidAccessIndex(index));
|
||||
};
|
||||
components.push(expressions.append(expr));
|
||||
}
|
||||
crate::Expression::Compose {
|
||||
ty: self.lookup_type.lookup(result_type_id)?.handle,
|
||||
components,
|
||||
}
|
||||
};
|
||||
|
||||
self.lookup_expression.insert(
|
||||
result_id,
|
||||
LookupExpression {
|
||||
|
@ -379,55 +379,49 @@ impl<'a> ExpressionContext<'a, '_, '_> {
|
||||
}
|
||||
|
||||
enum Composition {
|
||||
Single(crate::Expression),
|
||||
Multi(crate::VectorSize, Vec<Handle<crate::Expression>>),
|
||||
Single(u32),
|
||||
Multi(crate::VectorSize, [crate::SwizzleComponent; 4]),
|
||||
}
|
||||
|
||||
impl Composition {
|
||||
//TODO: could be `const fn` once MSRV allows
|
||||
fn letter_pos(letter: char) -> u32 {
|
||||
fn letter_component(letter: char) -> Option<crate::SwizzleComponent> {
|
||||
use crate::SwizzleComponent as Sc;
|
||||
match letter {
|
||||
'x' | 'r' => 0,
|
||||
'y' | 'g' => 1,
|
||||
'z' | 'b' => 2,
|
||||
'w' | 'a' => 3,
|
||||
_ => !0,
|
||||
'x' | 'r' => Some(Sc::X),
|
||||
'y' | 'g' => Some(Sc::Y),
|
||||
'z' | 'b' => Some(Sc::Z),
|
||||
'w' | 'a' => Some(Sc::W),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_impl(name: &str, name_span: Range<usize>) -> Result<u32, Error> {
|
||||
let ch = name
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
|
||||
match Self::letter_component(ch) {
|
||||
Some(sc) => Ok(sc as u32),
|
||||
None => Err(Error::BadAccessor(name_span)),
|
||||
}
|
||||
}
|
||||
|
||||
fn extract(
|
||||
base: Handle<crate::Expression>,
|
||||
base_size: crate::VectorSize,
|
||||
name: &str,
|
||||
name_span: Range<usize>,
|
||||
) -> Result<crate::Expression, Error> {
|
||||
let ch = name
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
|
||||
let index = Self::letter_pos(ch);
|
||||
if index >= base_size as u32 {
|
||||
return Err(Error::BadAccessor(name_span));
|
||||
}
|
||||
Ok(crate::Expression::AccessIndex { base, index })
|
||||
Self::extract_impl(name, name_span)
|
||||
.map(|index| crate::Expression::AccessIndex { base, index })
|
||||
}
|
||||
|
||||
fn make<'a>(
|
||||
base: Handle<crate::Expression>,
|
||||
base_size: crate::VectorSize,
|
||||
name: &'a str,
|
||||
name_span: Range<usize>,
|
||||
expressions: &mut Arena<crate::Expression>,
|
||||
) -> Result<Self, Error<'a>> {
|
||||
fn make(name: &str, name_span: Range<usize>) -> Result<Self, Error> {
|
||||
if name.len() > 1 {
|
||||
let mut components = Vec::with_capacity(name.len());
|
||||
for ch in name.chars() {
|
||||
let index = Self::letter_pos(ch);
|
||||
if index >= base_size as u32 {
|
||||
return Err(Error::BadAccessor(name_span));
|
||||
}
|
||||
let expr = crate::Expression::AccessIndex { base, index };
|
||||
components.push(expressions.append(expr));
|
||||
let mut components = [crate::SwizzleComponent::X; 4];
|
||||
for (comp, ch) in components.iter_mut().zip(name.chars()) {
|
||||
*comp = Self::letter_component(ch)
|
||||
.ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
|
||||
}
|
||||
|
||||
let size = match name.len() {
|
||||
@ -438,7 +432,7 @@ impl Composition {
|
||||
};
|
||||
Ok(Composition::Multi(size, components))
|
||||
} else {
|
||||
Self::extract(base, base_size, name, name_span).map(Composition::Single)
|
||||
Self::extract_impl(name, name_span).map(Composition::Single)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -504,14 +498,23 @@ impl BindingParser {
|
||||
}
|
||||
|
||||
fn finish<'a>(self) -> Result<Option<crate::Binding>, Error<'a>> {
|
||||
match (self.location, self.built_in, self.interpolation, self.sampling) {
|
||||
match (
|
||||
self.location,
|
||||
self.built_in,
|
||||
self.interpolation,
|
||||
self.sampling,
|
||||
) {
|
||||
(None, None, None, None) => Ok(None),
|
||||
(Some(location), None, interpolation, sampling) => {
|
||||
// Before handing over the completed `Module`, we call
|
||||
// `apply_common_default_interpolation` to ensure that the interpolation and
|
||||
// sampling have been explicitly specified on all vertex shader output and fragment
|
||||
// shader input user bindings, so leaving them potentially `None` here is fine.
|
||||
Ok(Some(crate::Binding::Location { location, interpolation, sampling }))
|
||||
Ok(Some(crate::Binding::Location {
|
||||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
}))
|
||||
}
|
||||
(None, Some(bi), None, None) => Ok(Some(crate::Binding::BuiltIn(bi))),
|
||||
(location, built_in, interpolation, sampling) => Err(Error::InconsistentBinding(
|
||||
@ -1251,52 +1254,24 @@ impl Parser {
|
||||
index,
|
||||
}
|
||||
}
|
||||
crate::TypeInner::Vector { size, kind, width } => {
|
||||
match Composition::make(handle, size, name, name_span, ctx.expressions)?
|
||||
{
|
||||
//TODO: Swizzling in IR
|
||||
Composition::Multi(size, components) => {
|
||||
let inner = crate::TypeInner::Vector { size, kind, width };
|
||||
crate::Expression::Compose {
|
||||
ty: ctx
|
||||
.types
|
||||
.fetch_or_append(crate::Type { name: None, inner }),
|
||||
components,
|
||||
crate::TypeInner::Vector { .. } | crate::TypeInner::Matrix { .. } => {
|
||||
match Composition::make(name, name_span)? {
|
||||
Composition::Multi(dst_size, pattern) => {
|
||||
crate::Expression::Swizzle {
|
||||
size: dst_size,
|
||||
vector: handle,
|
||||
pattern,
|
||||
}
|
||||
}
|
||||
Composition::Single(expr) => expr,
|
||||
Composition::Single(index) => crate::Expression::AccessIndex {
|
||||
base: handle,
|
||||
index,
|
||||
},
|
||||
}
|
||||
}
|
||||
crate::TypeInner::Matrix {
|
||||
columns,
|
||||
rows,
|
||||
width,
|
||||
} => match Composition::make(
|
||||
handle,
|
||||
columns,
|
||||
name,
|
||||
name_span,
|
||||
ctx.expressions,
|
||||
)? {
|
||||
//TODO: is this really supported?
|
||||
Composition::Multi(columns, components) => {
|
||||
let inner = crate::TypeInner::Matrix {
|
||||
columns,
|
||||
rows,
|
||||
width,
|
||||
};
|
||||
crate::Expression::Compose {
|
||||
ty: ctx
|
||||
.types
|
||||
.fetch_or_append(crate::Type { name: None, inner }),
|
||||
components,
|
||||
}
|
||||
}
|
||||
Composition::Single(expr) => expr,
|
||||
},
|
||||
crate::TypeInner::ValuePointer {
|
||||
size: Some(size), ..
|
||||
} => Composition::extract(handle, size, name, name_span)?,
|
||||
crate::TypeInner::ValuePointer { .. } => {
|
||||
Composition::extract(handle, name, name_span)?
|
||||
}
|
||||
crate::TypeInner::Pointer { base, class: _ } => match ctx.types[base].inner
|
||||
{
|
||||
crate::TypeInner::Struct { ref members, .. } => {
|
||||
@ -1310,13 +1285,7 @@ impl Parser {
|
||||
index,
|
||||
}
|
||||
}
|
||||
crate::TypeInner::Vector { size, .. } => {
|
||||
Composition::extract(handle, size, name, name_span)?
|
||||
}
|
||||
crate::TypeInner::Matrix { columns, .. } => {
|
||||
Composition::extract(handle, columns, name, name_span)?
|
||||
}
|
||||
_ => return Err(Error::BadAccessor(name_span)),
|
||||
_ => Composition::extract(handle, name, name_span)?,
|
||||
},
|
||||
_ => return Err(Error::BadAccessor(name_span)),
|
||||
}
|
||||
|
23
src/lib.rs
23
src/lib.rs
@ -480,7 +480,7 @@ pub enum Binding {
|
||||
Location {
|
||||
location: u32,
|
||||
interpolation: Option<Interpolation>,
|
||||
sampling: Option<Sampling>
|
||||
sampling: Option<Sampling>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -679,6 +679,21 @@ pub enum ImageQuery {
|
||||
NumSamples,
|
||||
}
|
||||
|
||||
/// Component selection for a vector swizzle.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
|
||||
pub enum SwizzleComponent {
|
||||
///
|
||||
X,
|
||||
///
|
||||
Y,
|
||||
///
|
||||
Z,
|
||||
///
|
||||
W,
|
||||
}
|
||||
|
||||
/// An expression that can be evaluated to obtain a value.
|
||||
///
|
||||
/// This is a Single Static Assignment (SSA) scheme similar to SPIR-V.
|
||||
@ -704,6 +719,12 @@ pub enum Expression {
|
||||
size: VectorSize,
|
||||
value: Handle<Expression>,
|
||||
},
|
||||
/// Vector swizzle.
|
||||
Swizzle {
|
||||
size: VectorSize,
|
||||
vector: Handle<Expression>,
|
||||
pattern: [SwizzleComponent; 4],
|
||||
},
|
||||
/// Composite expression.
|
||||
Compose {
|
||||
ty: Handle<Type>,
|
||||
|
@ -36,13 +36,16 @@ impl crate::Module {
|
||||
/// `binding` refers to the `Binding` whose type is `ty`. If `ty` is a struct, then it's the
|
||||
/// bindings of the struct's members that we care about, and the binding of the struct
|
||||
/// itself is meaningless, so `binding` should be `None`.
|
||||
fn default_binding_or_struct(binding: &mut Option<Binding>,
|
||||
ty: Handle<Type>,
|
||||
types: &mut Arena<Type>)
|
||||
{
|
||||
fn default_binding_or_struct(
|
||||
binding: &mut Option<Binding>,
|
||||
ty: Handle<Type>,
|
||||
types: &mut Arena<Type>,
|
||||
) {
|
||||
match types.get_mut(ty).inner {
|
||||
// A struct. It's the individual members we care about, so recurse.
|
||||
TypeInner::Struct { members: ref mut m, .. } => {
|
||||
TypeInner::Struct {
|
||||
members: ref mut m, ..
|
||||
} => {
|
||||
// To choose the right interpolations for `members`, we must consult other
|
||||
// elements of `types`. But both `members` and the types it refers to are stored
|
||||
// in `types`, and Rust won't let us mutate one element of the `Arena`'s `Vec`
|
||||
@ -61,7 +64,9 @@ impl crate::Module {
|
||||
// afresh here, rather than just using `m`: it's only because `m` was dead that
|
||||
// we were able to pass `types` to the recursive call.
|
||||
match types.get_mut(ty).inner {
|
||||
TypeInner::Struct { members: ref mut m, .. } => replace(m, members),
|
||||
TypeInner::Struct {
|
||||
members: ref mut m, ..
|
||||
} => replace(m, members),
|
||||
_ => unreachable!("ty must be a struct"),
|
||||
};
|
||||
}
|
||||
@ -71,16 +76,29 @@ impl crate::Module {
|
||||
// GLSL has 64-bit floats, but it won't interpolate them. WGSL and MSL only have
|
||||
// 32-bit floats. SPIR-V has 16- and 64-bit float capabilities, but Vulkan is vague
|
||||
// about what can and cannot be interpolated.
|
||||
TypeInner::Scalar { kind: ScalarKind::Float, width: 4 } |
|
||||
TypeInner::Vector { kind: ScalarKind::Float, width: 4, .. } => {
|
||||
TypeInner::Scalar {
|
||||
kind: ScalarKind::Float,
|
||||
width: 4,
|
||||
}
|
||||
| TypeInner::Vector {
|
||||
kind: ScalarKind::Float,
|
||||
width: 4,
|
||||
..
|
||||
} => {
|
||||
// unwrap: all `EntryPoint` arguments or return values must either be structures
|
||||
// or have a `Binding`.
|
||||
let binding = binding.as_mut().unwrap();
|
||||
if let Binding::Location { ref mut interpolation, ref mut sampling, .. } = *binding {
|
||||
if let Binding::Location {
|
||||
ref mut interpolation,
|
||||
ref mut sampling,
|
||||
..
|
||||
} = *binding
|
||||
{
|
||||
if interpolation.is_none() {
|
||||
*interpolation = Some(crate::Interpolation::Perspective);
|
||||
}
|
||||
if sampling.is_none() && *interpolation != Some(crate::Interpolation::Flat) {
|
||||
if sampling.is_none() && *interpolation != Some(crate::Interpolation::Flat)
|
||||
{
|
||||
*sampling = Some(crate::Sampling::Center);
|
||||
}
|
||||
}
|
||||
@ -91,7 +109,12 @@ impl crate::Module {
|
||||
// unwrap: all `EntryPoint` arguments or return values must either be structures
|
||||
// or have a `Binding`.
|
||||
let binding = binding.as_mut().unwrap();
|
||||
if let Binding::Location { ref mut interpolation, ref mut sampling, .. } = *binding {
|
||||
if let Binding::Location {
|
||||
ref mut interpolation,
|
||||
ref mut sampling,
|
||||
..
|
||||
} = *binding
|
||||
{
|
||||
*interpolation = Some(crate::Interpolation::Flat);
|
||||
*sampling = None;
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ pub enum ResolveError {
|
||||
},
|
||||
#[error("Invalid scalar {0:?}")]
|
||||
InvalidScalar(Handle<crate::Expression>),
|
||||
#[error("Invalid vector {0:?}")]
|
||||
InvalidVector(Handle<crate::Expression>),
|
||||
#[error("Invalid pointer {0:?}")]
|
||||
InvalidPointer(Handle<crate::Expression>),
|
||||
#[error("Invalid image {0:?}")]
|
||||
@ -288,6 +290,21 @@ impl<'a> ResolveContext<'a> {
|
||||
return Err(ResolveError::InvalidScalar(value));
|
||||
}
|
||||
},
|
||||
crate::Expression::Swizzle {
|
||||
size,
|
||||
vector,
|
||||
pattern: _,
|
||||
} => match *past(vector).inner_with(types) {
|
||||
Ti::Vector {
|
||||
size: _,
|
||||
kind,
|
||||
width,
|
||||
} => TypeResolution::Value(Ti::Vector { size, kind, width }),
|
||||
ref other => {
|
||||
log::error!("Vector type {:?}", other);
|
||||
return Err(ResolveError::InvalidVector(vector));
|
||||
}
|
||||
},
|
||||
crate::Expression::Compose { ty, .. } => TypeResolution::Handle(ty),
|
||||
crate::Expression::FunctionArgument(index) => {
|
||||
TypeResolution::Handle(self.arguments[index as usize].ty)
|
||||
|
@ -322,6 +322,10 @@ impl FunctionInfo {
|
||||
non_uniform_result: self.add_ref(value),
|
||||
requirements: UniformityRequirements::empty(),
|
||||
},
|
||||
E::Swizzle { vector, .. } => Uniformity {
|
||||
non_uniform_result: self.add_ref(vector),
|
||||
requirements: UniformityRequirements::empty(),
|
||||
},
|
||||
E::Compose { ref components, .. } => {
|
||||
let non_uniform_result = components
|
||||
.iter()
|
||||
|
@ -33,6 +33,10 @@ pub enum ExpressionError {
|
||||
InvalidArrayType(Handle<crate::Expression>),
|
||||
#[error("Splatting {0:?} can't be done")]
|
||||
InvalidSplatType(Handle<crate::Expression>),
|
||||
#[error("Swizzling {0:?} can't be done")]
|
||||
InvalidVectorType(Handle<crate::Expression>),
|
||||
#[error("Swizzle component {0:?} is outside of vector size {1:?}")]
|
||||
InvalidSwizzleComponent(crate::SwizzleComponent, crate::VectorSize),
|
||||
#[error(transparent)]
|
||||
Compose(#[from] ComposeError),
|
||||
#[error("Operation {0:?} can't work with {1:?}")]
|
||||
@ -200,6 +204,25 @@ impl super::Validator {
|
||||
return Err(ExpressionError::InvalidSplatType(value));
|
||||
}
|
||||
},
|
||||
E::Swizzle {
|
||||
size,
|
||||
vector,
|
||||
pattern,
|
||||
} => {
|
||||
let vec_size = match *resolver.resolve(vector)? {
|
||||
Ti::Vector { size: vec_size, .. } => vec_size,
|
||||
ref other => {
|
||||
log::error!("Swizzle vector type {:?}", other);
|
||||
return Err(ExpressionError::InvalidVectorType(vector));
|
||||
}
|
||||
};
|
||||
for &sc in pattern[..size as usize].iter() {
|
||||
if sc as u8 >= vec_size as u8 {
|
||||
return Err(ExpressionError::InvalidSwizzleComponent(sc, vec_size));
|
||||
}
|
||||
}
|
||||
ShaderStages::all()
|
||||
}
|
||||
E::Compose { ref components, ty } => {
|
||||
for &handle in components {
|
||||
if handle >= root {
|
||||
|
@ -208,7 +208,11 @@ impl VaryingContext<'_> {
|
||||
return Err(VaryingError::InvalidBuiltInType(built_in));
|
||||
}
|
||||
}
|
||||
crate::Binding::Location { location, interpolation, sampling } => {
|
||||
crate::Binding::Location {
|
||||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
} => {
|
||||
if !self.location_mask.insert(location as usize) {
|
||||
return Err(VaryingError::BindingCollision { location });
|
||||
}
|
||||
@ -235,7 +239,8 @@ impl VaryingContext<'_> {
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
if needs_interpolation && interpolation != Some(crate::Interpolation::Flat) {
|
||||
if needs_interpolation && interpolation != Some(crate::Interpolation::Flat)
|
||||
{
|
||||
return Err(VaryingError::InvalidInterpolation);
|
||||
}
|
||||
}
|
||||
|
@ -76,24 +76,3 @@ fn invalid_scalar_width() {
|
||||
"###,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "wgsl-in")]
|
||||
#[test]
|
||||
fn invalid_accessor() {
|
||||
check(
|
||||
r###"
|
||||
[[stage(vertex)]]
|
||||
fn vs_main() {
|
||||
var color: vec3<f32> = vec3<f32>(1.0, 2.0, 3.0);
|
||||
var i: f32 = color.a;
|
||||
}
|
||||
"###,
|
||||
r###"error: invalid field accessor `a`
|
||||
┌─ wgsl:5:24
|
||||
│
|
||||
5 │ var i: f32 = color.a;
|
||||
│ ^ invalid accessor
|
||||
|
||||
"###,
|
||||
);
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ kernel void main1(
|
||||
, metal::texture2d<uint, metal::access::read> image_src [[user(fake0)]]
|
||||
, metal::texture1d<uint, metal::access::write> image_dst [[user(fake0)]]
|
||||
) {
|
||||
metal::int2 _e12 = (int2(image_src.get_width(), image_src.get_height()) * static_cast<int2>(metal::uint2(local_id.x, local_id.y))) % metal::int2(10, 20);
|
||||
metal::uint4 _e13 = image_src.read(metal::uint2(_e12));
|
||||
image_dst.write(_e13, metal::uint(_e12.x));
|
||||
metal::int2 _e10 = (int2(image_src.get_width(), image_src.get_height()) * static_cast<int2>(local_id.xy)) % metal::int2(10, 20);
|
||||
metal::uint4 _e11 = image_src.read(metal::uint2(_e10));
|
||||
image_dst.write(_e11, metal::uint(_e10.x));
|
||||
return;
|
||||
}
|
||||
|
@ -4,8 +4,7 @@ precision highp float;
|
||||
|
||||
|
||||
void main() {
|
||||
vec2 _expr10 = (((vec2(1.0) + vec2(2.0)) - vec2(3.0)) / vec2(4.0));
|
||||
gl_Position = (vec4(_expr10[0], _expr10[1], _expr10[0], _expr10[1]) + vec4((ivec4(5) % ivec4(2))));
|
||||
gl_Position = ((((vec2(1.0) + vec2(2.0)) - vec2(3.0)) / vec2(4.0)).xyxy + vec4((ivec4(5) % ivec4(2))));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,5 @@ struct splatOutput {
|
||||
};
|
||||
vertex splatOutput splat(
|
||||
) {
|
||||
metal::float2 _e10 = ((float2(1.0) + float2(2.0)) - float2(3.0)) / float2(4.0);
|
||||
return splatOutput { metal::float4(_e10.x, _e10.y, _e10.x, _e10.y) + static_cast<float4>(int4(5) % int4(2)) };
|
||||
return splatOutput { (((float2(1.0) + float2(2.0)) - float2(3.0)) / float2(4.0)).xyxy + static_cast<float4>(int4(5) % int4(2)) };
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: rspirv
|
||||
; Bound: 37
|
||||
; Bound: 33
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
@ -36,13 +36,9 @@ OpBranch %17
|
||||
%27 = OpCompositeConstruct %26 %8 %8 %8 %8
|
||||
%28 = OpCompositeConstruct %26 %10 %10 %10 %10
|
||||
%29 = OpSMod %26 %27 %28
|
||||
%30 = OpCompositeExtract %4 %25 0
|
||||
%31 = OpCompositeExtract %4 %25 1
|
||||
%32 = OpCompositeExtract %4 %25 0
|
||||
%33 = OpCompositeExtract %4 %25 1
|
||||
%34 = OpCompositeConstruct %11 %30 %31 %32 %33
|
||||
%35 = OpConvertSToF %11 %29
|
||||
%36 = OpFAdd %11 %34 %35
|
||||
OpStore %13 %36
|
||||
%30 = OpVectorShuffle %11 %25 %25 0 1 0 1
|
||||
%31 = OpConvertSToF %11 %29
|
||||
%32 = OpFAdd %11 %30 %31
|
||||
OpStore %13 %32
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -26,8 +26,8 @@ float fetch_shadow(uint light_id, vec4 homogeneous_coords) {
|
||||
if((homogeneous_coords[3] <= 0.0)) {
|
||||
return 1.0;
|
||||
}
|
||||
float _expr28 = textureGrad(_group_0_binding_2, vec4((((vec2(homogeneous_coords[0], homogeneous_coords[1]) * vec2(0.5, -0.5)) / vec2(homogeneous_coords[3])) + vec2(0.5, 0.5)), int(light_id), (homogeneous_coords[2] / homogeneous_coords[3])), vec2(0, 0), vec2(0,0));
|
||||
return _expr28;
|
||||
float _expr26 = textureGrad(_group_0_binding_2, vec4((((homogeneous_coords.xy * vec2(0.5, -0.5)) / vec2(homogeneous_coords[3])) + vec2(0.5, 0.5)), int(light_id), (homogeneous_coords[2] / homogeneous_coords[3])), vec2(0, 0), vec2(0,0));
|
||||
return _expr26;
|
||||
}
|
||||
|
||||
void main() {
|
||||
@ -41,7 +41,7 @@ void main() {
|
||||
}
|
||||
Light _expr21 = _group_0_binding_1.data[i];
|
||||
float _expr25 = fetch_shadow(i, (_expr21.proj * position));
|
||||
color1 = (color1 + ((_expr25 * max(0.0, dot(normalize(raw_normal), normalize((vec3(_expr21.pos[0], _expr21.pos[1], _expr21.pos[2]) - vec3(position[0], position[1], position[2])))))) * vec3(_expr21.color[0], _expr21.color[1], _expr21.color[2])));
|
||||
color1 = (color1 + ((_expr25 * max(0.0, dot(normalize(raw_normal), normalize((_expr21.pos.xyz - position.xyz))))) * _expr21.color.xyz));
|
||||
i = (i + 1u);
|
||||
}
|
||||
_fs2p_location0 = vec4(color1, 1.0);
|
||||
|
@ -25,8 +25,8 @@ float fetch_shadow(
|
||||
if (homogeneous_coords.w <= 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
float _e28 = t_shadow.sample_compare(sampler_shadow, ((metal::float2(homogeneous_coords.x, homogeneous_coords.y) * metal::float2(0.5, -0.5)) / float2(homogeneous_coords.w)) + metal::float2(0.5, 0.5), static_cast<int>(light_id), homogeneous_coords.z / homogeneous_coords.w);
|
||||
return _e28;
|
||||
float _e26 = t_shadow.sample_compare(sampler_shadow, ((homogeneous_coords.xy * metal::float2(0.5, -0.5)) / float2(homogeneous_coords.w)) + metal::float2(0.5, 0.5), static_cast<int>(light_id), homogeneous_coords.z / homogeneous_coords.w);
|
||||
return _e26;
|
||||
}
|
||||
|
||||
struct fs_mainInput {
|
||||
@ -58,7 +58,7 @@ fragment fs_mainOutput fs_main(
|
||||
}
|
||||
Light _e21 = s_lights.data[i];
|
||||
float _e25 = fetch_shadow(i, _e21.proj * position, t_shadow, sampler_shadow);
|
||||
color1 = color1 + ((_e25 * metal::max(0.0, metal::dot(metal::normalize(raw_normal), metal::normalize(metal::float3(_e21.pos.x, _e21.pos.y, _e21.pos.z) - metal::float3(position.x, position.y, position.z))))) * metal::float3(_e21.color.x, _e21.color.y, _e21.color.z));
|
||||
color1 = color1 + ((_e25 * metal::max(0.0, metal::dot(metal::normalize(raw_normal), metal::normalize(_e21.pos.xyz - position.xyz)))) * _e21.color.xyz);
|
||||
}
|
||||
return fs_mainOutput { metal::float4(color1, 1.0) };
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
; SPIR-V
|
||||
; Version: 1.2
|
||||
; Generator: rspirv
|
||||
; Bound: 137
|
||||
; Bound: 126
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %82 "fs_main" %74 %77 %80
|
||||
OpExecutionMode %82 OriginUpperLeft
|
||||
OpEntryPoint Fragment %80 "fs_main" %72 %75 %78
|
||||
OpExecutionMode %80 OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %9 "c_max_lights"
|
||||
OpName %14 "Globals"
|
||||
@ -24,11 +24,11 @@ OpName %27 "s_lights"
|
||||
OpName %29 "t_shadow"
|
||||
OpName %31 "sampler_shadow"
|
||||
OpName %36 "fetch_shadow"
|
||||
OpName %69 "color"
|
||||
OpName %71 "i"
|
||||
OpName %74 "raw_normal"
|
||||
OpName %77 "position"
|
||||
OpName %82 "fs_main"
|
||||
OpName %67 "color"
|
||||
OpName %69 "i"
|
||||
OpName %72 "raw_normal"
|
||||
OpName %75 "position"
|
||||
OpName %80 "fs_main"
|
||||
OpDecorate %14 Block
|
||||
OpMemberDecorate %14 0 Offset 0
|
||||
OpMemberDecorate %17 0 Offset 0
|
||||
@ -48,9 +48,9 @@ OpDecorate %29 DescriptorSet 0
|
||||
OpDecorate %29 Binding 2
|
||||
OpDecorate %31 DescriptorSet 0
|
||||
OpDecorate %31 Binding 3
|
||||
OpDecorate %74 Location 0
|
||||
OpDecorate %77 Location 1
|
||||
OpDecorate %80 Location 0
|
||||
OpDecorate %72 Location 0
|
||||
OpDecorate %75 Location 1
|
||||
OpDecorate %78 Location 0
|
||||
%2 = OpTypeVoid
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpConstant %4 0.0
|
||||
@ -84,22 +84,22 @@ OpDecorate %80 Location 0
|
||||
%31 = OpVariable %32 UniformConstant
|
||||
%37 = OpTypeFunction %4 %10 %16
|
||||
%42 = OpTypeBool
|
||||
%56 = OpTypeInt 32 1
|
||||
%61 = OpTypeSampledImage %20
|
||||
%68 = OpConstant %4 0.0
|
||||
%70 = OpTypePointer Function %23
|
||||
%72 = OpTypePointer Function %10
|
||||
%75 = OpTypePointer Input %23
|
||||
%74 = OpVariable %75 Input
|
||||
%78 = OpTypePointer Input %16
|
||||
%77 = OpVariable %78 Input
|
||||
%81 = OpTypePointer Output %16
|
||||
%80 = OpVariable %81 Output
|
||||
%83 = OpTypeFunction %2
|
||||
%93 = OpTypePointer Uniform %13
|
||||
%94 = OpConstant %56 0
|
||||
%102 = OpTypePointer StorageBuffer %18
|
||||
%104 = OpTypePointer StorageBuffer %17
|
||||
%54 = OpTypeInt 32 1
|
||||
%59 = OpTypeSampledImage %20
|
||||
%66 = OpConstant %4 0.0
|
||||
%68 = OpTypePointer Function %23
|
||||
%70 = OpTypePointer Function %10
|
||||
%73 = OpTypePointer Input %23
|
||||
%72 = OpVariable %73 Input
|
||||
%76 = OpTypePointer Input %16
|
||||
%75 = OpVariable %76 Input
|
||||
%79 = OpTypePointer Output %16
|
||||
%78 = OpVariable %79 Output
|
||||
%81 = OpTypeFunction %2
|
||||
%91 = OpTypePointer Uniform %13
|
||||
%92 = OpConstant %54 0
|
||||
%100 = OpTypePointer StorageBuffer %18
|
||||
%102 = OpTypePointer StorageBuffer %17
|
||||
%36 = OpFunction %4 None %37
|
||||
%34 = OpFunctionParameter %10
|
||||
%35 = OpFunctionParameter %16
|
||||
@ -116,93 +116,82 @@ OpBranchConditional %43 %45 %44
|
||||
OpReturnValue %5
|
||||
%44 = OpLabel
|
||||
%46 = OpCompositeConstruct %22 %6 %7
|
||||
%47 = OpCompositeExtract %4 %35 0
|
||||
%48 = OpCompositeExtract %4 %35 1
|
||||
%49 = OpCompositeConstruct %22 %47 %48
|
||||
%50 = OpFMul %22 %49 %46
|
||||
%51 = OpCompositeExtract %4 %35 3
|
||||
%52 = OpCompositeConstruct %22 %51 %51
|
||||
%53 = OpFDiv %22 %50 %52
|
||||
%54 = OpCompositeConstruct %22 %6 %6
|
||||
%55 = OpFAdd %22 %53 %54
|
||||
%57 = OpBitcast %56 %34
|
||||
%58 = OpCompositeExtract %4 %35 2
|
||||
%59 = OpCompositeExtract %4 %35 3
|
||||
%60 = OpFDiv %4 %58 %59
|
||||
%62 = OpCompositeExtract %4 %55 0
|
||||
%63 = OpCompositeExtract %4 %55 1
|
||||
%64 = OpConvertUToF %4 %57
|
||||
%65 = OpCompositeConstruct %23 %62 %63 %64
|
||||
%66 = OpSampledImage %61 %38 %39
|
||||
%67 = OpImageSampleDrefExplicitLod %4 %66 %65 %60 Lod %68
|
||||
OpReturnValue %67
|
||||
%47 = OpVectorShuffle %22 %35 %35 0 1
|
||||
%48 = OpFMul %22 %47 %46
|
||||
%49 = OpCompositeExtract %4 %35 3
|
||||
%50 = OpCompositeConstruct %22 %49 %49
|
||||
%51 = OpFDiv %22 %48 %50
|
||||
%52 = OpCompositeConstruct %22 %6 %6
|
||||
%53 = OpFAdd %22 %51 %52
|
||||
%55 = OpBitcast %54 %34
|
||||
%56 = OpCompositeExtract %4 %35 2
|
||||
%57 = OpCompositeExtract %4 %35 3
|
||||
%58 = OpFDiv %4 %56 %57
|
||||
%60 = OpCompositeExtract %4 %53 0
|
||||
%61 = OpCompositeExtract %4 %53 1
|
||||
%62 = OpConvertUToF %4 %55
|
||||
%63 = OpCompositeConstruct %23 %60 %61 %62
|
||||
%64 = OpSampledImage %59 %38 %39
|
||||
%65 = OpImageSampleDrefExplicitLod %4 %64 %63 %58 Lod %66
|
||||
OpReturnValue %65
|
||||
OpFunctionEnd
|
||||
%82 = OpFunction %2 None %83
|
||||
%73 = OpLabel
|
||||
%69 = OpVariable %70 Function %24
|
||||
%71 = OpVariable %72 Function %11
|
||||
%76 = OpLoad %23 %74
|
||||
%79 = OpLoad %16 %77
|
||||
%84 = OpLoad %20 %29
|
||||
%85 = OpLoad %21 %31
|
||||
%80 = OpFunction %2 None %81
|
||||
%71 = OpLabel
|
||||
%67 = OpVariable %68 Function %24
|
||||
%69 = OpVariable %70 Function %11
|
||||
%74 = OpLoad %23 %72
|
||||
%77 = OpLoad %16 %75
|
||||
%82 = OpLoad %20 %29
|
||||
%83 = OpLoad %21 %31
|
||||
OpBranch %84
|
||||
%84 = OpLabel
|
||||
%85 = OpExtInst %23 %1 Normalize %74
|
||||
OpBranch %86
|
||||
%86 = OpLabel
|
||||
%87 = OpExtInst %23 %1 Normalize %76
|
||||
OpLoopMerge %87 %89 None
|
||||
OpBranch %88
|
||||
%88 = OpLabel
|
||||
OpLoopMerge %89 %91 None
|
||||
OpBranch %90
|
||||
%90 = OpLabel
|
||||
%92 = OpLoad %10 %71
|
||||
%95 = OpAccessChain %93 %25 %94
|
||||
%96 = OpLoad %13 %95
|
||||
%97 = OpCompositeExtract %10 %96 0
|
||||
%98 = OpExtInst %10 %1 UMin %97 %9
|
||||
%99 = OpUGreaterThanEqual %42 %92 %98
|
||||
OpSelectionMerge %100 None
|
||||
OpBranchConditional %99 %101 %100
|
||||
%101 = OpLabel
|
||||
%90 = OpLoad %10 %69
|
||||
%93 = OpAccessChain %91 %25 %92
|
||||
%94 = OpLoad %13 %93
|
||||
%95 = OpCompositeExtract %10 %94 0
|
||||
%96 = OpExtInst %10 %1 UMin %95 %9
|
||||
%97 = OpUGreaterThanEqual %42 %90 %96
|
||||
OpSelectionMerge %98 None
|
||||
OpBranchConditional %97 %99 %98
|
||||
%99 = OpLabel
|
||||
OpBranch %87
|
||||
%98 = OpLabel
|
||||
%101 = OpLoad %10 %69
|
||||
%103 = OpAccessChain %102 %27 %92 %101
|
||||
%104 = OpLoad %17 %103
|
||||
%105 = OpLoad %10 %69
|
||||
%106 = OpCompositeExtract %15 %104 0
|
||||
%107 = OpMatrixTimesVector %16 %106 %77
|
||||
%108 = OpFunctionCall %4 %36 %105 %107
|
||||
%109 = OpCompositeExtract %16 %104 1
|
||||
%110 = OpVectorShuffle %23 %109 %109 0 1 2
|
||||
%111 = OpVectorShuffle %23 %77 %77 0 1 2
|
||||
%112 = OpFSub %23 %110 %111
|
||||
%113 = OpExtInst %23 %1 Normalize %112
|
||||
%114 = OpDot %4 %85 %113
|
||||
%115 = OpExtInst %4 %1 FMax %3 %114
|
||||
%116 = OpLoad %23 %67
|
||||
%117 = OpFMul %4 %108 %115
|
||||
%118 = OpCompositeExtract %16 %104 2
|
||||
%119 = OpVectorShuffle %23 %118 %118 0 1 2
|
||||
%120 = OpVectorTimesScalar %23 %119 %117
|
||||
%121 = OpFAdd %23 %116 %120
|
||||
OpStore %67 %121
|
||||
OpBranch %89
|
||||
%100 = OpLabel
|
||||
%103 = OpLoad %10 %71
|
||||
%105 = OpAccessChain %104 %27 %94 %103
|
||||
%106 = OpLoad %17 %105
|
||||
%107 = OpLoad %10 %71
|
||||
%108 = OpCompositeExtract %15 %106 0
|
||||
%109 = OpMatrixTimesVector %16 %108 %79
|
||||
%110 = OpFunctionCall %4 %36 %107 %109
|
||||
%111 = OpCompositeExtract %16 %106 1
|
||||
%112 = OpCompositeExtract %4 %111 0
|
||||
%113 = OpCompositeExtract %4 %111 1
|
||||
%114 = OpCompositeExtract %4 %111 2
|
||||
%115 = OpCompositeConstruct %23 %112 %113 %114
|
||||
%116 = OpCompositeExtract %4 %79 0
|
||||
%117 = OpCompositeExtract %4 %79 1
|
||||
%118 = OpCompositeExtract %4 %79 2
|
||||
%119 = OpCompositeConstruct %23 %116 %117 %118
|
||||
%120 = OpFSub %23 %115 %119
|
||||
%121 = OpExtInst %23 %1 Normalize %120
|
||||
%122 = OpDot %4 %87 %121
|
||||
%123 = OpExtInst %4 %1 FMax %3 %122
|
||||
%124 = OpLoad %23 %69
|
||||
%125 = OpFMul %4 %110 %123
|
||||
%126 = OpCompositeExtract %16 %106 2
|
||||
%127 = OpCompositeExtract %4 %126 0
|
||||
%128 = OpCompositeExtract %4 %126 1
|
||||
%129 = OpCompositeExtract %4 %126 2
|
||||
%130 = OpCompositeConstruct %23 %127 %128 %129
|
||||
%131 = OpVectorTimesScalar %23 %130 %125
|
||||
%132 = OpFAdd %23 %124 %131
|
||||
OpStore %69 %132
|
||||
OpBranch %91
|
||||
%91 = OpLabel
|
||||
%133 = OpLoad %10 %71
|
||||
%134 = OpIAdd %10 %133 %12
|
||||
OpStore %71 %134
|
||||
OpBranch %88
|
||||
%89 = OpLabel
|
||||
%135 = OpLoad %23 %69
|
||||
%136 = OpCompositeConstruct %16 %135 %5
|
||||
OpStore %80 %136
|
||||
%122 = OpLoad %10 %69
|
||||
%123 = OpIAdd %10 %122 %12
|
||||
OpStore %69 %123
|
||||
OpBranch %86
|
||||
%87 = OpLabel
|
||||
%124 = OpLoad %23 %67
|
||||
%125 = OpCompositeConstruct %16 %124 %5
|
||||
OpStore %78 %125
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -21,9 +21,8 @@ void main() {
|
||||
tmp1_ = (int(vertex_index) / 2);
|
||||
tmp2_ = (int(vertex_index) & 1);
|
||||
vec4 _expr24 = vec4(((float(tmp1_) * 4.0) - 1.0), ((float(tmp2_) * 4.0) - 1.0), 0.0, 1.0);
|
||||
vec4 _expr50 = (_group_0_binding_0.proj_inv * _expr24);
|
||||
gl_Position = VertexOutput(_expr24, (transpose(mat3x3(vec3(_group_0_binding_0.view[0][0], _group_0_binding_0.view[0][1], _group_0_binding_0.view[0][2]), vec3(_group_0_binding_0.view[1][0], _group_0_binding_0.view[1][1], _group_0_binding_0.view[1][2]), vec3(_group_0_binding_0.view[2][0], _group_0_binding_0.view[2][1], _group_0_binding_0.view[2][2]))) * vec3(_expr50[0], _expr50[1], _expr50[2]))).position;
|
||||
_vs2fs_location0 = VertexOutput(_expr24, (transpose(mat3x3(vec3(_group_0_binding_0.view[0][0], _group_0_binding_0.view[0][1], _group_0_binding_0.view[0][2]), vec3(_group_0_binding_0.view[1][0], _group_0_binding_0.view[1][1], _group_0_binding_0.view[1][2]), vec3(_group_0_binding_0.view[2][0], _group_0_binding_0.view[2][1], _group_0_binding_0.view[2][2]))) * vec3(_expr50[0], _expr50[1], _expr50[2]))).uv;
|
||||
gl_Position = VertexOutput(_expr24, (transpose(mat3x3(_group_0_binding_0.view[0].xyz, _group_0_binding_0.view[1].xyz, _group_0_binding_0.view[2].xyz)) * (_group_0_binding_0.proj_inv * _expr24).xyz)).position;
|
||||
_vs2fs_location0 = VertexOutput(_expr24, (transpose(mat3x3(_group_0_binding_0.view[0].xyz, _group_0_binding_0.view[1].xyz, _group_0_binding_0.view[2].xyz)) * (_group_0_binding_0.proj_inv * _expr24).xyz)).uv;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,7 @@ vertex vs_mainOutput vs_main(
|
||||
tmp1_ = static_cast<int>(vertex_index) / 2;
|
||||
tmp2_ = static_cast<int>(vertex_index) & 1;
|
||||
metal::float4 _e24 = metal::float4((static_cast<float>(tmp1_) * 4.0) - 1.0, (static_cast<float>(tmp2_) * 4.0) - 1.0, 0.0, 1.0);
|
||||
metal::float4 _e50 = r_data.proj_inv * _e24;
|
||||
const auto _tmp = VertexOutput {_e24, metal::transpose(metal::float3x3(metal::float3(r_data.view[0].x, r_data.view[0].y, r_data.view[0].z), metal::float3(r_data.view[1].x, r_data.view[1].y, r_data.view[1].z), metal::float3(r_data.view[2].x, r_data.view[2].y, r_data.view[2].z))) * metal::float3(_e50.x, _e50.y, _e50.z)};
|
||||
const auto _tmp = VertexOutput {_e24, metal::transpose(metal::float3x3(r_data.view[0].xyz, r_data.view[1].xyz, r_data.view[2].xyz)) * (r_data.proj_inv * _e24).xyz};
|
||||
return vs_mainOutput { _tmp.position, _tmp.uv };
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: rspirv
|
||||
; Bound: 105
|
||||
; Bound: 93
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %36 "vs_main" %29 %32 %34
|
||||
OpEntryPoint Fragment %97 "fs_main" %90 %93 %96
|
||||
OpExecutionMode %97 OriginUpperLeft
|
||||
OpEntryPoint Fragment %85 "fs_main" %78 %81 %84
|
||||
OpExecutionMode %85 OriginUpperLeft
|
||||
OpMemberDecorate %12 0 Offset 0
|
||||
OpMemberDecorate %12 1 Offset 16
|
||||
OpDecorate %14 Block
|
||||
@ -26,9 +26,9 @@ OpDecorate %23 Binding 2
|
||||
OpDecorate %29 BuiltIn VertexIndex
|
||||
OpDecorate %32 BuiltIn Position
|
||||
OpDecorate %34 Location 0
|
||||
OpDecorate %90 BuiltIn FragCoord
|
||||
OpDecorate %93 Location 0
|
||||
OpDecorate %96 Location 0
|
||||
OpDecorate %78 BuiltIn FragCoord
|
||||
OpDecorate %81 Location 0
|
||||
OpDecorate %84 Location 0
|
||||
%2 = OpTypeVoid
|
||||
%4 = OpTypeInt 32 1
|
||||
%3 = OpConstant %4 2
|
||||
@ -61,13 +61,13 @@ OpDecorate %96 Location 0
|
||||
%34 = OpVariable %35 Output
|
||||
%37 = OpTypeFunction %2
|
||||
%52 = OpTypePointer Uniform %13
|
||||
%76 = OpConstant %4 0
|
||||
%91 = OpTypePointer Input %10
|
||||
%90 = OpVariable %91 Input
|
||||
%94 = OpTypePointer Input %11
|
||||
%93 = OpVariable %94 Input
|
||||
%96 = OpVariable %33 Output
|
||||
%102 = OpTypeSampledImage %17
|
||||
%67 = OpConstant %4 0
|
||||
%79 = OpTypePointer Input %10
|
||||
%78 = OpVariable %79 Input
|
||||
%82 = OpTypePointer Input %11
|
||||
%81 = OpVariable %82 Input
|
||||
%84 = OpVariable %33 Output
|
||||
%90 = OpTypeSampledImage %17
|
||||
%36 = OpFunction %2 None %37
|
||||
%28 = OpLabel
|
||||
%25 = OpVariable %26 Function
|
||||
@ -93,53 +93,41 @@ OpStore %27 %42
|
||||
%53 = OpAccessChain %52 %19 %5
|
||||
%54 = OpLoad %13 %53
|
||||
%55 = OpCompositeExtract %10 %54 0
|
||||
%56 = OpCompositeExtract %7 %55 0
|
||||
%57 = OpCompositeExtract %7 %55 1
|
||||
%58 = OpCompositeExtract %7 %55 2
|
||||
%59 = OpCompositeConstruct %11 %56 %57 %58
|
||||
%60 = OpAccessChain %52 %19 %5
|
||||
%61 = OpLoad %13 %60
|
||||
%62 = OpCompositeExtract %10 %61 1
|
||||
%63 = OpCompositeExtract %7 %62 0
|
||||
%64 = OpCompositeExtract %7 %62 1
|
||||
%65 = OpCompositeExtract %7 %62 2
|
||||
%66 = OpCompositeConstruct %11 %63 %64 %65
|
||||
%67 = OpAccessChain %52 %19 %5
|
||||
%68 = OpLoad %13 %67
|
||||
%69 = OpCompositeExtract %10 %68 2
|
||||
%70 = OpCompositeExtract %7 %69 0
|
||||
%71 = OpCompositeExtract %7 %69 1
|
||||
%72 = OpCompositeExtract %7 %69 2
|
||||
%73 = OpCompositeConstruct %11 %70 %71 %72
|
||||
%74 = OpCompositeConstruct %16 %59 %66 %73
|
||||
%75 = OpTranspose %16 %74
|
||||
%77 = OpAccessChain %52 %19 %76
|
||||
%78 = OpLoad %13 %77
|
||||
%79 = OpMatrixTimesVector %10 %78 %51
|
||||
%80 = OpCompositeExtract %7 %79 0
|
||||
%81 = OpCompositeExtract %7 %79 1
|
||||
%82 = OpCompositeExtract %7 %79 2
|
||||
%83 = OpCompositeConstruct %11 %80 %81 %82
|
||||
%84 = OpMatrixTimesVector %11 %75 %83
|
||||
%85 = OpCompositeConstruct %12 %51 %84
|
||||
%86 = OpCompositeExtract %10 %85 0
|
||||
OpStore %32 %86
|
||||
%87 = OpCompositeExtract %11 %85 1
|
||||
OpStore %34 %87
|
||||
%56 = OpVectorShuffle %11 %55 %55 0 1 2
|
||||
%57 = OpAccessChain %52 %19 %5
|
||||
%58 = OpLoad %13 %57
|
||||
%59 = OpCompositeExtract %10 %58 1
|
||||
%60 = OpVectorShuffle %11 %59 %59 0 1 2
|
||||
%61 = OpAccessChain %52 %19 %5
|
||||
%62 = OpLoad %13 %61
|
||||
%63 = OpCompositeExtract %10 %62 2
|
||||
%64 = OpVectorShuffle %11 %63 %63 0 1 2
|
||||
%65 = OpCompositeConstruct %16 %56 %60 %64
|
||||
%66 = OpTranspose %16 %65
|
||||
%68 = OpAccessChain %52 %19 %67
|
||||
%69 = OpLoad %13 %68
|
||||
%70 = OpMatrixTimesVector %10 %69 %51
|
||||
%71 = OpVectorShuffle %11 %70 %70 0 1 2
|
||||
%72 = OpMatrixTimesVector %11 %66 %71
|
||||
%73 = OpCompositeConstruct %12 %51 %72
|
||||
%74 = OpCompositeExtract %10 %73 0
|
||||
OpStore %32 %74
|
||||
%75 = OpCompositeExtract %11 %73 1
|
||||
OpStore %34 %75
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%97 = OpFunction %2 None %37
|
||||
%85 = OpFunction %2 None %37
|
||||
%76 = OpLabel
|
||||
%80 = OpLoad %10 %78
|
||||
%83 = OpLoad %11 %81
|
||||
%77 = OpCompositeConstruct %12 %80 %83
|
||||
%86 = OpLoad %17 %21
|
||||
%87 = OpLoad %18 %23
|
||||
OpBranch %88
|
||||
%88 = OpLabel
|
||||
%92 = OpLoad %10 %90
|
||||
%95 = OpLoad %11 %93
|
||||
%89 = OpCompositeConstruct %12 %92 %95
|
||||
%98 = OpLoad %17 %21
|
||||
%99 = OpLoad %18 %23
|
||||
OpBranch %100
|
||||
%100 = OpLabel
|
||||
%101 = OpCompositeExtract %11 %89 1
|
||||
%103 = OpSampledImage %102 %98 %99
|
||||
%104 = OpImageSampleImplicitLod %10 %103 %101
|
||||
OpStore %96 %104
|
||||
%89 = OpCompositeExtract %11 %77 1
|
||||
%91 = OpSampledImage %90 %86 %87
|
||||
%92 = OpImageSampleImplicitLod %10 %91 %89
|
||||
OpStore %84 %92
|
||||
OpReturn
|
||||
OpFunctionEnd
|
Loading…
Reference in New Issue
Block a user