[naga spv-out] Avoid undefined behaviour for integer division and modulo

Integer division or modulo is undefined behaviour in SPIR-V when the
divisor is zero, or when the dividend is the most negative number
representable by the result type and the divisor is negative one.

This patch makes us avoid this undefined behaviour and instead ensures
we adhere to the WGSL spec in these cases: for divisions the
expression evaluates to the value of the dividend, and for modulos the
expression evaluates to zero.

Similarily to how we handle these cases for the MSL and HLSL backends,
prior to emitting each function we emit code for any helper functions
required by that function's expressions. In this case that is helper
functions for integer division and modulo. Then, when emitting the
actual function's body, if we encounter an expression which needs
wrapped we instead emit a function call to the helper.
This commit is contained in:
Jamie Nicol
2025-01-27 15:43:45 +00:00
committed by Jim Blandy
parent b6186ba332
commit 6cf4b710b8
9 changed files with 2769 additions and 2240 deletions

View File

@@ -4,7 +4,8 @@ Implementations for `BlockContext` methods.
use super::{
index::BoundsCheckResult, selection::Selection, Block, BlockContext, Dimension, Error,
Instruction, LocalType, LookupType, NumericType, ResultMember, Writer, WriterFlags,
Instruction, LocalType, LookupType, NumericType, ResultMember, WrappedFunction, Writer,
WriterFlags,
};
use crate::{arena::Handle, proc::index::GuardedIndex, Statement};
use spirv::Word;
@@ -578,201 +579,227 @@ impl BlockContext<'_> {
let id = self.gen_id();
let left_id = self.cached[left];
let right_id = self.cached[right];
let left_type_id = self.get_expression_type_id(&self.fun_info[left].ty);
let right_type_id = self.get_expression_type_id(&self.fun_info[right].ty);
let left_ty_inner = self.fun_info[left].ty.inner_with(&self.ir_module.types);
let right_ty_inner = self.fun_info[right].ty.inner_with(&self.ir_module.types);
if let Some(function_id) =
self.writer
.wrapped_functions
.get(&WrappedFunction::BinaryOp {
op,
left_type_id,
right_type_id,
})
{
block.body.push(Instruction::function_call(
result_type_id,
id,
*function_id,
&[left_id, right_id],
));
} else {
let left_ty_inner = self.fun_info[left].ty.inner_with(&self.ir_module.types);
let right_ty_inner = self.fun_info[right].ty.inner_with(&self.ir_module.types);
let left_dimension = get_dimension(left_ty_inner);
let right_dimension = get_dimension(right_ty_inner);
let left_dimension = get_dimension(left_ty_inner);
let right_dimension = get_dimension(right_ty_inner);
let mut reverse_operands = false;
let mut reverse_operands = false;
let spirv_op = match op {
crate::BinaryOperator::Add => match *left_ty_inner {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
crate::ScalarKind::Float => spirv::Op::FAdd,
_ => spirv::Op::IAdd,
},
crate::TypeInner::Matrix {
columns,
rows,
scalar,
} => {
self.write_matrix_matrix_column_op(
block,
id,
result_type_id,
left_id,
right_id,
let spirv_op = match op {
crate::BinaryOperator::Add => match *left_ty_inner {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
crate::ScalarKind::Float => spirv::Op::FAdd,
_ => spirv::Op::IAdd,
},
crate::TypeInner::Matrix {
columns,
rows,
scalar.width,
spirv::Op::FAdd,
);
scalar,
} => {
self.write_matrix_matrix_column_op(
block,
id,
result_type_id,
left_id,
right_id,
columns,
rows,
scalar.width,
spirv::Op::FAdd,
);
self.cached[expr_handle] = id;
return Ok(());
}
_ => unimplemented!(),
},
crate::BinaryOperator::Subtract => match *left_ty_inner {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
crate::ScalarKind::Float => spirv::Op::FSub,
_ => spirv::Op::ISub,
self.cached[expr_handle] = id;
return Ok(());
}
_ => unimplemented!(),
},
crate::TypeInner::Matrix {
columns,
rows,
scalar,
} => {
self.write_matrix_matrix_column_op(
block,
id,
result_type_id,
left_id,
right_id,
crate::BinaryOperator::Subtract => match *left_ty_inner {
crate::TypeInner::Scalar(scalar)
| crate::TypeInner::Vector { scalar, .. } => match scalar.kind {
crate::ScalarKind::Float => spirv::Op::FSub,
_ => spirv::Op::ISub,
},
crate::TypeInner::Matrix {
columns,
rows,
scalar.width,
spirv::Op::FSub,
);
scalar,
} => {
self.write_matrix_matrix_column_op(
block,
id,
result_type_id,
left_id,
right_id,
columns,
rows,
scalar.width,
spirv::Op::FSub,
);
self.cached[expr_handle] = id;
return Ok(());
}
_ => unimplemented!(),
},
crate::BinaryOperator::Multiply => match (left_dimension, right_dimension) {
(Dimension::Scalar, Dimension::Vector) => {
self.write_vector_scalar_mult(
block,
id,
result_type_id,
right_id,
left_id,
right_ty_inner,
);
self.cached[expr_handle] = id;
return Ok(());
}
_ => unimplemented!(),
},
crate::BinaryOperator::Multiply => {
match (left_dimension, right_dimension) {
(Dimension::Scalar, Dimension::Vector) => {
self.write_vector_scalar_mult(
block,
id,
result_type_id,
right_id,
left_id,
right_ty_inner,
);
self.cached[expr_handle] = id;
return Ok(());
}
(Dimension::Vector, Dimension::Scalar) => {
self.write_vector_scalar_mult(
block,
id,
result_type_id,
left_id,
right_id,
left_ty_inner,
);
self.cached[expr_handle] = id;
return Ok(());
}
(Dimension::Vector, Dimension::Scalar) => {
self.write_vector_scalar_mult(
block,
id,
result_type_id,
left_id,
right_id,
left_ty_inner,
);
self.cached[expr_handle] = id;
return Ok(());
self.cached[expr_handle] = id;
return Ok(());
}
(Dimension::Vector, Dimension::Matrix) => {
spirv::Op::VectorTimesMatrix
}
(Dimension::Matrix, Dimension::Scalar) => {
spirv::Op::MatrixTimesScalar
}
(Dimension::Scalar, Dimension::Matrix) => {
reverse_operands = true;
spirv::Op::MatrixTimesScalar
}
(Dimension::Matrix, Dimension::Vector) => {
spirv::Op::MatrixTimesVector
}
(Dimension::Matrix, Dimension::Matrix) => {
spirv::Op::MatrixTimesMatrix
}
(Dimension::Vector, Dimension::Vector)
| (Dimension::Scalar, Dimension::Scalar)
if left_ty_inner.scalar_kind()
== Some(crate::ScalarKind::Float) =>
{
spirv::Op::FMul
}
(Dimension::Vector, Dimension::Vector)
| (Dimension::Scalar, Dimension::Scalar) => spirv::Op::IMul,
}
}
(Dimension::Vector, Dimension::Matrix) => spirv::Op::VectorTimesMatrix,
(Dimension::Matrix, Dimension::Scalar) => spirv::Op::MatrixTimesScalar,
(Dimension::Scalar, Dimension::Matrix) => {
reverse_operands = true;
spirv::Op::MatrixTimesScalar
}
(Dimension::Matrix, Dimension::Vector) => spirv::Op::MatrixTimesVector,
(Dimension::Matrix, Dimension::Matrix) => spirv::Op::MatrixTimesMatrix,
(Dimension::Vector, Dimension::Vector)
| (Dimension::Scalar, Dimension::Scalar)
if left_ty_inner.scalar_kind() == Some(crate::ScalarKind::Float) =>
{
spirv::Op::FMul
}
(Dimension::Vector, Dimension::Vector)
| (Dimension::Scalar, Dimension::Scalar) => spirv::Op::IMul,
},
crate::BinaryOperator::Divide => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SDiv,
Some(crate::ScalarKind::Uint) => spirv::Op::UDiv,
Some(crate::ScalarKind::Float) => spirv::Op::FDiv,
_ => unimplemented!(),
},
crate::BinaryOperator::Modulo => match left_ty_inner.scalar_kind() {
// TODO: handle undefined behavior
// if right == 0 return 0
// if left == min(type_of(left)) && right == -1 return 0
Some(crate::ScalarKind::Sint) => spirv::Op::SRem,
// TODO: handle undefined behavior
// if right == 0 return 0
Some(crate::ScalarKind::Uint) => spirv::Op::UMod,
// TODO: handle undefined behavior
// if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798
Some(crate::ScalarKind::Float) => spirv::Op::FRem,
_ => unimplemented!(),
},
crate::BinaryOperator::Equal => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => {
spirv::Op::IEqual
}
Some(crate::ScalarKind::Float) => spirv::Op::FOrdEqual,
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::NotEqual => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => {
spirv::Op::INotEqual
}
Some(crate::ScalarKind::Float) => spirv::Op::FOrdNotEqual,
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalNotEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::Less => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SLessThan,
Some(crate::ScalarKind::Uint) => spirv::Op::ULessThan,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThan,
_ => unimplemented!(),
},
crate::BinaryOperator::LessEqual => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SLessThanEqual,
Some(crate::ScalarKind::Uint) => spirv::Op::ULessThanEqual,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThanEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::Greater => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThan,
Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThan,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThan,
_ => unimplemented!(),
},
crate::BinaryOperator::GreaterEqual => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThanEqual,
Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThanEqual,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThanEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::And => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalAnd,
_ => spirv::Op::BitwiseAnd,
},
crate::BinaryOperator::ExclusiveOr => spirv::Op::BitwiseXor,
crate::BinaryOperator::InclusiveOr => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalOr,
_ => spirv::Op::BitwiseOr,
},
crate::BinaryOperator::LogicalAnd => spirv::Op::LogicalAnd,
crate::BinaryOperator::LogicalOr => spirv::Op::LogicalOr,
crate::BinaryOperator::ShiftLeft => spirv::Op::ShiftLeftLogical,
crate::BinaryOperator::ShiftRight => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::ShiftRightArithmetic,
Some(crate::ScalarKind::Uint) => spirv::Op::ShiftRightLogical,
_ => unimplemented!(),
},
};
crate::BinaryOperator::Divide => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SDiv,
Some(crate::ScalarKind::Uint) => spirv::Op::UDiv,
Some(crate::ScalarKind::Float) => spirv::Op::FDiv,
_ => unimplemented!(),
},
crate::BinaryOperator::Modulo => match left_ty_inner.scalar_kind() {
// TODO: handle undefined behavior
// if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798
Some(crate::ScalarKind::Float) => spirv::Op::FRem,
Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => {
unreachable!("Should have been handled by wrapped function")
}
_ => unimplemented!(),
},
crate::BinaryOperator::Equal => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => {
spirv::Op::IEqual
}
Some(crate::ScalarKind::Float) => spirv::Op::FOrdEqual,
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::NotEqual => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => {
spirv::Op::INotEqual
}
Some(crate::ScalarKind::Float) => spirv::Op::FOrdNotEqual,
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalNotEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::Less => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SLessThan,
Some(crate::ScalarKind::Uint) => spirv::Op::ULessThan,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThan,
_ => unimplemented!(),
},
crate::BinaryOperator::LessEqual => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SLessThanEqual,
Some(crate::ScalarKind::Uint) => spirv::Op::ULessThanEqual,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThanEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::Greater => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThan,
Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThan,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThan,
_ => unimplemented!(),
},
crate::BinaryOperator::GreaterEqual => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThanEqual,
Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThanEqual,
Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThanEqual,
_ => unimplemented!(),
},
crate::BinaryOperator::And => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalAnd,
_ => spirv::Op::BitwiseAnd,
},
crate::BinaryOperator::ExclusiveOr => spirv::Op::BitwiseXor,
crate::BinaryOperator::InclusiveOr => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Bool) => spirv::Op::LogicalOr,
_ => spirv::Op::BitwiseOr,
},
crate::BinaryOperator::LogicalAnd => spirv::Op::LogicalAnd,
crate::BinaryOperator::LogicalOr => spirv::Op::LogicalOr,
crate::BinaryOperator::ShiftLeft => spirv::Op::ShiftLeftLogical,
crate::BinaryOperator::ShiftRight => match left_ty_inner.scalar_kind() {
Some(crate::ScalarKind::Sint) => spirv::Op::ShiftRightArithmetic,
Some(crate::ScalarKind::Uint) => spirv::Op::ShiftRightLogical,
_ => unimplemented!(),
},
};
block.body.push(Instruction::binary(
spirv_op,
result_type_id,
id,
if reverse_operands { right_id } else { left_id },
if reverse_operands { left_id } else { right_id },
));
block.body.push(Instruction::binary(
spirv_op,
result_type_id,
id,
if reverse_operands { right_id } else { left_id },
if reverse_operands { left_id } else { right_id },
));
}
id
}
crate::Expression::Math {

View File

@@ -302,6 +302,18 @@ impl NumericType {
_ => None,
}
}
const fn with_scalar(self, scalar: crate::Scalar) -> Self {
match self {
NumericType::Scalar(_) => NumericType::Scalar(scalar),
NumericType::Vector { size, .. } => NumericType::Vector { size, scalar },
NumericType::Matrix { columns, rows, .. } => NumericType::Matrix {
columns,
rows,
scalar,
},
}
}
}
/// A SPIR-V type constructed during code generation.
@@ -475,6 +487,18 @@ enum Dimension {
Matrix,
}
/// Key used to look up an operation which we have wrapped in a helper
/// function, which should be called instead of directly emitting code
/// for the expression. See [`Writer::wrapped_functions`].
#[derive(Debug, Eq, PartialEq, Hash)]
enum WrappedFunction {
BinaryOp {
op: crate::BinaryOperator,
left_type_id: Word,
right_type_id: Word,
},
}
/// A map from evaluated [`Expression`](crate::Expression)s to their SPIR-V ids.
///
/// When we emit code to evaluate a given `Expression`, we record the
@@ -752,6 +776,10 @@ pub struct Writer {
lookup_type: crate::FastHashMap<LookupType, Word>,
lookup_function: crate::FastHashMap<Handle<crate::Function>, Word>,
lookup_function_type: crate::FastHashMap<LookupFunctionType, Word>,
/// Operations which have been wrapped in a helper function. The value is
/// the ID of the function, which should be called instead of emitting code
/// for the operation directly.
wrapped_functions: crate::FastHashMap<WrappedFunction, Word>,
/// Indexed by const-expression handle indexes
constant_ids: HandleVec<crate::Expression, Word>,
cached_constants: crate::FastHashMap<CachedConstant, Word>,

View File

@@ -8,7 +8,7 @@ use super::{
};
use crate::{
arena::{Handle, HandleVec, UniqueArena},
back::spv::BindingInfo,
back::spv::{BindingInfo, WrappedFunction},
proc::{Alignment, TypeResolution},
valid::{FunctionInfo, ModuleInfo},
};
@@ -74,6 +74,7 @@ impl Writer {
lookup_type: crate::FastHashMap::default(),
lookup_function: crate::FastHashMap::default(),
lookup_function_type: crate::FastHashMap::default(),
wrapped_functions: crate::FastHashMap::default(),
constant_ids: HandleVec::new(),
cached_constants: crate::FastHashMap::default(),
global_variables: HandleVec::new(),
@@ -127,6 +128,7 @@ impl Writer {
lookup_type: take(&mut self.lookup_type).recycle(),
lookup_function: take(&mut self.lookup_function).recycle(),
lookup_function_type: take(&mut self.lookup_function_type).recycle(),
wrapped_functions: take(&mut self.wrapped_functions).recycle(),
constant_ids: take(&mut self.constant_ids).recycle(),
cached_constants: take(&mut self.cached_constants).recycle(),
global_variables: take(&mut self.global_variables).recycle(),
@@ -305,6 +307,221 @@ impl Writer {
.push(Instruction::decorate(id, decoration, operands));
}
/// Emits code for any wrapper functions required by the expressions in ir_function.
/// The IDs of any emitted functions will be stored in [`Self::wrapped_functions`].
fn write_wrapped_functions(
&mut self,
ir_function: &crate::Function,
info: &FunctionInfo,
ir_module: &crate::Module,
) -> Result<(), Error> {
log::trace!("Generating wrapped functions for {:?}", ir_function.name);
for (expr_handle, expr) in ir_function.expressions.iter() {
match *expr {
crate::Expression::Binary { op, left, right } => {
let expr_ty = info[expr_handle].ty.inner_with(&ir_module.types);
let Some(numeric_type) = NumericType::from_inner(expr_ty) else {
continue;
};
match (op, expr_ty.scalar()) {
// Division and modulo are undefined behaviour when the dividend is the
// minimum representable value and the divisor is negative one, or when
// the divisor is zero. These wrapped functions override the divisor to
// one in these cases, matching the WGSL spec.
(
crate::BinaryOperator::Divide | crate::BinaryOperator::Modulo,
Some(
scalar @ crate::Scalar {
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
..
},
),
) => {
let return_type_id = self.get_expression_type_id(&info[expr_handle].ty);
let left_type_id = self.get_expression_type_id(&info[left].ty);
let right_type_id = self.get_expression_type_id(&info[right].ty);
let wrapped = WrappedFunction::BinaryOp {
op,
left_type_id,
right_type_id,
};
let function_id = *match self.wrapped_functions.entry(wrapped) {
Entry::Occupied(_) => continue,
Entry::Vacant(e) => e.insert(self.id_gen.next()),
};
if self.flags.contains(WriterFlags::DEBUG) {
let function_name = match op {
crate::BinaryOperator::Divide => "naga_div",
crate::BinaryOperator::Modulo => "naga_mod",
_ => unreachable!(),
};
self.debugs
.push(Instruction::name(function_id, function_name));
}
let mut function = Function::default();
let function_type_id = self.get_function_type(LookupFunctionType {
parameter_type_ids: vec![left_type_id, right_type_id],
return_type_id,
});
function.signature = Some(Instruction::function(
return_type_id,
function_id,
spirv::FunctionControl::empty(),
function_type_id,
));
let lhs_id = self.id_gen.next();
let rhs_id = self.id_gen.next();
if self.flags.contains(WriterFlags::DEBUG) {
self.debugs.push(Instruction::name(lhs_id, "lhs"));
self.debugs.push(Instruction::name(rhs_id, "rhs"));
}
let left_par = Instruction::function_parameter(left_type_id, lhs_id);
let right_par = Instruction::function_parameter(right_type_id, rhs_id);
for instruction in [left_par, right_par] {
function.parameters.push(FunctionArgument {
instruction,
handle_id: 0,
});
}
let label_id = self.id_gen.next();
let mut block = Block::new(label_id);
let bool_type = numeric_type.with_scalar(crate::Scalar::BOOL);
let bool_type_id =
self.get_type_id(LookupType::Local(LocalType::Numeric(bool_type)));
let maybe_splat_const = |writer: &mut Self, const_id| match numeric_type
{
NumericType::Scalar(_) => const_id,
NumericType::Vector { size, .. } => {
let constituent_ids = [const_id; crate::VectorSize::MAX];
writer.get_constant_composite(
LookupType::Local(LocalType::Numeric(numeric_type)),
&constituent_ids[..size as usize],
)
}
NumericType::Matrix { .. } => unreachable!(),
};
let const_zero_id = self.get_constant_scalar_with(0, scalar)?;
let composite_zero_id = maybe_splat_const(self, const_zero_id);
let rhs_eq_zero_id = self.id_gen.next();
block.body.push(Instruction::binary(
spirv::Op::IEqual,
bool_type_id,
rhs_eq_zero_id,
rhs_id,
composite_zero_id,
));
let divisor_selector_id = match scalar.kind {
crate::ScalarKind::Sint => {
let (const_min_id, const_neg_one_id) = match scalar.width {
4 => Ok((
self.get_constant_scalar(crate::Literal::I32(i32::MIN)),
self.get_constant_scalar(crate::Literal::I32(-1i32)),
)),
8 => Ok((
self.get_constant_scalar(crate::Literal::I64(i64::MIN)),
self.get_constant_scalar(crate::Literal::I64(-1i64)),
)),
_ => Err(Error::Validation("Unexpected scalar width")),
}?;
let composite_min_id = maybe_splat_const(self, const_min_id);
let composite_neg_one_id =
maybe_splat_const(self, const_neg_one_id);
let lhs_eq_int_min_id = self.id_gen.next();
block.body.push(Instruction::binary(
spirv::Op::IEqual,
bool_type_id,
lhs_eq_int_min_id,
lhs_id,
composite_min_id,
));
let rhs_eq_neg_one_id = self.id_gen.next();
block.body.push(Instruction::binary(
spirv::Op::IEqual,
bool_type_id,
rhs_eq_neg_one_id,
rhs_id,
composite_neg_one_id,
));
let lhs_eq_int_min_and_rhs_eq_neg_one_id = self.id_gen.next();
block.body.push(Instruction::binary(
spirv::Op::LogicalAnd,
bool_type_id,
lhs_eq_int_min_and_rhs_eq_neg_one_id,
lhs_eq_int_min_id,
rhs_eq_neg_one_id,
));
let rhs_eq_zero_or_lhs_eq_int_min_and_rhs_eq_neg_one_id =
self.id_gen.next();
block.body.push(Instruction::binary(
spirv::Op::LogicalOr,
bool_type_id,
rhs_eq_zero_or_lhs_eq_int_min_and_rhs_eq_neg_one_id,
rhs_eq_zero_id,
lhs_eq_int_min_and_rhs_eq_neg_one_id,
));
rhs_eq_zero_or_lhs_eq_int_min_and_rhs_eq_neg_one_id
}
crate::ScalarKind::Uint => rhs_eq_zero_id,
_ => unreachable!(),
};
let const_one_id = self.get_constant_scalar_with(1, scalar)?;
let composite_one_id = maybe_splat_const(self, const_one_id);
let divisor_id = self.id_gen.next();
block.body.push(Instruction::select(
right_type_id,
divisor_id,
divisor_selector_id,
composite_one_id,
rhs_id,
));
let op = match (op, scalar.kind) {
(crate::BinaryOperator::Divide, crate::ScalarKind::Sint) => {
spirv::Op::SDiv
}
(crate::BinaryOperator::Divide, crate::ScalarKind::Uint) => {
spirv::Op::UDiv
}
(crate::BinaryOperator::Modulo, crate::ScalarKind::Sint) => {
spirv::Op::SRem
}
(crate::BinaryOperator::Modulo, crate::ScalarKind::Uint) => {
spirv::Op::UMod
}
_ => unreachable!(),
};
let return_id = self.id_gen.next();
block.body.push(Instruction::binary(
op,
return_type_id,
return_id,
lhs_id,
divisor_id,
));
function.consume(block, Instruction::return_value(return_id));
function.to_words(&mut self.logical_layout.function_definitions);
Instruction::function_end()
.to_words(&mut self.logical_layout.function_definitions);
}
_ => {}
}
}
_ => {}
}
}
Ok(())
}
fn write_function(
&mut self,
ir_function: &crate::Function,
@@ -313,6 +530,8 @@ impl Writer {
mut interface: Option<FunctionInterface>,
debug_info: &Option<DebugInfoInner>,
) -> Result<Word, Error> {
self.write_wrapped_functions(ir_function, info, ir_module)?;
log::trace!("Generating code for {:?}", ir_function.name);
let mut function = Function::default();

View File

@@ -1,28 +1,34 @@
; SPIR-V
; Version: 1.0
; Generator: rspirv
; Bound: 62
; Bound: 77
OpCapability Shader
OpExtension "SPV_KHR_storage_buffer_storage_class"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %51 "main" %48
OpExecutionMode %51 LocalSize 1 1 1
OpEntryPoint GLCompute %66 "main" %63
OpExecutionMode %66 LocalSize 1 1 1
OpMemberName %5 0 "data"
OpName %5 "PrimeIndices"
OpName %7 "v_indices"
OpName %10 "n_base"
OpName %11 "collatz_iterations"
OpName %17 "n"
OpName %20 "i"
OpName %48 "global_id"
OpName %51 "main"
OpName %9 "naga_mod"
OpName %11 "lhs"
OpName %12 "rhs"
OpName %20 "naga_div"
OpName %21 "lhs"
OpName %22 "rhs"
OpName %28 "n_base"
OpName %29 "collatz_iterations"
OpName %33 "n"
OpName %36 "i"
OpName %63 "global_id"
OpName %66 "main"
OpDecorate %4 ArrayStride 4
OpMemberDecorate %5 0 Offset 0
OpDecorate %5 Block
OpDecorate %7 DescriptorSet 0
OpDecorate %7 Binding 0
OpDecorate %48 BuiltIn GlobalInvocationId
OpDecorate %63 BuiltIn GlobalInvocationId
%2 = OpTypeVoid
%3 = OpTypeInt 32 0
%4 = OpTypeRuntimeArray %3
@@ -30,81 +36,100 @@ OpDecorate %48 BuiltIn GlobalInvocationId
%6 = OpTypeVector %3 3
%8 = OpTypePointer StorageBuffer %5
%7 = OpVariable %8 StorageBuffer
%12 = OpTypeFunction %3 %3
%13 = OpConstant %3 0
%14 = OpConstant %3 1
%15 = OpConstant %3 2
%16 = OpConstant %3 3
%18 = OpTypePointer Function %3
%19 = OpConstantNull %3
%27 = OpTypeBool
%49 = OpTypePointer Input %6
%48 = OpVariable %49 Input
%52 = OpTypeFunction %2
%54 = OpTypePointer StorageBuffer %4
%56 = OpTypePointer StorageBuffer %3
%11 = OpFunction %3 None %12
%10 = OpFunctionParameter %3
%9 = OpLabel
%17 = OpVariable %18 Function %19
%20 = OpVariable %18 Function %13
OpBranch %21
%21 = OpLabel
OpStore %17 %10
OpBranch %22
%22 = OpLabel
OpLoopMerge %23 %25 None
OpBranch %24
%24 = OpLabel
%26 = OpLoad %3 %17
%28 = OpUGreaterThan %27 %26 %14
OpSelectionMerge %29 None
OpBranchConditional %28 %29 %30
%30 = OpLabel
OpBranch %23
%29 = OpLabel
OpBranch %31
%31 = OpLabel
%33 = OpLoad %3 %17
%34 = OpUMod %3 %33 %15
%35 = OpIEqual %27 %34 %13
OpSelectionMerge %36 None
OpBranchConditional %35 %37 %38
%37 = OpLabel
%39 = OpLoad %3 %17
%40 = OpUDiv %3 %39 %15
OpStore %17 %40
OpBranch %36
%38 = OpLabel
%41 = OpLoad %3 %17
%42 = OpIMul %3 %16 %41
%43 = OpIAdd %3 %42 %14
OpStore %17 %43
OpBranch %36
%36 = OpLabel
%44 = OpLoad %3 %20
%45 = OpIAdd %3 %44 %14
OpStore %20 %45
OpBranch %32
%32 = OpLabel
OpBranch %25
%25 = OpLabel
OpBranch %22
%23 = OpLabel
%46 = OpLoad %3 %20
OpReturnValue %46
%10 = OpTypeFunction %3 %3 %3
%14 = OpTypeBool
%15 = OpConstant %3 0
%17 = OpConstant %3 1
%30 = OpTypeFunction %3 %3
%31 = OpConstant %3 2
%32 = OpConstant %3 3
%34 = OpTypePointer Function %3
%35 = OpConstantNull %3
%64 = OpTypePointer Input %6
%63 = OpVariable %64 Input
%67 = OpTypeFunction %2
%69 = OpTypePointer StorageBuffer %4
%71 = OpTypePointer StorageBuffer %3
%9 = OpFunction %3 None %10
%11 = OpFunctionParameter %3
%12 = OpFunctionParameter %3
%13 = OpLabel
%16 = OpIEqual %14 %12 %15
%18 = OpSelect %3 %16 %17 %12
%19 = OpUMod %3 %11 %18
OpReturnValue %19
OpFunctionEnd
%51 = OpFunction %2 None %52
%47 = OpLabel
%50 = OpLoad %6 %48
OpBranch %53
%20 = OpFunction %3 None %10
%21 = OpFunctionParameter %3
%22 = OpFunctionParameter %3
%23 = OpLabel
%24 = OpIEqual %14 %22 %15
%25 = OpSelect %3 %24 %17 %22
%26 = OpUDiv %3 %21 %25
OpReturnValue %26
OpFunctionEnd
%29 = OpFunction %3 None %30
%28 = OpFunctionParameter %3
%27 = OpLabel
%33 = OpVariable %34 Function %35
%36 = OpVariable %34 Function %15
OpBranch %37
%37 = OpLabel
OpStore %33 %28
OpBranch %38
%38 = OpLabel
OpLoopMerge %39 %41 None
OpBranch %40
%40 = OpLabel
%42 = OpLoad %3 %33
%43 = OpUGreaterThan %14 %42 %17
OpSelectionMerge %44 None
OpBranchConditional %43 %44 %45
%45 = OpLabel
OpBranch %39
%44 = OpLabel
OpBranch %46
%46 = OpLabel
%48 = OpLoad %3 %33
%49 = OpFunctionCall %3 %9 %48 %31
%50 = OpIEqual %14 %49 %15
OpSelectionMerge %51 None
OpBranchConditional %50 %52 %53
%52 = OpLabel
%54 = OpLoad %3 %33
%55 = OpFunctionCall %3 %20 %54 %31
OpStore %33 %55
OpBranch %51
%53 = OpLabel
%55 = OpCompositeExtract %3 %50 0
%57 = OpCompositeExtract %3 %50 0
%58 = OpAccessChain %56 %7 %13 %57
%59 = OpLoad %3 %58
%60 = OpFunctionCall %3 %11 %59
%61 = OpAccessChain %56 %7 %13 %55
OpStore %61 %60
%56 = OpLoad %3 %33
%57 = OpIMul %3 %32 %56
%58 = OpIAdd %3 %57 %17
OpStore %33 %58
OpBranch %51
%51 = OpLabel
%59 = OpLoad %3 %36
%60 = OpIAdd %3 %59 %17
OpStore %36 %60
OpBranch %47
%47 = OpLabel
OpBranch %41
%41 = OpLabel
OpBranch %38
%39 = OpLabel
%61 = OpLoad %3 %36
OpReturnValue %61
OpFunctionEnd
%66 = OpFunction %2 None %67
%62 = OpLabel
%65 = OpLoad %6 %63
OpBranch %68
%68 = OpLabel
%70 = OpCompositeExtract %3 %65 0
%72 = OpCompositeExtract %3 %65 0
%73 = OpAccessChain %71 %7 %15 %72
%74 = OpLoad %3 %73
%75 = OpFunctionCall %3 %29 %74
%76 = OpAccessChain %71 %7 %15 %70
OpStore %76 %75
OpReturn
OpFunctionEnd

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
; SPIR-V
; Version: 1.1
; Generator: rspirv
; Bound: 413
; Bound: 528
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %398 "main" %395
OpExecutionMode %398 LocalSize 1 1 1
OpDecorate %395 BuiltIn WorkgroupId
OpEntryPoint GLCompute %513 "main" %510
OpExecutionMode %513 LocalSize 1 1 1
OpDecorate %510 BuiltIn WorkgroupId
%2 = OpTypeVoid
%3 = OpTypeFloat 32
%4 = OpTypeVector %3 4
@@ -38,55 +38,73 @@ OpDecorate %395 BuiltIn WorkgroupId
%31 = OpConstantComposite %7 %30 %30 %30 %30
%32 = OpConstant %3 0.1
%33 = OpConstantComposite %6 %29 %29 %29 %29
%57 = OpTypeFunction %4 %3 %5
%58 = OpConstant %3 2.0
%59 = OpConstantComposite %9 %58 %58
%60 = OpConstant %3 4.0
%61 = OpConstantComposite %9 %60 %60
%62 = OpConstant %3 8.0
%63 = OpConstantComposite %9 %62 %62
%64 = OpConstant %5 2
%65 = OpConstantComposite %6 %64 %64 %64 %64
%78 = OpTypeFunction %9
%79 = OpConstantComposite %9 %17 %17
%80 = OpConstant %3 3.0
%54 = OpTypeFunction %6 %6 %6
%58 = OpConstantComposite %6 %29 %29 %29 %29
%60 = OpConstant %5 -2147483648
%61 = OpConstant %5 -1
%62 = OpConstantComposite %6 %60 %60 %60 %60
%63 = OpConstantComposite %6 %61 %61 %61 %61
%68 = OpConstantComposite %6 %23 %23 %23 %23
%75 = OpTypeFunction %4 %3 %5
%76 = OpConstant %3 2.0
%77 = OpConstantComposite %9 %76 %76
%78 = OpConstant %3 4.0
%79 = OpConstantComposite %9 %78 %78
%80 = OpConstant %3 8.0
%81 = OpConstantComposite %9 %80 %80
%83 = OpTypePointer Function %9
%95 = OpTypeFunction %10 %10
%97 = OpTypeVector %8 3
%98 = OpConstantComposite %10 %19 %19 %19
%100 = OpConstantComposite %10 %17 %17 %17
%104 = OpTypeFunction %2
%105 = OpTypeVector %8 2
%106 = OpConstantComposite %105 %28 %28
%107 = OpConstantComposite %97 %28 %28 %28
%108 = OpConstantComposite %97 %30 %30 %30
%109 = OpConstantComposite %7 %28 %28 %28 %28
%110 = OpConstantComposite %7 %30 %30 %30 %30
%122 = OpConstant %16 1
%123 = OpConstant %16 2
%124 = OpTypeVector %5 2
%125 = OpConstantComposite %124 %23 %23
%126 = OpConstantComposite %124 %64 %64
%127 = OpConstantComposite %15 %123 %123 %123
%128 = OpConstantComposite %15 %122 %122 %122
%129 = OpConstantComposite %4 %58 %58 %58 %58
%130 = OpConstantComposite %4 %17 %17 %17 %17
%131 = OpTypeVector %16 2
%132 = OpConstantComposite %131 %123 %123
%133 = OpConstantComposite %131 %122 %122
%134 = OpConstantNull %11
%135 = OpConstantNull %12
%136 = OpConstantComposite %10 %58 %58 %58
%137 = OpConstantNull %13
%301 = OpConstantNull %14
%303 = OpTypePointer Function %5
%304 = OpConstantNull %5
%306 = OpTypePointer Function %14
%334 = OpTypePointer Function %5
%396 = OpTypePointer Input %15
%395 = OpVariable %396 Input
%399 = OpConstantComposite %10 %17 %17 %17
%82 = OpConstant %5 2
%83 = OpConstantComposite %6 %82 %82 %82 %82
%96 = OpTypeFunction %9
%97 = OpConstantComposite %9 %17 %17
%98 = OpConstant %3 3.0
%99 = OpConstantComposite %9 %98 %98
%101 = OpTypePointer Function %9
%113 = OpTypeFunction %10 %10
%115 = OpTypeVector %8 3
%116 = OpConstantComposite %10 %19 %19 %19
%118 = OpConstantComposite %10 %17 %17 %17
%122 = OpTypeFunction %2
%123 = OpTypeVector %8 2
%124 = OpConstantComposite %123 %28 %28
%125 = OpConstantComposite %115 %28 %28 %28
%126 = OpConstantComposite %115 %30 %30 %30
%127 = OpConstantComposite %7 %28 %28 %28 %28
%128 = OpConstantComposite %7 %30 %30 %30 %30
%139 = OpTypeFunction %5 %5 %5
%151 = OpTypeFunction %16 %16 %16
%155 = OpConstant %16 0
%157 = OpConstant %16 1
%160 = OpTypeVector %5 2
%162 = OpTypeFunction %160 %160 %160
%166 = OpConstantComposite %160 %29 %29
%168 = OpConstantComposite %160 %60 %60
%169 = OpConstantComposite %160 %61 %61
%174 = OpConstantComposite %160 %23 %23
%178 = OpTypeFunction %15 %15 %15
%182 = OpConstantComposite %15 %155 %155 %155
%184 = OpConstantComposite %15 %157 %157 %157
%223 = OpTypeVector %16 2
%225 = OpTypeFunction %223 %223 %223
%229 = OpConstantComposite %223 %155 %155
%231 = OpConstantComposite %223 %157 %157
%243 = OpConstant %16 2
%244 = OpConstantComposite %160 %82 %82
%245 = OpConstantComposite %15 %243 %243 %243
%246 = OpConstantComposite %4 %76 %76 %76 %76
%247 = OpConstantComposite %4 %17 %17 %17 %17
%248 = OpConstantComposite %223 %243 %243
%249 = OpConstantNull %11
%250 = OpConstantNull %12
%251 = OpConstantComposite %10 %76 %76 %76
%252 = OpConstantNull %13
%416 = OpConstantNull %14
%418 = OpTypePointer Function %5
%419 = OpConstantNull %5
%421 = OpTypePointer Function %14
%449 = OpTypePointer Function %5
%511 = OpTypePointer Input %15
%510 = OpVariable %511 Input
%514 = OpConstantComposite %10 %17 %17 %17
%26 = OpFunction %4 None %27
%25 = OpLabel
OpBranch %34
@@ -111,364 +129,483 @@ OpBranch %34
%52 = OpFAdd %4 %51 %43
OpReturnValue %52
OpFunctionEnd
%56 = OpFunction %4 None %57
%54 = OpFunctionParameter %3
%55 = OpFunctionParameter %5
%53 = OpLabel
OpBranch %66
%66 = OpLabel
%67 = OpCompositeConstruct %9 %54 %54
%68 = OpFAdd %9 %59 %67
%69 = OpFSub %9 %68 %61
%70 = OpFDiv %9 %69 %63
%71 = OpCompositeConstruct %6 %55 %55 %55 %55
%72 = OpSRem %6 %71 %65
%73 = OpVectorShuffle %4 %70 %70 0 1 0 1
%74 = OpConvertSToF %4 %72
%75 = OpFAdd %4 %73 %74
OpReturnValue %75
%53 = OpFunction %6 None %54
%55 = OpFunctionParameter %6
%56 = OpFunctionParameter %6
%57 = OpLabel
%59 = OpIEqual %7 %56 %58
%64 = OpIEqual %7 %55 %62
%65 = OpIEqual %7 %56 %63
%66 = OpLogicalAnd %7 %64 %65
%67 = OpLogicalOr %7 %59 %66
%69 = OpSelect %6 %67 %68 %56
%70 = OpSRem %6 %55 %69
OpReturnValue %70
OpFunctionEnd
%77 = OpFunction %9 None %78
%76 = OpLabel
%82 = OpVariable %83 Function %59
%74 = OpFunction %4 None %75
%72 = OpFunctionParameter %3
%73 = OpFunctionParameter %5
%71 = OpLabel
OpBranch %84
%84 = OpLabel
%85 = OpLoad %9 %82
%86 = OpFAdd %9 %85 %79
OpStore %82 %86
%87 = OpLoad %9 %82
%88 = OpFSub %9 %87 %81
OpStore %82 %88
%89 = OpLoad %9 %82
%90 = OpFDiv %9 %89 %61
OpStore %82 %90
%91 = OpLoad %9 %82
OpReturnValue %91
%85 = OpCompositeConstruct %9 %72 %72
%86 = OpFAdd %9 %77 %85
%87 = OpFSub %9 %86 %79
%88 = OpFDiv %9 %87 %81
%89 = OpCompositeConstruct %6 %73 %73 %73 %73
%90 = OpFunctionCall %6 %53 %89 %83
%91 = OpVectorShuffle %4 %88 %88 0 1 0 1
%92 = OpConvertSToF %4 %90
%93 = OpFAdd %4 %91 %92
OpReturnValue %93
OpFunctionEnd
%94 = OpFunction %10 None %95
%93 = OpFunctionParameter %10
%92 = OpLabel
OpBranch %96
%96 = OpLabel
%99 = OpFUnordNotEqual %97 %93 %98
%101 = OpSelect %10 %99 %100 %98
OpReturnValue %101
OpFunctionEnd
%103 = OpFunction %2 None %104
%95 = OpFunction %9 None %96
%94 = OpLabel
%100 = OpVariable %101 Function %77
OpBranch %102
%102 = OpLabel
OpBranch %111
%111 = OpLabel
%112 = OpLogicalNot %8 %28
%113 = OpLogicalNot %105 %106
%114 = OpLogicalOr %8 %28 %30
%115 = OpLogicalAnd %8 %28 %30
%116 = OpLogicalOr %8 %28 %30
%117 = OpLogicalOr %97 %107 %108
%118 = OpLogicalAnd %8 %28 %30
%119 = OpLogicalAnd %7 %109 %110
OpReturn
%103 = OpLoad %9 %100
%104 = OpFAdd %9 %103 %97
OpStore %100 %104
%105 = OpLoad %9 %100
%106 = OpFSub %9 %105 %99
OpStore %100 %106
%107 = OpLoad %9 %100
%108 = OpFDiv %9 %107 %79
OpStore %100 %108
%109 = OpLoad %9 %100
OpReturnValue %109
OpFunctionEnd
%121 = OpFunction %2 None %104
%112 = OpFunction %10 None %113
%111 = OpFunctionParameter %10
%110 = OpLabel
OpBranch %114
%114 = OpLabel
%117 = OpFUnordNotEqual %115 %111 %116
%119 = OpSelect %10 %117 %118 %116
OpReturnValue %119
OpFunctionEnd
%121 = OpFunction %2 None %122
%120 = OpLabel
OpBranch %138
%138 = OpLabel
%139 = OpFNegate %3 %17
%140 = OpSNegate %124 %125
%141 = OpFNegate %9 %79
%142 = OpIAdd %5 %64 %23
%143 = OpIAdd %16 %123 %122
%144 = OpFAdd %3 %58 %17
%145 = OpIAdd %124 %126 %125
%146 = OpIAdd %15 %127 %128
%147 = OpFAdd %4 %129 %130
%148 = OpISub %5 %64 %23
%149 = OpISub %16 %123 %122
%150 = OpFSub %3 %58 %17
%151 = OpISub %124 %126 %125
%152 = OpISub %15 %127 %128
%153 = OpFSub %4 %129 %130
%154 = OpIMul %5 %64 %23
%155 = OpIMul %16 %123 %122
%156 = OpFMul %3 %58 %17
%157 = OpIMul %124 %126 %125
%158 = OpIMul %15 %127 %128
%159 = OpFMul %4 %129 %130
%160 = OpSDiv %5 %64 %23
%161 = OpUDiv %16 %123 %122
%162 = OpFDiv %3 %58 %17
%163 = OpSDiv %124 %126 %125
%164 = OpUDiv %15 %127 %128
%165 = OpFDiv %4 %129 %130
%166 = OpSRem %5 %64 %23
%167 = OpUMod %16 %123 %122
%168 = OpFRem %3 %58 %17
%169 = OpSRem %124 %126 %125
%170 = OpUMod %15 %127 %128
%171 = OpFRem %4 %129 %130
OpBranch %172
%172 = OpLabel
%174 = OpIAdd %124 %126 %125
%175 = OpIAdd %124 %126 %125
%176 = OpIAdd %131 %132 %133
%177 = OpIAdd %131 %132 %133
%178 = OpFAdd %9 %59 %79
%179 = OpFAdd %9 %59 %79
%180 = OpISub %124 %126 %125
%181 = OpISub %124 %126 %125
%182 = OpISub %131 %132 %133
%183 = OpISub %131 %132 %133
%184 = OpFSub %9 %59 %79
%185 = OpFSub %9 %59 %79
%187 = OpCompositeConstruct %124 %23 %23
%186 = OpIMul %124 %126 %187
%189 = OpCompositeConstruct %124 %64 %64
%188 = OpIMul %124 %125 %189
%191 = OpCompositeConstruct %131 %122 %122
%190 = OpIMul %131 %132 %191
%193 = OpCompositeConstruct %131 %123 %123
%192 = OpIMul %131 %133 %193
%194 = OpVectorTimesScalar %9 %59 %17
%195 = OpVectorTimesScalar %9 %79 %58
%196 = OpSDiv %124 %126 %125
%197 = OpSDiv %124 %126 %125
%198 = OpUDiv %131 %132 %133
%199 = OpUDiv %131 %132 %133
%200 = OpFDiv %9 %59 %79
%201 = OpFDiv %9 %59 %79
%202 = OpSRem %124 %126 %125
%203 = OpSRem %124 %126 %125
%204 = OpUMod %131 %132 %133
%205 = OpUMod %131 %132 %133
%206 = OpFRem %9 %59 %79
%207 = OpFRem %9 %59 %79
OpBranch %173
%173 = OpLabel
%209 = OpCompositeExtract %10 %134 0
%210 = OpCompositeExtract %10 %134 0
%211 = OpFAdd %10 %209 %210
%212 = OpCompositeExtract %10 %134 1
%213 = OpCompositeExtract %10 %134 1
%214 = OpFAdd %10 %212 %213
%215 = OpCompositeExtract %10 %134 2
%216 = OpCompositeExtract %10 %134 2
%217 = OpFAdd %10 %215 %216
%208 = OpCompositeConstruct %11 %211 %214 %217
%219 = OpCompositeExtract %10 %134 0
%220 = OpCompositeExtract %10 %134 0
%221 = OpFSub %10 %219 %220
%222 = OpCompositeExtract %10 %134 1
%223 = OpCompositeExtract %10 %134 1
%224 = OpFSub %10 %222 %223
%225 = OpCompositeExtract %10 %134 2
%226 = OpCompositeExtract %10 %134 2
%227 = OpFSub %10 %225 %226
%218 = OpCompositeConstruct %11 %221 %224 %227
%228 = OpMatrixTimesScalar %11 %134 %17
%229 = OpMatrixTimesScalar %11 %134 %58
%230 = OpMatrixTimesVector %10 %135 %130
%231 = OpVectorTimesMatrix %4 %136 %135
%232 = OpMatrixTimesMatrix %11 %135 %137
OpBranch %129
%129 = OpLabel
%130 = OpLogicalNot %8 %28
%131 = OpLogicalNot %123 %124
%132 = OpLogicalOr %8 %28 %30
%133 = OpLogicalAnd %8 %28 %30
%134 = OpLogicalOr %8 %28 %30
%135 = OpLogicalOr %115 %125 %126
%136 = OpLogicalAnd %8 %28 %30
%137 = OpLogicalAnd %7 %127 %128
OpReturn
OpFunctionEnd
%234 = OpFunction %2 None %104
%233 = OpLabel
OpBranch %235
%235 = OpLabel
%236 = OpNot %5 %23
%237 = OpNot %16 %122
%238 = OpNot %124 %125
%239 = OpNot %15 %128
%240 = OpBitwiseOr %5 %64 %23
%241 = OpBitwiseOr %16 %123 %122
%242 = OpBitwiseOr %124 %126 %125
%243 = OpBitwiseOr %15 %127 %128
%244 = OpBitwiseAnd %5 %64 %23
%245 = OpBitwiseAnd %16 %123 %122
%246 = OpBitwiseAnd %124 %126 %125
%247 = OpBitwiseAnd %15 %127 %128
%248 = OpBitwiseXor %5 %64 %23
%249 = OpBitwiseXor %16 %123 %122
%250 = OpBitwiseXor %124 %126 %125
%251 = OpBitwiseXor %15 %127 %128
%252 = OpShiftLeftLogical %5 %64 %122
%253 = OpShiftLeftLogical %16 %123 %122
%254 = OpShiftLeftLogical %124 %126 %133
%255 = OpShiftLeftLogical %15 %127 %128
%256 = OpShiftRightArithmetic %5 %64 %122
%257 = OpShiftRightLogical %16 %123 %122
%258 = OpShiftRightArithmetic %124 %126 %133
%259 = OpShiftRightLogical %15 %127 %128
%138 = OpFunction %5 None %139
%140 = OpFunctionParameter %5
%141 = OpFunctionParameter %5
%142 = OpLabel
%143 = OpIEqual %8 %141 %29
%144 = OpIEqual %8 %140 %60
%145 = OpIEqual %8 %141 %61
%146 = OpLogicalAnd %8 %144 %145
%147 = OpLogicalOr %8 %143 %146
%148 = OpSelect %5 %147 %23 %141
%149 = OpSDiv %5 %140 %148
OpReturnValue %149
OpFunctionEnd
%150 = OpFunction %16 None %151
%152 = OpFunctionParameter %16
%153 = OpFunctionParameter %16
%154 = OpLabel
%156 = OpIEqual %8 %153 %155
%158 = OpSelect %16 %156 %157 %153
%159 = OpUDiv %16 %152 %158
OpReturnValue %159
OpFunctionEnd
%161 = OpFunction %160 None %162
%163 = OpFunctionParameter %160
%164 = OpFunctionParameter %160
%165 = OpLabel
%167 = OpIEqual %123 %164 %166
%170 = OpIEqual %123 %163 %168
%171 = OpIEqual %123 %164 %169
%172 = OpLogicalAnd %123 %170 %171
%173 = OpLogicalOr %123 %167 %172
%175 = OpSelect %160 %173 %174 %164
%176 = OpSDiv %160 %163 %175
OpReturnValue %176
OpFunctionEnd
%177 = OpFunction %15 None %178
%179 = OpFunctionParameter %15
%180 = OpFunctionParameter %15
%181 = OpLabel
%183 = OpIEqual %115 %180 %182
%185 = OpSelect %15 %183 %184 %180
%186 = OpUDiv %15 %179 %185
OpReturnValue %186
OpFunctionEnd
%187 = OpFunction %5 None %139
%188 = OpFunctionParameter %5
%189 = OpFunctionParameter %5
%190 = OpLabel
%191 = OpIEqual %8 %189 %29
%192 = OpIEqual %8 %188 %60
%193 = OpIEqual %8 %189 %61
%194 = OpLogicalAnd %8 %192 %193
%195 = OpLogicalOr %8 %191 %194
%196 = OpSelect %5 %195 %23 %189
%197 = OpSRem %5 %188 %196
OpReturnValue %197
OpFunctionEnd
%198 = OpFunction %16 None %151
%199 = OpFunctionParameter %16
%200 = OpFunctionParameter %16
%201 = OpLabel
%202 = OpIEqual %8 %200 %155
%203 = OpSelect %16 %202 %157 %200
%204 = OpUMod %16 %199 %203
OpReturnValue %204
OpFunctionEnd
%205 = OpFunction %160 None %162
%206 = OpFunctionParameter %160
%207 = OpFunctionParameter %160
%208 = OpLabel
%209 = OpIEqual %123 %207 %166
%210 = OpIEqual %123 %206 %168
%211 = OpIEqual %123 %207 %169
%212 = OpLogicalAnd %123 %210 %211
%213 = OpLogicalOr %123 %209 %212
%214 = OpSelect %160 %213 %174 %207
%215 = OpSRem %160 %206 %214
OpReturnValue %215
OpFunctionEnd
%216 = OpFunction %15 None %178
%217 = OpFunctionParameter %15
%218 = OpFunctionParameter %15
%219 = OpLabel
%220 = OpIEqual %115 %218 %182
%221 = OpSelect %15 %220 %184 %218
%222 = OpUMod %15 %217 %221
OpReturnValue %222
OpFunctionEnd
%224 = OpFunction %223 None %225
%226 = OpFunctionParameter %223
%227 = OpFunctionParameter %223
%228 = OpLabel
%230 = OpIEqual %123 %227 %229
%232 = OpSelect %223 %230 %231 %227
%233 = OpUDiv %223 %226 %232
OpReturnValue %233
OpFunctionEnd
%234 = OpFunction %223 None %225
%235 = OpFunctionParameter %223
%236 = OpFunctionParameter %223
%237 = OpLabel
%238 = OpIEqual %123 %236 %229
%239 = OpSelect %223 %238 %231 %236
%240 = OpUMod %223 %235 %239
OpReturnValue %240
OpFunctionEnd
%242 = OpFunction %2 None %122
%241 = OpLabel
OpBranch %253
%253 = OpLabel
%254 = OpFNegate %3 %17
%255 = OpSNegate %160 %174
%256 = OpFNegate %9 %97
%257 = OpIAdd %5 %82 %23
%258 = OpIAdd %16 %243 %157
%259 = OpFAdd %3 %76 %17
%260 = OpIAdd %160 %244 %174
%261 = OpIAdd %15 %245 %184
%262 = OpFAdd %4 %246 %247
%263 = OpISub %5 %82 %23
%264 = OpISub %16 %243 %157
%265 = OpFSub %3 %76 %17
%266 = OpISub %160 %244 %174
%267 = OpISub %15 %245 %184
%268 = OpFSub %4 %246 %247
%269 = OpIMul %5 %82 %23
%270 = OpIMul %16 %243 %157
%271 = OpFMul %3 %76 %17
%272 = OpIMul %160 %244 %174
%273 = OpIMul %15 %245 %184
%274 = OpFMul %4 %246 %247
%275 = OpFunctionCall %5 %138 %82 %23
%276 = OpFunctionCall %16 %150 %243 %157
%277 = OpFDiv %3 %76 %17
%278 = OpFunctionCall %160 %161 %244 %174
%279 = OpFunctionCall %15 %177 %245 %184
%280 = OpFDiv %4 %246 %247
%281 = OpFunctionCall %5 %187 %82 %23
%282 = OpFunctionCall %16 %198 %243 %157
%283 = OpFRem %3 %76 %17
%284 = OpFunctionCall %160 %205 %244 %174
%285 = OpFunctionCall %15 %216 %245 %184
%286 = OpFRem %4 %246 %247
OpBranch %287
%287 = OpLabel
%289 = OpIAdd %160 %244 %174
%290 = OpIAdd %160 %244 %174
%291 = OpIAdd %223 %248 %231
%292 = OpIAdd %223 %248 %231
%293 = OpFAdd %9 %77 %97
%294 = OpFAdd %9 %77 %97
%295 = OpISub %160 %244 %174
%296 = OpISub %160 %244 %174
%297 = OpISub %223 %248 %231
%298 = OpISub %223 %248 %231
%299 = OpFSub %9 %77 %97
%300 = OpFSub %9 %77 %97
%302 = OpCompositeConstruct %160 %23 %23
%301 = OpIMul %160 %244 %302
%304 = OpCompositeConstruct %160 %82 %82
%303 = OpIMul %160 %174 %304
%306 = OpCompositeConstruct %223 %157 %157
%305 = OpIMul %223 %248 %306
%308 = OpCompositeConstruct %223 %243 %243
%307 = OpIMul %223 %231 %308
%309 = OpVectorTimesScalar %9 %77 %17
%310 = OpVectorTimesScalar %9 %97 %76
%311 = OpFunctionCall %160 %161 %244 %174
%312 = OpFunctionCall %160 %161 %244 %174
%313 = OpFunctionCall %223 %224 %248 %231
%314 = OpFunctionCall %223 %224 %248 %231
%315 = OpFDiv %9 %77 %97
%316 = OpFDiv %9 %77 %97
%317 = OpFunctionCall %160 %205 %244 %174
%318 = OpFunctionCall %160 %205 %244 %174
%319 = OpFunctionCall %223 %234 %248 %231
%320 = OpFunctionCall %223 %234 %248 %231
%321 = OpFRem %9 %77 %97
%322 = OpFRem %9 %77 %97
OpBranch %288
%288 = OpLabel
%324 = OpCompositeExtract %10 %249 0
%325 = OpCompositeExtract %10 %249 0
%326 = OpFAdd %10 %324 %325
%327 = OpCompositeExtract %10 %249 1
%328 = OpCompositeExtract %10 %249 1
%329 = OpFAdd %10 %327 %328
%330 = OpCompositeExtract %10 %249 2
%331 = OpCompositeExtract %10 %249 2
%332 = OpFAdd %10 %330 %331
%323 = OpCompositeConstruct %11 %326 %329 %332
%334 = OpCompositeExtract %10 %249 0
%335 = OpCompositeExtract %10 %249 0
%336 = OpFSub %10 %334 %335
%337 = OpCompositeExtract %10 %249 1
%338 = OpCompositeExtract %10 %249 1
%339 = OpFSub %10 %337 %338
%340 = OpCompositeExtract %10 %249 2
%341 = OpCompositeExtract %10 %249 2
%342 = OpFSub %10 %340 %341
%333 = OpCompositeConstruct %11 %336 %339 %342
%343 = OpMatrixTimesScalar %11 %249 %17
%344 = OpMatrixTimesScalar %11 %249 %76
%345 = OpMatrixTimesVector %10 %250 %247
%346 = OpVectorTimesMatrix %4 %251 %250
%347 = OpMatrixTimesMatrix %11 %250 %252
OpReturn
OpFunctionEnd
%261 = OpFunction %2 None %104
%260 = OpLabel
OpBranch %262
%262 = OpLabel
%263 = OpIEqual %8 %64 %23
%264 = OpIEqual %8 %123 %122
%265 = OpFOrdEqual %8 %58 %17
%266 = OpIEqual %105 %126 %125
%267 = OpIEqual %97 %127 %128
%268 = OpFOrdEqual %7 %129 %130
%269 = OpINotEqual %8 %64 %23
%270 = OpINotEqual %8 %123 %122
%271 = OpFOrdNotEqual %8 %58 %17
%272 = OpINotEqual %105 %126 %125
%273 = OpINotEqual %97 %127 %128
%274 = OpFOrdNotEqual %7 %129 %130
%275 = OpSLessThan %8 %64 %23
%276 = OpULessThan %8 %123 %122
%277 = OpFOrdLessThan %8 %58 %17
%278 = OpSLessThan %105 %126 %125
%279 = OpULessThan %97 %127 %128
%280 = OpFOrdLessThan %7 %129 %130
%281 = OpSLessThanEqual %8 %64 %23
%282 = OpULessThanEqual %8 %123 %122
%283 = OpFOrdLessThanEqual %8 %58 %17
%284 = OpSLessThanEqual %105 %126 %125
%285 = OpULessThanEqual %97 %127 %128
%286 = OpFOrdLessThanEqual %7 %129 %130
%287 = OpSGreaterThan %8 %64 %23
%288 = OpUGreaterThan %8 %123 %122
%289 = OpFOrdGreaterThan %8 %58 %17
%290 = OpSGreaterThan %105 %126 %125
%291 = OpUGreaterThan %97 %127 %128
%292 = OpFOrdGreaterThan %7 %129 %130
%293 = OpSGreaterThanEqual %8 %64 %23
%294 = OpUGreaterThanEqual %8 %123 %122
%295 = OpFOrdGreaterThanEqual %8 %58 %17
%296 = OpSGreaterThanEqual %105 %126 %125
%297 = OpUGreaterThanEqual %97 %127 %128
%298 = OpFOrdGreaterThanEqual %7 %129 %130
%349 = OpFunction %2 None %122
%348 = OpLabel
OpBranch %350
%350 = OpLabel
%351 = OpNot %5 %23
%352 = OpNot %16 %157
%353 = OpNot %160 %174
%354 = OpNot %15 %184
%355 = OpBitwiseOr %5 %82 %23
%356 = OpBitwiseOr %16 %243 %157
%357 = OpBitwiseOr %160 %244 %174
%358 = OpBitwiseOr %15 %245 %184
%359 = OpBitwiseAnd %5 %82 %23
%360 = OpBitwiseAnd %16 %243 %157
%361 = OpBitwiseAnd %160 %244 %174
%362 = OpBitwiseAnd %15 %245 %184
%363 = OpBitwiseXor %5 %82 %23
%364 = OpBitwiseXor %16 %243 %157
%365 = OpBitwiseXor %160 %244 %174
%366 = OpBitwiseXor %15 %245 %184
%367 = OpShiftLeftLogical %5 %82 %157
%368 = OpShiftLeftLogical %16 %243 %157
%369 = OpShiftLeftLogical %160 %244 %231
%370 = OpShiftLeftLogical %15 %245 %184
%371 = OpShiftRightArithmetic %5 %82 %157
%372 = OpShiftRightLogical %16 %243 %157
%373 = OpShiftRightArithmetic %160 %244 %231
%374 = OpShiftRightLogical %15 %245 %184
OpReturn
OpFunctionEnd
%300 = OpFunction %2 None %104
%299 = OpLabel
%302 = OpVariable %303 Function %304
%305 = OpVariable %306 Function %301
OpBranch %307
%307 = OpLabel
OpStore %302 %23
%308 = OpLoad %5 %302
%309 = OpIAdd %5 %308 %23
OpStore %302 %309
%310 = OpLoad %5 %302
%311 = OpISub %5 %310 %23
OpStore %302 %311
%312 = OpLoad %5 %302
%313 = OpLoad %5 %302
%314 = OpIMul %5 %313 %312
OpStore %302 %314
%315 = OpLoad %5 %302
%316 = OpLoad %5 %302
%317 = OpSDiv %5 %316 %315
OpStore %302 %317
%318 = OpLoad %5 %302
%319 = OpSRem %5 %318 %23
OpStore %302 %319
%320 = OpLoad %5 %302
%321 = OpBitwiseAnd %5 %320 %29
OpStore %302 %321
%322 = OpLoad %5 %302
%323 = OpBitwiseOr %5 %322 %29
OpStore %302 %323
%324 = OpLoad %5 %302
%325 = OpBitwiseXor %5 %324 %29
OpStore %302 %325
%326 = OpLoad %5 %302
%327 = OpShiftLeftLogical %5 %326 %123
OpStore %302 %327
%328 = OpLoad %5 %302
%329 = OpShiftRightArithmetic %5 %328 %122
OpStore %302 %329
%330 = OpLoad %5 %302
%331 = OpIAdd %5 %330 %23
OpStore %302 %331
%332 = OpLoad %5 %302
%333 = OpISub %5 %332 %23
OpStore %302 %333
%335 = OpAccessChain %334 %305 %122
%336 = OpLoad %5 %335
%337 = OpIAdd %5 %336 %23
%338 = OpAccessChain %334 %305 %122
OpStore %338 %337
%339 = OpAccessChain %334 %305 %122
%340 = OpLoad %5 %339
%341 = OpISub %5 %340 %23
%342 = OpAccessChain %334 %305 %122
OpStore %342 %341
%376 = OpFunction %2 None %122
%375 = OpLabel
OpBranch %377
%377 = OpLabel
%378 = OpIEqual %8 %82 %23
%379 = OpIEqual %8 %243 %157
%380 = OpFOrdEqual %8 %76 %17
%381 = OpIEqual %123 %244 %174
%382 = OpIEqual %115 %245 %184
%383 = OpFOrdEqual %7 %246 %247
%384 = OpINotEqual %8 %82 %23
%385 = OpINotEqual %8 %243 %157
%386 = OpFOrdNotEqual %8 %76 %17
%387 = OpINotEqual %123 %244 %174
%388 = OpINotEqual %115 %245 %184
%389 = OpFOrdNotEqual %7 %246 %247
%390 = OpSLessThan %8 %82 %23
%391 = OpULessThan %8 %243 %157
%392 = OpFOrdLessThan %8 %76 %17
%393 = OpSLessThan %123 %244 %174
%394 = OpULessThan %115 %245 %184
%395 = OpFOrdLessThan %7 %246 %247
%396 = OpSLessThanEqual %8 %82 %23
%397 = OpULessThanEqual %8 %243 %157
%398 = OpFOrdLessThanEqual %8 %76 %17
%399 = OpSLessThanEqual %123 %244 %174
%400 = OpULessThanEqual %115 %245 %184
%401 = OpFOrdLessThanEqual %7 %246 %247
%402 = OpSGreaterThan %8 %82 %23
%403 = OpUGreaterThan %8 %243 %157
%404 = OpFOrdGreaterThan %8 %76 %17
%405 = OpSGreaterThan %123 %244 %174
%406 = OpUGreaterThan %115 %245 %184
%407 = OpFOrdGreaterThan %7 %246 %247
%408 = OpSGreaterThanEqual %8 %82 %23
%409 = OpUGreaterThanEqual %8 %243 %157
%410 = OpFOrdGreaterThanEqual %8 %76 %17
%411 = OpSGreaterThanEqual %123 %244 %174
%412 = OpUGreaterThanEqual %115 %245 %184
%413 = OpFOrdGreaterThanEqual %7 %246 %247
OpReturn
OpFunctionEnd
%344 = OpFunction %2 None %104
%343 = OpLabel
OpBranch %345
%345 = OpLabel
%346 = OpSNegate %5 %23
%347 = OpSNegate %5 %23
%348 = OpSNegate %5 %347
%349 = OpSNegate %5 %23
%350 = OpSNegate %5 %349
%351 = OpSNegate %5 %23
%352 = OpSNegate %5 %351
%353 = OpSNegate %5 %23
%354 = OpSNegate %5 %353
%355 = OpSNegate %5 %354
%356 = OpSNegate %5 %23
%357 = OpSNegate %5 %356
%358 = OpSNegate %5 %357
%359 = OpSNegate %5 %358
%360 = OpSNegate %5 %23
%361 = OpSNegate %5 %360
%362 = OpSNegate %5 %361
%363 = OpSNegate %5 %362
%364 = OpSNegate %5 %363
%365 = OpSNegate %5 %23
%366 = OpSNegate %5 %365
%367 = OpSNegate %5 %366
%368 = OpSNegate %5 %367
%369 = OpSNegate %5 %368
%370 = OpFNegate %3 %17
%371 = OpFNegate %3 %17
%372 = OpFNegate %3 %371
%373 = OpFNegate %3 %17
%374 = OpFNegate %3 %373
%375 = OpFNegate %3 %17
%376 = OpFNegate %3 %375
%377 = OpFNegate %3 %17
%378 = OpFNegate %3 %377
%379 = OpFNegate %3 %378
%380 = OpFNegate %3 %17
%381 = OpFNegate %3 %380
%382 = OpFNegate %3 %381
%383 = OpFNegate %3 %382
%384 = OpFNegate %3 %17
%385 = OpFNegate %3 %384
%386 = OpFNegate %3 %385
%387 = OpFNegate %3 %386
%388 = OpFNegate %3 %387
%389 = OpFNegate %3 %17
%390 = OpFNegate %3 %389
%391 = OpFNegate %3 %390
%392 = OpFNegate %3 %391
%393 = OpFNegate %3 %392
%415 = OpFunction %2 None %122
%414 = OpLabel
%417 = OpVariable %418 Function %419
%420 = OpVariable %421 Function %416
OpBranch %422
%422 = OpLabel
OpStore %417 %23
%423 = OpLoad %5 %417
%424 = OpIAdd %5 %423 %23
OpStore %417 %424
%425 = OpLoad %5 %417
%426 = OpISub %5 %425 %23
OpStore %417 %426
%427 = OpLoad %5 %417
%428 = OpLoad %5 %417
%429 = OpIMul %5 %428 %427
OpStore %417 %429
%430 = OpLoad %5 %417
%431 = OpLoad %5 %417
%432 = OpFunctionCall %5 %138 %431 %430
OpStore %417 %432
%433 = OpLoad %5 %417
%434 = OpFunctionCall %5 %187 %433 %23
OpStore %417 %434
%435 = OpLoad %5 %417
%436 = OpBitwiseAnd %5 %435 %29
OpStore %417 %436
%437 = OpLoad %5 %417
%438 = OpBitwiseOr %5 %437 %29
OpStore %417 %438
%439 = OpLoad %5 %417
%440 = OpBitwiseXor %5 %439 %29
OpStore %417 %440
%441 = OpLoad %5 %417
%442 = OpShiftLeftLogical %5 %441 %243
OpStore %417 %442
%443 = OpLoad %5 %417
%444 = OpShiftRightArithmetic %5 %443 %157
OpStore %417 %444
%445 = OpLoad %5 %417
%446 = OpIAdd %5 %445 %23
OpStore %417 %446
%447 = OpLoad %5 %417
%448 = OpISub %5 %447 %23
OpStore %417 %448
%450 = OpAccessChain %449 %420 %157
%451 = OpLoad %5 %450
%452 = OpIAdd %5 %451 %23
%453 = OpAccessChain %449 %420 %157
OpStore %453 %452
%454 = OpAccessChain %449 %420 %157
%455 = OpLoad %5 %454
%456 = OpISub %5 %455 %23
%457 = OpAccessChain %449 %420 %157
OpStore %457 %456
OpReturn
OpFunctionEnd
%398 = OpFunction %2 None %104
%394 = OpLabel
%397 = OpLoad %15 %395
OpBranch %400
%400 = OpLabel
%401 = OpFunctionCall %4 %26
%402 = OpCompositeExtract %16 %397 0
%403 = OpConvertUToF %3 %402
%404 = OpCompositeExtract %16 %397 1
%405 = OpBitcast %5 %404
%406 = OpFunctionCall %4 %56 %403 %405
%407 = OpFunctionCall %10 %94 %399
%408 = OpFunctionCall %2 %103
%409 = OpFunctionCall %2 %121
%410 = OpFunctionCall %2 %234
%411 = OpFunctionCall %2 %261
%412 = OpFunctionCall %2 %300
%459 = OpFunction %2 None %122
%458 = OpLabel
OpBranch %460
%460 = OpLabel
%461 = OpSNegate %5 %23
%462 = OpSNegate %5 %23
%463 = OpSNegate %5 %462
%464 = OpSNegate %5 %23
%465 = OpSNegate %5 %464
%466 = OpSNegate %5 %23
%467 = OpSNegate %5 %466
%468 = OpSNegate %5 %23
%469 = OpSNegate %5 %468
%470 = OpSNegate %5 %469
%471 = OpSNegate %5 %23
%472 = OpSNegate %5 %471
%473 = OpSNegate %5 %472
%474 = OpSNegate %5 %473
%475 = OpSNegate %5 %23
%476 = OpSNegate %5 %475
%477 = OpSNegate %5 %476
%478 = OpSNegate %5 %477
%479 = OpSNegate %5 %478
%480 = OpSNegate %5 %23
%481 = OpSNegate %5 %480
%482 = OpSNegate %5 %481
%483 = OpSNegate %5 %482
%484 = OpSNegate %5 %483
%485 = OpFNegate %3 %17
%486 = OpFNegate %3 %17
%487 = OpFNegate %3 %486
%488 = OpFNegate %3 %17
%489 = OpFNegate %3 %488
%490 = OpFNegate %3 %17
%491 = OpFNegate %3 %490
%492 = OpFNegate %3 %17
%493 = OpFNegate %3 %492
%494 = OpFNegate %3 %493
%495 = OpFNegate %3 %17
%496 = OpFNegate %3 %495
%497 = OpFNegate %3 %496
%498 = OpFNegate %3 %497
%499 = OpFNegate %3 %17
%500 = OpFNegate %3 %499
%501 = OpFNegate %3 %500
%502 = OpFNegate %3 %501
%503 = OpFNegate %3 %502
%504 = OpFNegate %3 %17
%505 = OpFNegate %3 %504
%506 = OpFNegate %3 %505
%507 = OpFNegate %3 %506
%508 = OpFNegate %3 %507
OpReturn
OpFunctionEnd
%513 = OpFunction %2 None %122
%509 = OpLabel
%512 = OpLoad %15 %510
OpBranch %515
%515 = OpLabel
%516 = OpFunctionCall %4 %26
%517 = OpCompositeExtract %16 %512 0
%518 = OpConvertUToF %3 %517
%519 = OpCompositeExtract %16 %512 1
%520 = OpBitcast %5 %519
%521 = OpFunctionCall %4 %74 %518 %520
%522 = OpFunctionCall %10 %112 %514
%523 = OpFunctionCall %2 %121
%524 = OpFunctionCall %2 %242
%525 = OpFunctionCall %2 %349
%526 = OpFunctionCall %2 %376
%527 = OpFunctionCall %2 %415
OpReturn
OpFunctionEnd

View File

@@ -1,13 +1,13 @@
; SPIR-V
; Version: 1.0
; Generator: rspirv
; Bound: 98
; Bound: 114
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %29 "vs_main" %22 %25 %27
OpEntryPoint Fragment %90 "fs_main" %83 %86 %89
OpExecutionMode %90 OriginUpperLeft
OpEntryPoint Vertex %46 "vs_main" %39 %42 %44
OpEntryPoint Fragment %106 "fs_main" %99 %102 %105
OpExecutionMode %106 OriginUpperLeft
OpMemberDecorate %6 0 Offset 0
OpMemberDecorate %6 1 Offset 16
OpMemberDecorate %8 0 Offset 0
@@ -24,12 +24,12 @@ OpDecorate %17 DescriptorSet 0
OpDecorate %17 Binding 1
OpDecorate %19 DescriptorSet 0
OpDecorate %19 Binding 2
OpDecorate %22 BuiltIn VertexIndex
OpDecorate %25 BuiltIn Position
OpDecorate %27 Location 0
OpDecorate %83 BuiltIn FragCoord
OpDecorate %86 Location 0
OpDecorate %89 Location 0
OpDecorate %39 BuiltIn VertexIndex
OpDecorate %42 BuiltIn Position
OpDecorate %44 Location 0
OpDecorate %99 BuiltIn FragCoord
OpDecorate %102 Location 0
OpDecorate %105 Location 0
%2 = OpTypeVoid
%4 = OpTypeFloat 32
%3 = OpTypeVector %4 4
@@ -49,91 +49,109 @@ OpDecorate %89 Location 0
%17 = OpVariable %18 UniformConstant
%20 = OpTypePointer UniformConstant %13
%19 = OpVariable %20 UniformConstant
%23 = OpTypePointer Input %9
%22 = OpVariable %23 Input
%26 = OpTypePointer Output %3
%25 = OpVariable %26 Output
%28 = OpTypePointer Output %5
%27 = OpVariable %28 Output
%30 = OpTypeFunction %2
%31 = OpTypePointer Uniform %8
%32 = OpConstant %9 0
%34 = OpConstant %10 2
%22 = OpTypeFunction %10 %10 %10
%26 = OpTypeBool
%27 = OpConstant %10 0
%29 = OpConstant %10 -2147483648
%30 = OpConstant %10 -1
%35 = OpConstant %10 1
%36 = OpConstant %4 4.0
%37 = OpConstant %4 1.0
%38 = OpConstant %4 0.0
%40 = OpTypePointer Function %10
%41 = OpConstantNull %10
%43 = OpConstantNull %10
%58 = OpTypePointer Uniform %7
%59 = OpTypePointer Uniform %3
%60 = OpConstant %9 1
%67 = OpConstant %9 2
%84 = OpTypePointer Input %3
%83 = OpVariable %84 Input
%87 = OpTypePointer Input %5
%86 = OpVariable %87 Input
%89 = OpVariable %26 Output
%95 = OpTypeSampledImage %12
%29 = OpFunction %2 None %30
%21 = OpLabel
%39 = OpVariable %40 Function %41
%42 = OpVariable %40 Function %43
%24 = OpLoad %9 %22
%33 = OpAccessChain %31 %14 %32
OpBranch %44
%44 = OpLabel
%45 = OpBitcast %10 %24
%46 = OpSDiv %10 %45 %34
OpStore %39 %46
%47 = OpBitcast %10 %24
%48 = OpBitwiseAnd %10 %47 %35
OpStore %42 %48
%49 = OpLoad %10 %39
%50 = OpConvertSToF %4 %49
%51 = OpFMul %4 %50 %36
%52 = OpFSub %4 %51 %37
%53 = OpLoad %10 %42
%54 = OpConvertSToF %4 %53
%55 = OpFMul %4 %54 %36
%56 = OpFSub %4 %55 %37
%57 = OpCompositeConstruct %3 %52 %56 %38 %37
%61 = OpAccessChain %59 %33 %60 %32
%62 = OpLoad %3 %61
%63 = OpVectorShuffle %5 %62 %62 0 1 2
%64 = OpAccessChain %59 %33 %60 %60
%65 = OpLoad %3 %64
%66 = OpVectorShuffle %5 %65 %65 0 1 2
%68 = OpAccessChain %59 %33 %60 %67
%69 = OpLoad %3 %68
%70 = OpVectorShuffle %5 %69 %69 0 1 2
%71 = OpCompositeConstruct %11 %63 %66 %70
%72 = OpTranspose %11 %71
%73 = OpAccessChain %58 %33 %32
%74 = OpLoad %7 %73
%75 = OpMatrixTimesVector %3 %74 %57
%76 = OpVectorShuffle %5 %75 %75 0 1 2
%77 = OpMatrixTimesVector %5 %72 %76
%78 = OpCompositeConstruct %6 %57 %77
%79 = OpCompositeExtract %3 %78 0
OpStore %25 %79
%80 = OpCompositeExtract %5 %78 1
OpStore %27 %80
%40 = OpTypePointer Input %9
%39 = OpVariable %40 Input
%43 = OpTypePointer Output %3
%42 = OpVariable %43 Output
%45 = OpTypePointer Output %5
%44 = OpVariable %45 Output
%47 = OpTypeFunction %2
%48 = OpTypePointer Uniform %8
%49 = OpConstant %9 0
%51 = OpConstant %10 2
%52 = OpConstant %4 4.0
%53 = OpConstant %4 1.0
%54 = OpConstant %4 0.0
%56 = OpTypePointer Function %10
%57 = OpConstantNull %10
%59 = OpConstantNull %10
%74 = OpTypePointer Uniform %7
%75 = OpTypePointer Uniform %3
%76 = OpConstant %9 1
%83 = OpConstant %9 2
%100 = OpTypePointer Input %3
%99 = OpVariable %100 Input
%103 = OpTypePointer Input %5
%102 = OpVariable %103 Input
%105 = OpVariable %43 Output
%111 = OpTypeSampledImage %12
%21 = OpFunction %10 None %22
%23 = OpFunctionParameter %10
%24 = OpFunctionParameter %10
%25 = OpLabel
%28 = OpIEqual %26 %24 %27
%31 = OpIEqual %26 %23 %29
%32 = OpIEqual %26 %24 %30
%33 = OpLogicalAnd %26 %31 %32
%34 = OpLogicalOr %26 %28 %33
%36 = OpSelect %10 %34 %35 %24
%37 = OpSDiv %10 %23 %36
OpReturnValue %37
OpFunctionEnd
%46 = OpFunction %2 None %47
%38 = OpLabel
%55 = OpVariable %56 Function %57
%58 = OpVariable %56 Function %59
%41 = OpLoad %9 %39
%50 = OpAccessChain %48 %14 %49
OpBranch %60
%60 = OpLabel
%61 = OpBitcast %10 %41
%62 = OpFunctionCall %10 %21 %61 %51
OpStore %55 %62
%63 = OpBitcast %10 %41
%64 = OpBitwiseAnd %10 %63 %35
OpStore %58 %64
%65 = OpLoad %10 %55
%66 = OpConvertSToF %4 %65
%67 = OpFMul %4 %66 %52
%68 = OpFSub %4 %67 %53
%69 = OpLoad %10 %58
%70 = OpConvertSToF %4 %69
%71 = OpFMul %4 %70 %52
%72 = OpFSub %4 %71 %53
%73 = OpCompositeConstruct %3 %68 %72 %54 %53
%77 = OpAccessChain %75 %50 %76 %49
%78 = OpLoad %3 %77
%79 = OpVectorShuffle %5 %78 %78 0 1 2
%80 = OpAccessChain %75 %50 %76 %76
%81 = OpLoad %3 %80
%82 = OpVectorShuffle %5 %81 %81 0 1 2
%84 = OpAccessChain %75 %50 %76 %83
%85 = OpLoad %3 %84
%86 = OpVectorShuffle %5 %85 %85 0 1 2
%87 = OpCompositeConstruct %11 %79 %82 %86
%88 = OpTranspose %11 %87
%89 = OpAccessChain %74 %50 %49
%90 = OpLoad %7 %89
%91 = OpMatrixTimesVector %3 %90 %73
%92 = OpVectorShuffle %5 %91 %91 0 1 2
%93 = OpMatrixTimesVector %5 %88 %92
%94 = OpCompositeConstruct %6 %73 %93
%95 = OpCompositeExtract %3 %94 0
OpStore %42 %95
%96 = OpCompositeExtract %5 %94 1
OpStore %44 %96
OpReturn
OpFunctionEnd
%90 = OpFunction %2 None %30
%81 = OpLabel
%85 = OpLoad %3 %83
%88 = OpLoad %5 %86
%82 = OpCompositeConstruct %6 %85 %88
%91 = OpLoad %12 %17
%92 = OpLoad %13 %19
OpBranch %93
%93 = OpLabel
%94 = OpCompositeExtract %5 %82 1
%96 = OpSampledImage %95 %91 %92
%97 = OpImageSampleImplicitLod %3 %96 %94
OpStore %89 %97
%106 = OpFunction %2 None %47
%97 = OpLabel
%101 = OpLoad %3 %99
%104 = OpLoad %5 %102
%98 = OpCompositeConstruct %6 %101 %104
%107 = OpLoad %12 %17
%108 = OpLoad %13 %19
OpBranch %109
%109 = OpLabel
%110 = OpCompositeExtract %5 %98 1
%112 = OpSampledImage %111 %107 %108
%113 = OpImageSampleImplicitLod %3 %112 %110
OpStore %105 %113
OpReturn
OpFunctionEnd