Open jimblandy opened 5 months ago
It's not clear that this must be a problem. We could simply decide that Naga's validation rules permit subexpressions that are not covered by Emit
statements, and backends are free to evaluate such subexpressions whenever is convenient. It seems that our backends work this way already, by accident.
Here's an illustration of the impact. Emit
statements determine when Load
expressions are evaluated relative to side effects that could affect the values they produce. For example:
var<private> x: i32 = 0;
fn inc_x() -> i32 {
x++;
return x;
}
fn f() -> i32 {
x = 0;
return x + inc_x();
}
In x + inc_x()
, WGSL requires the subexpression x
to be evaluated before the call to inc_x
takes place, per the rules in §14.1. Program Order Within an Invocation. So the WGSL standard is clear that calling f
must return 1
: the value of the subexpression x
is 0
, and inc_x()
returns 1
.
To get this behavior, however, Naga's WGSL front end must ensure that, in the Module
it generates, the Load
of x
in f
is covered by an Emit
statement before the Call
statement that invokes inc_x
. Otherwise, the Load
will not be evaluated until the Return
statement, as if the source code had been:
return inc_x() + x;
and the program will return 2
.
The reason this issue isn't necessarily a bug in Naga's evaluator is that, if the Load
is not covered by an Emit
, that is arguably a bug in Naga's WGSL front end: it did not properly translate the meaning of the WGSL source code into Naga IR.
However, I think this is unsatisfying: if a front end neglects to specify when an order-sensitive expression like Load
is evaluated, rather than saying "do as you wish, backends!" we should help front-end developers by rejecting the module, and making them spell out the evaluation order they want.
I'm not sure what the intention was when we initially implemented the emitting machinery.
However, I think this is unsatisfying: if a front end neglects to specify when an order-sensitive expression like
Load
is evaluated, rather than saying "do as you wish, backends!" we should help front-end developers by rejecting the module, and making them spell out the evaluation order they want.
I think this is a good idea, we'd avoid a possible footgun.
Ideally we'd remove the emitting concept altogether. I really liked the Instruction
concept we previously talked about.
Naga doesn't check that each subexpression of an expression used by a statement has been covered by an
Emit
statement.When added to
naga/tests/validation.rs
, the following test should pass, but it fails: