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

[naga wgsl-in] Allow global const declarations to have abstract types #7055

Merged
merged 5 commits into from
Feb 25, 2025

Conversation

jamienicol
Copy link
Contributor

@jamienicol jamienicol commented Feb 4, 2025

Connections
Fixes #6232
Depends on #7035 as it builds upon testcases added there. But could be made independent if we choose not to land that for whatever reason. The first commit of the 4 in this PR is actually from there. If there's a better way to handle dependent PRs in github please let me know!

Description
Currently global const declarations are concretized when declared, meaning if you declared an abstract float or abstract int they will be given an effective value type of f32 or i32 respectively, and can only be subsequently used as those types. The spec, however, allows const declarations to have an abstract type, which then allows, for example, an abstract int const to later be used as either an f32 or an i32 (or both) depending on the context. These patches implement that behaviour by removing the call to concretize() when lowering a global const declaration, instead appending the Constant to the IR with its abstract type.

We must, however, ensure that abstract types do not end up in the final IR that will be validated or passed to the backends. We therefore ensure that the compact pass removes any constants of abstract types. Any other non-constant expressions in the IR which referenced that abstract constant will have had to have been concretized, meaning they no longer will reference the constant. Meaning this does not remove any expressions that were actually used. It does, however, remove some unused expressions, which does have some effect on our snapshot tests.

Testing
Inspected snapshot changes and ensured validation still passes. Checked that some webgpu:shader,validation,const_assert,const_assert:constant_expression_assert:* tests in the CTS now pass. (Some still fail in that group for other reasons.)

Added some additional tests in the final patch in series. For reviewability I kept them separate from the snapshot changes caused by the fix itself.

Checklist

  • Run cargo fmt.
  • Run cargo clippy. If applicable, add:
  • Run cargo xtask test to run tests.
  • Add change to CHANGELOG.md. See simple instructions inside file.

@jamienicol jamienicol changed the title Allow const declarations to have abstract types [naga wgsl-in] Allow const declarations to have abstract types Feb 4, 2025
@ErichDonGubler ErichDonGubler self-assigned this Feb 4, 2025
Comment on lines 46 to 49
let mut expr_ty = typifier.get(value, self.types);
while let crate::TypeInner::Array { base, .. } = *expr_ty {
expr_ty = &self.types[base].inner;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Here and in other places, we're recursing into types that can have abstract numeric components, and making sure those aren't abstract. This sounds correct. However, we're only checking for Arrays' components. Don't we also need to check for vector and matrix components?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Face-to-face discussion with @jamienicol: This is because the scalar() helper below handles the cases I'm thinking of, but not Array. A separate helper here sounds interesting.

ErichDonGubler
ErichDonGubler previously approved these changes Feb 4, 2025
Copy link
Member

@ErichDonGubler ErichDonGubler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ErichDonGubler ErichDonGubler added type: enhancement New feature or request naga Shader Translator area: naga front-end lang: WGSL WebGPU Shading Language type: bug Something isn't working area: ecosystem Help the connected projects grow and prosper area: correctness We're behaving incorrectly labels Feb 4, 2025
Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to split out global constants and local constants into separate PRs. Also, I think we need to take a different approach for local constants.

Comment on lines 7 to 8
pub types: &'a crate::UniqueArena<crate::Type>,
pub resolve_context: crate::proc::ResolveContext<'a>,
Copy link
Member

@jimblandy jimblandy Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the right approach. We talked in person about how this works, and I see that it does accomplish the goal. But as much as possible, I would really like to keep the compactor a dumb structural algorithm: you give it this DAG-gy module thing, and it shakes out all the disconnected pieces without looking too hard at their semantics, and that's it. Running the typifier in compaction introduces subtleties that are not the direction that I would like to see things going.

Instead, as discussed, let's try having the WGSL front end simply not add abstract-typed constants to the function's named expressions table at all. The hope is that this would make compaction just remove them naturally, since constant evaluation should have left them all unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The avoid adding them to named expressions trick seemed to work. Patch is updated. It felt trivial enough just to keep it in the same PR

@cwfitzgerald cwfitzgerald dismissed ErichDonGubler’s stale review February 5, 2025 16:35

Code was indeed fine, some structural changes are needed per discussion with jimb

@jamienicol jamienicol force-pushed the abstract-consts branch 5 times, most recently from 93f7101 to 38e2eeb Compare February 6, 2025 10:30
@jamienicol
Copy link
Contributor Author

Updated this PR to only handle global const declarations per @jimblandy's request.

As a consequence, noticed an issue with the first patch in the series (the one to handle casting constant arrays.) The problem was that ConstantEvaluator.cast_array() did not properly handle Constant expressions by calling check_and_get(). My old patch fixed this from one callsight by making it eval a Expression::As instead (which does call check_and_get(). And making evaluating an Expression:As call cast_array instead of just cast.

However, by splitting out the local and global consts from eachother, I noticed we run in to the same problem from a different callsight - when concretizing a local const which is set to a global const. The concretize() call here also calls cast_array(). So I think the better solution is just to make cast_array() itself call check_and_get(). Additionally I noticed the comment for cast_array() specifically mentions that Expression::As does not handle arrays, so I think my previous patch was incorrect to make it do so.

@jamienicol jamienicol changed the title [naga wgsl-in] Allow const declarations to have abstract types [naga wgsl-in] Allow global const declarations to have abstract types Feb 6, 2025
@jamienicol
Copy link
Contributor Author

Rebased now #7035 has been merged

@jamienicol
Copy link
Contributor Author

Rebased now #7055 has merged as it conflicted. Ready for re-review

@jamienicol jamienicol force-pushed the abstract-consts branch 2 times, most recently from a61968b to c08f218 Compare February 17, 2025 15:25
@jimblandy jimblandy force-pushed the abstract-consts branch 3 times, most recently from f4f0d08 to d85e418 Compare February 25, 2025 00:53
@@ -14,25 +14,53 @@ fn func_au(a: array<u32, 2>) {}

fn func_f_i(a: f32, b: i32) {}

const const_af = 0;
Copy link
Member

@jimblandy jimblandy Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how juvenile

Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Please look over the additional changes I pushed, and if they look good, please merge.

For these tests, I send you a bouquet of flowers: 💐

jamienicol and others added 5 commits February 25, 2025 09:01
…t expressions

It must call ConstantEvaluator::check_and_get() to possibly retrieve
the constant expression from a separate arena, like is currently done
when evaluating `As` expressions for non-array casts.
… abstract types

Instead allow the const to be converted and each time it is const
evaluated as part of another expression. This allows an abstract const
to be used as a different type depending on the context.

A consequence of this is that abstract types may now find their way to
the validation stage, which we don't want. We therefore additionally
now ensure that the compact pass removes global constants of abstract
types. This will have no *functional* effect on shaders generated by
the backends, as the expressions belonging to the abstract consts in
the IR will not actually be used, as any usage in the input shader
will have been const-evaluated away. Certain unused const declarations
will now be removed, however, as can be seen by the effect on the
snapshot outputs.
Define `TypeInner::is_abstract`, and let it take a type arena so that
it can properly handle abstract arrays. Use this in compaction and in
the WGSL front end's conversion code to recognize abstract types.
Introduce the `AbstractRule` enum to control the behavior of
`Lowerer::type_and_init`. This is slightly clearer than
`allow_abstract: bool`, but more wordy.
@jamienicol jamienicol merged commit e0f0185 into gfx-rs:trunk Feb 25, 2025
35 checks passed
@jamienicol jamienicol deleted the abstract-consts branch February 25, 2025 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: correctness We're behaving incorrectly area: ecosystem Help the connected projects grow and prosper area: naga front-end lang: WGSL WebGPU Shading Language naga Shader Translator type: bug Something isn't working type: enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

WGSL constant values should not be concretized
3 participants