[glsl-out] add support for boolean vector ~, | and & ops

This commit is contained in:
teoxoy
2022-04-13 15:05:22 +02:00
committed by Teodor Tanasoaia
parent d3b37dcdb1
commit 7f4e07e5cd
2 changed files with 63 additions and 37 deletions

View File

@@ -356,6 +356,8 @@ pub enum Error {
enum BinaryOperation {
/// Vector comparison should use the function like `greaterThan()`, etc.
VectorCompare,
/// Vector component wise operation; used to polyfill unsupported ops like `|` and `&` for `bvecN`'s
VectorComponentWise,
/// GLSL `%` is SPIR-V `OpUMod/OpSMod` and `mod()` is `OpFMod`, but [`BinaryOperator::Modulo`](crate::BinaryOperator::Modulo) is `OpFRem`.
Modulo,
/// Any plain operation. No additional logic required.
@@ -2452,26 +2454,30 @@ impl<'a, W: Write> Writer<'a, W> {
Expression::Unary { op, expr } => {
use crate::{ScalarKind as Sk, UnaryOperator as Uo};
write!(
self.out,
"({} ",
match op {
Uo::Negate => "-",
Uo::Not => match ctx.info[expr]
.ty
.inner_with(&self.module.types)
.scalar_kind()
{
Some(Sk::Sint) | Some(Sk::Uint) => "~",
Some(Sk::Bool) => "!",
ref other =>
return Err(Error::Custom(format!(
"Cannot apply not to type {:?}",
other
))),
},
let ty = ctx.info[expr].ty.inner_with(&self.module.types);
match *ty {
TypeInner::Vector { kind: Sk::Bool, .. } => {
write!(self.out, "not(")?;
}
)?;
_ => {
let operator = match op {
Uo::Negate => "-",
Uo::Not => match ty.scalar_kind() {
Some(Sk::Sint) | Some(Sk::Uint) => "~",
Some(Sk::Bool) => "!",
ref other => {
return Err(Error::Custom(format!(
"Cannot apply not to type {:?}",
other
)))
}
},
};
write!(self.out, "({} ", operator)?;
}
}
self.write_expr(expr, ctx)?;
@@ -2494,27 +2500,22 @@ impl<'a, W: Write> Writer<'a, W> {
let right_inner = ctx.info[right].ty.inner_with(&self.module.types);
let function = match (left_inner, right_inner) {
(
&Ti::Vector {
kind: left_kind, ..
},
&Ti::Vector {
kind: right_kind, ..
},
) => match op {
(&Ti::Vector { kind, .. }, &Ti::Vector { .. }) => match op {
Bo::Less
| Bo::LessEqual
| Bo::Greater
| Bo::GreaterEqual
| Bo::Equal
| Bo::NotEqual => BinaryOperation::VectorCompare,
Bo::Modulo => match (left_kind, right_kind) {
(Sk::Float, _) | (_, Sk::Float) => match op {
Bo::Modulo => BinaryOperation::Modulo,
_ => BinaryOperation::Other,
},
_ => BinaryOperation::Other,
},
Bo::Modulo if kind == Sk::Float => BinaryOperation::Modulo,
Bo::And if kind == Sk::Bool => {
op = crate::BinaryOperator::LogicalAnd;
BinaryOperation::VectorComponentWise
}
Bo::InclusiveOr if kind == Sk::Bool => {
op = crate::BinaryOperator::LogicalOr;
BinaryOperation::VectorComponentWise
}
_ => BinaryOperation::Other,
},
_ => match (left_inner.scalar_kind(), right_inner.scalar_kind()) {
@@ -2554,6 +2555,31 @@ impl<'a, W: Write> Writer<'a, W> {
self.write_expr(right, ctx)?;
write!(self.out, ")")?;
}
BinaryOperation::VectorComponentWise => {
self.write_value_type(left_inner)?;
write!(self.out, "(")?;
let size = match *left_inner {
Ti::Vector { size, .. } => size,
_ => unreachable!(),
};
for i in 0..size as usize {
if i != 0 {
write!(self.out, ", ")?;
}
self.write_expr(left, ctx)?;
write!(self.out, ".{}", back::COMPONENTS[i])?;
write!(self.out, " {} ", back::binary_operation_str(op))?;
self.write_expr(right, ctx)?;
write!(self.out, ".{}", back::COMPONENTS[i])?;
}
write!(self.out, ")")?;
}
BinaryOperation::Modulo => {
write!(self.out, "(")?;

View File

@@ -58,13 +58,13 @@ float constructors() {
void logical() {
bool unnamed_11 = (! true);
bvec2 unnamed_12 = (! bvec2(true));
bvec2 unnamed_12 = not(bvec2(true));
bool unnamed_13 = (true || false);
bool unnamed_14 = (true && false);
bool unnamed_15 = (true || false);
bvec3 unnamed_16 = (bvec3(true) | bvec3(false));
bvec3 unnamed_16 = bvec3(bvec3(true).x || bvec3(false).x, bvec3(true).y || bvec3(false).y, bvec3(true).z || bvec3(false).z);
bool unnamed_17 = (true && false);
bvec4 unnamed_18 = (bvec4(true) & bvec4(false));
bvec4 unnamed_18 = bvec4(bvec4(true).x && bvec4(false).x, bvec4(true).y && bvec4(false).y, bvec4(true).z && bvec4(false).z, bvec4(true).w && bvec4(false).w);
}
void arithmetic() {