glsl-in: use forced conversions for vector/matrix constructors

The spec defines that for vector and matrix constructors all arguments
should use the same conversions as scalar constructors (forced conversions)
This commit is contained in:
João Capucho 2022-03-27 22:11:30 +01:00 committed by Dzmitry Malyshau
parent 26537c1a60
commit 21f89b65e4
4 changed files with 38 additions and 8 deletions

View File

@ -1279,6 +1279,25 @@ impl Context {
Ok(())
}
pub fn forced_conversion(
&mut self,
parser: &Parser,
expr: &mut Handle<Expression>,
meta: Span,
kind: ScalarKind,
width: crate::Bytes,
) -> Result<()> {
if let Some((expr_scalar_kind, expr_width)) =
self.expr_scalar_components(parser, *expr, meta)?
{
if expr_scalar_kind != kind || expr_width != width {
self.conversion(expr, meta, kind, width)?;
}
}
Ok(())
}
pub fn binary_implicit_conversion(
&mut self,
parser: &Parser,

View File

@ -113,7 +113,7 @@ impl Parser {
Ok(match self.module.types[ty].inner {
TypeInner::Vector { size, kind, width } if vector_size.is_none() => {
ctx.implicit_conversion(self, &mut value, meta, kind, width)?;
ctx.forced_conversion(self, &mut value, expr_meta, kind, width)?;
if let TypeInner::Scalar { .. } = *self.resolve_type(ctx, value, expr_meta)? {
ctx.add_expression(Expression::Splat { size, value }, meta, body)
@ -256,7 +256,7 @@ impl Parser {
// `Expression::As` doesn't support matrix width
// casts so we need to do some extra work for casts
ctx.implicit_conversion(self, &mut value, expr_meta, ScalarKind::Float, width)?;
ctx.forced_conversion(self, &mut value, expr_meta, ScalarKind::Float, width)?;
match *self.resolve_type(ctx, value, expr_meta)? {
TypeInner::Scalar { .. } => {
// If a matrix is constructed with a single scalar value, then that
@ -446,7 +446,7 @@ impl Parser {
let mut components = Vec::with_capacity(size as usize);
for (mut arg, expr_meta) in args.iter().copied() {
ctx.implicit_conversion(self, &mut arg, expr_meta, kind, width)?;
ctx.forced_conversion(self, &mut arg, expr_meta, kind, width)?;
if components.len() >= size as usize {
break;
@ -512,10 +512,7 @@ impl Parser {
let mut flattened = Vec::with_capacity(columns as usize * rows as usize);
for (mut arg, meta) in args.iter().copied() {
let scalar_components = scalar_components(&self.module.types[ty].inner);
if let Some((kind, width)) = scalar_components {
ctx.implicit_conversion(self, &mut arg, meta, kind, width)?;
}
ctx.forced_conversion(self, &mut arg, meta, ScalarKind::Float, width)?;
match *self.resolve_type(ctx, arg, meta)? {
TypeInner::Vector { size, .. } => {

View File

@ -113,6 +113,11 @@ void testFreestandingConstructor() {
vec4(1.0);
}
void testNonImplicitCastVectorCast() {
uint a = 1;
ivec4 b = ivec4(a);
}
float global;
void privatePointer(inout float a) {}

View File

@ -286,7 +286,16 @@ fn testFreestandingConstructor() {
return;
}
fn privatePointer(a_18: ptr<function, f32>) {
fn testNonImplicitCastVectorCast() {
var a_18: u32 = 1u;
var b_16: vec4<i32>;
let _e3 = a_18;
b_16 = vec4<i32>(i32(_e3));
return;
}
fn privatePointer(a_19: ptr<function, f32>) {
return;
}