Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

[glsl-in] add support for .length() #2017

Merged
merged 10 commits into from
Aug 8, 2022
9 changes: 9 additions & 0 deletions src/front/glsl/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ pub enum HirExprKind {
/// The target expression
expr: Handle<HirExpr>,
},
/// A method call like `what.something(a, b, c)`
Method {
/// expression the method call applies to (`what` in the example)
expr: Handle<HirExpr>,
/// the method name (`something` in the example)
name: String,
/// the arguments to the method (`a`, `b`, and `c` in the example)
args: Vec<Handle<HirExpr>>,
},
}

#[derive(Debug, Hash, PartialEq, Eq)]
Expand Down
61 changes: 61 additions & 0 deletions src/front/glsl/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,67 @@ impl Context {
value
}
}
HirExprKind::Method {
expr: object,
ref name,
ref args,
} if ExprPos::Lhs != pos => {
JCapucho marked this conversation as resolved.
Show resolved Hide resolved
let args = args
.iter()
.map(|e| self.lower_expect_inner(stmt, parser, *e, ExprPos::Rhs, body))
.collect::<Result<Vec<_>>>()?;
match name.as_ref() {
"length" => {
if !args.is_empty() {
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
".length() doesn't take any arguments".into(),
),
meta,
});
}
let lowered_array =
self.lower_expect_inner(stmt, parser, object, pos, body)?.0;
let array_type = parser.resolve_type(self, lowered_array, meta)?;

match *array_type {
TypeInner::Array {
size: crate::ArraySize::Constant(size),
..
} => {
let mut array_length =
self.add_expression(Expression::Constant(size), meta, body);
self.forced_conversion(
parser,
&mut array_length,
meta,
ScalarKind::Sint,
4,
)?;
array_length
}
// let the error be handled in type checking if it's not a dynamic array
_ => {
let mut array_length = self.add_expression(
Expression::ArrayLength(lowered_array),
meta,
body,
);
self.conversion(&mut array_length, meta, ScalarKind::Sint, 4)?;
array_length
}
}
}
_ => {
return Err(Error {
JCapucho marked this conversation as resolved.
Show resolved Hide resolved
kind: ErrorKind::SemanticError(
format!("unknown method '{}'", name).into(),
),
meta,
});
}
}
}
_ => {
return Err(Error {
kind: ErrorKind::SemanticError(
Expand Down
18 changes: 18 additions & 0 deletions src/front/glsl/parser/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,24 @@ impl<'source> ParsingContext<'source> {
TokenValue::Dot => {
let (field, end_meta) = self.expect_ident(parser)?;

if self.bump_if(parser, TokenValue::LeftParen).is_some() {
let args =
self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?;

base = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Method {
expr: base,
name: field,
args,
},
meta,
},
Default::default(),
);
continue;
}

meta.subsume(end_meta);
base = stmt.hir_exprs.append(
HirExpr {
Expand Down
12 changes: 12 additions & 0 deletions tests/in/glsl/expressions.frag
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,18 @@ void testMatrixMultiplication(mat4x3 a, mat4x4 b) {
mat4x3 c = a * b;
}

layout(std430, binding = 0) buffer a_buf {
float a[];
};

void testLength() {
int len = a.length();
}

JCapucho marked this conversation as resolved.
Show resolved Hide resolved
void testConstantLength(float a[4u]) {
int len = a.length();
}

out vec4 o_color;
void main() {
privatePointer(global);
Expand Down
51 changes: 38 additions & 13 deletions tests/out/wgsl/expressions-frag.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ struct BST {
data: i32,
}

struct a_buf {
a: array<f32>,
}

struct FragmentOutput {
@location(0) o_color: vec4<f32>,
}

var<private> global: f32;
@group(0) @binding(0)
var<storage, read_write> global_1: a_buf;
var<private> o_color: vec4<f32>;

fn testBinOpVecFloat(a: vec4<f32>, b: f32) {
Expand Down Expand Up @@ -369,28 +375,47 @@ fn testMatrixMultiplication(a_22: mat4x3<f32>, b_18: mat4x4<f32>) {
return;
}

fn testLength() {
var len: i32;

len = i32(arrayLength((&global_1.a)));
return;
}

fn testConstantLength(a_24: array<f32,4u>) {
var a_25: array<f32,4u>;
var len_1: i32 = 4;

_ = (&global_1.a);
a_25 = a_24;
_ = a_25;
_ = i32(4u);
}

fn main_1() {
var local_5: f32;

_ = (&global_1.a);
_ = global;
let _e3 = global;
local_5 = _e3;
let _e5 = global;
local_5 = _e5;
privatePointer((&local_5));
let _e5 = local_5;
global = _e5;
let _e6 = o_color;
_ = _e6.xyzw;
let _e9 = vec4<f32>(1.0);
o_color.x = _e9.x;
o_color.y = _e9.y;
o_color.z = _e9.z;
o_color.w = _e9.w;
let _e7 = local_5;
global = _e7;
let _e8 = o_color;
_ = _e8.xyzw;
let _e11 = vec4<f32>(1.0);
o_color.x = _e11.x;
o_color.y = _e11.y;
o_color.z = _e11.z;
o_color.w = _e11.w;
return;
}

@fragment
fn main() -> FragmentOutput {
_ = (&global_1.a);
main_1();
let _e5 = o_color;
return FragmentOutput(_e5);
let _e7 = o_color;
return FragmentOutput(_e7);
}