Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement const-expressions (phase 2) #2309

Merged
merged 37 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
92c30dc
[wgsl-in] eagerly evaluate const-expressions
teoxoy Apr 19, 2023
345360e
use LocalVariable init
teoxoy Apr 19, 2023
f190b48
[glsl-in] const eval as soon as possible
teoxoy May 3, 2023
6bae046
[glsl-in] set initializer of local variables
teoxoy May 3, 2023
6feb138
Move `front::Emitter` to `proc`.
jimblandy Sep 13, 2023
8fcadcb
Replace `ConstantEvaluator`'s closure with optional emitter data.
jimblandy Sep 13, 2023
a53de15
Add a bit of logging to `ConstantEvaluator`. (#2488)
jimblandy Sep 19, 2023
908d74e
Document some parts of `ConstantEvaluator`. (#2489)
jimblandy Sep 19, 2023
946c5f2
ConstantEvaluator::copy_from: Rename argument `handle` to `expr`. (#2…
jimblandy Sep 19, 2023
2e5a244
ConstantEvaluator::swizzle: Handle vector concatenation and indexing …
jimblandy Sep 20, 2023
938ce3d
Split `const-exprs.rs` test into separate functions.
jimblandy Sep 20, 2023
85b578a
Test that only constant expressions are hoisted to initializers.
jimblandy Sep 20, 2023
a2a917c
add an expression constness tracker
teoxoy Sep 22, 2023
170fd8c
Add snapshot tests for constant evaluation of splats and composes.
jimblandy Sep 28, 2023
b151a2a
Let ConstantEvaluator see through Constant exprs in Compose exprs.
jimblandy Sep 28, 2023
f733ac1
Let ConstantEvaluator see through Constant exprs in Splat exprs.
jimblandy Sep 28, 2023
f72d5c1
[wgsl-in] use ast spans for errors since they are more accurate
teoxoy Sep 29, 2023
4b4b0d3
avoid having constants pointing to other constants
teoxoy Sep 29, 2023
9d87d9e
[wgsl-in] don't treat `let` declarations as `const` declarations
teoxoy Sep 29, 2023
f06eee9
[wgsl] test `@workgroup_size` attribute with constants
teoxoy Sep 29, 2023
303a3cd
[wgsl] test const evaluation of division and multiplication
teoxoy Sep 29, 2023
82a3613
[wgsl] test usage of constants in switch cases
teoxoy Sep 29, 2023
b46ea49
[const-eval] add wgsl/glsl behavior switch to evaluator
teoxoy Oct 4, 2023
d87231b
[const-eval] check number of arguments for math functions
teoxoy Oct 4, 2023
c24ab86
[const-eval] account for `ZeroValue` index for `AccessIndex` expression
teoxoy Oct 4, 2023
f219e93
[const-eval] implement `pow` & `clamp` built-in functions properly
teoxoy Oct 4, 2023
da17650
[const-eval] allow bitcast, select and relational functions for GLSL …
teoxoy Oct 4, 2023
18f4de7
[const-eval] evaluate `BinaryOperator::Modulo` correctly (use the tru…
teoxoy Oct 5, 2023
b737d3e
[const-eval] error on invalid binary operations
teoxoy Oct 5, 2023
233c6c6
Properly recognize `Literal` expressions as non-dynamic indices. (#2537)
jimblandy Oct 5, 2023
c216a13
Avoid FXC's error X3694: race condition writing to shared resource de…
teoxoy Oct 5, 2023
9171884
[const-eval] error on NaN and infinite floats
teoxoy Oct 5, 2023
260effb
avoid const-evaluating the `operators.wgsl` snapshot
teoxoy Oct 9, 2023
ca46c6d
[wgsl-in] Document necessity of `force_non_const`.
jimblandy Oct 9, 2023
a0e0242
Some documentation for ConstantEvaluator.
jimblandy Oct 10, 2023
61d91eb
[valid] check local variable initializer is const
teoxoy Oct 11, 2023
f53151d
[wgsl-in] Don't double-initialize variables local to loops.
jimblandy Oct 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@ impl<'a, W: Write> Writer<'a, W> {

// Write the constant
// `write_constant` adds no trailing or leading space/newline
self.write_const_expr(init)?;
self.write_expr(init, &ctx)?;
} else if is_value_init_supported(self.module, local.ty) {
write!(self.out, " = ")?;
self.write_zero_init_value(local.ty)?;
Expand Down Expand Up @@ -1709,7 +1709,7 @@ impl<'a, W: Write> Writer<'a, W> {
arg: Handle<crate::Expression>,
arg1: Handle<crate::Expression>,
size: usize,
ctx: &back::FunctionCtx<'_>,
ctx: &back::FunctionCtx,
) -> BackendResult {
// Write parantheses around the dot product expression to prevent operators
// with different precedences from applying earlier.
Expand Down Expand Up @@ -2254,9 +2254,12 @@ impl<'a, W: Write> Writer<'a, W> {
/// [`Expression`]: crate::Expression
/// [`Module`]: crate::Module
fn write_const_expr(&mut self, expr: Handle<crate::Expression>) -> BackendResult {
self.write_possibly_const_expr(expr, &self.module.const_expressions, |writer, expr| {
writer.write_const_expr(expr)
})
self.write_possibly_const_expr(
expr,
&self.module.const_expressions,
|expr| &self.info[expr],
|writer, expr| writer.write_const_expr(expr),
)
}

/// Write [`Expression`] variants that can occur in both runtime and const expressions.
Expand All @@ -2277,13 +2280,15 @@ impl<'a, W: Write> Writer<'a, W> {
/// Adds no newlines or leading/trailing whitespace
///
/// [`Expression`]: crate::Expression
fn write_possibly_const_expr<E>(
&mut self,
fn write_possibly_const_expr<'w, I, E>(
&'w mut self,
expr: Handle<crate::Expression>,
expressions: &crate::Arena<crate::Expression>,
info: I,
write_expression: E,
) -> BackendResult
where
I: Fn(Handle<crate::Expression>) -> &'w proc::TypeResolution,
E: Fn(&mut Self, Handle<crate::Expression>) -> BackendResult,
{
use crate::Expression;
Expand Down Expand Up @@ -2331,6 +2336,14 @@ impl<'a, W: Write> Writer<'a, W> {
}
write!(self.out, ")")?
}
// `Splat` needs to actually write down a vector, it's not always inferred in GLSL.
Expression::Splat { size: _, value } => {
let resolved = info(expr).inner_with(&self.module.types);
self.write_value_type(resolved)?;
write!(self.out, "(")?;
write_expression(self, value)?;
write!(self.out, ")")?
}
_ => unreachable!(),
}

Expand All @@ -2344,7 +2357,7 @@ impl<'a, W: Write> Writer<'a, W> {
fn write_expr(
&mut self,
expr: Handle<crate::Expression>,
ctx: &back::FunctionCtx<'_>,
ctx: &back::FunctionCtx,
) -> BackendResult {
use crate::Expression;

Expand All @@ -2357,10 +2370,14 @@ impl<'a, W: Write> Writer<'a, W> {
Expression::Literal(_)
| Expression::Constant(_)
| Expression::ZeroValue(_)
| Expression::Compose { .. } => {
self.write_possibly_const_expr(expr, ctx.expressions, |writer, expr| {
writer.write_expr(expr, ctx)
})?;
| Expression::Compose { .. }
| Expression::Splat { .. } => {
self.write_possibly_const_expr(
expr,
ctx.expressions,
|expr| &ctx.info[expr].ty,
|writer, expr| writer.write_expr(expr, ctx),
)?;
}
// `Access` is applied to arrays, vectors and matrices and is written as indexing
Expression::Access { base, index } => {
Expand Down Expand Up @@ -2407,14 +2424,6 @@ impl<'a, W: Write> Writer<'a, W> {
ref other => return Err(Error::Custom(format!("Cannot index {other:?}"))),
}
}
// `Splat` needs to actually write down a vector, it's not always inferred in GLSL.
Expression::Splat { size: _, value } => {
let resolved = ctx.info[expr].ty.inner_with(&self.module.types);
self.write_value_type(resolved)?;
write!(self.out, "(")?;
self.write_expr(value, ctx)?;
write!(self.out, ")")?
}
// `Swizzle` adds a few letters behind the dot.
Expression::Swizzle {
size,
Expand Down
33 changes: 18 additions & 15 deletions src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, " = ")?;
// Write the local initializer if needed
if let Some(init) = local.init {
self.write_const_expression(module, init)?;
self.write_expr(module, init, func_ctx)?;
} else {
// Zero initialize local variables
self.write_default_init(module, local.ty)?;
Expand Down Expand Up @@ -2078,6 +2078,19 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
write!(self.out, ")")?;
}
Expression::Splat { size, value } => {
// hlsl is not supported one value constructor
// if we write, for example, int4(0), dxc returns error:
// error: too few elements in vector initialization (expected 4 elements, have 1)
let number_of_components = match size {
crate::VectorSize::Bi => "xx",
crate::VectorSize::Tri => "xxx",
crate::VectorSize::Quad => "xxxx",
};
write!(self.out, "(")?;
write_expression(self, value)?;
write!(self.out, ").{number_of_components}")?
}
_ => unreachable!(),
}

Expand Down Expand Up @@ -2135,7 +2148,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
Expression::Literal(_)
| Expression::Constant(_)
| Expression::ZeroValue(_)
| Expression::Compose { .. } => {
| Expression::Compose { .. }
| Expression::Splat { .. } => {
self.write_possibly_const_expression(
module,
expr,
Expand Down Expand Up @@ -2423,7 +2437,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {

if let Some(offset) = offset {
write!(self.out, ", ")?;
write!(self.out, "int2(")?; // work around https://github.com/microsoft/DirectXShaderCompiler/issues/5082#issuecomment-1540147807
self.write_const_expression(module, offset)?;
write!(self.out, ")")?;
}

write!(self.out, ")")?;
Expand Down Expand Up @@ -3154,19 +3170,6 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
self.write_expr(module, argument, func_ctx)?;
write!(self.out, ")")?
}
Expression::Splat { size, value } => {
// hlsl is not supported one value constructor
// if we write, for example, int4(0), dxc returns error:
// error: too few elements in vector initialization (expected 4 elements, have 1)
let number_of_components = match size {
crate::VectorSize::Bi => "xx",
crate::VectorSize::Tri => "xxx",
crate::VectorSize::Quad => "xxxx",
};
write!(self.out, "(")?;
self.write_expr(module, value, func_ctx)?;
write!(self.out, ").{number_of_components}")?
}
Expression::Select {
condition,
accept,
Expand Down
Loading
Loading