-
Notifications
You must be signed in to change notification settings - Fork 905
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 spv-out] bounds-check runtime-sized array access correctly. #6351
Open
jimblandy
wants to merge
8
commits into
gfx-rs:trunk
Choose a base branch
from
jimblandy:fix-4441-spv-out-accessindex-bounds-checks
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
[naga spv-out] bounds-check runtime-sized array access correctly. #6351
jimblandy
wants to merge
8
commits into
gfx-rs:trunk
from
jimblandy:fix-4441-spv-out-accessindex-bounds-checks
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Introduce a new function, `BlockContext::is_nonuniform_binding_array_access`, which determines whether a given array access expression means that the `OpAccessChain` instruction must have a `NonUniform` decoration.
Introduce a new function, `BlockContext::extend_bounds_check_condition_chain`, which adds a new boolean condition to the chain of bounds checks guarding an `OpAccessChain` instruction.
Let the SPIR-V backend use `GuardedIndex::try_resolve_to_constant`, rather than writing out its definition in `write_restricted_index` and `write_index_comparison`. Call `try_resolve_to_constant` in one place, in `write_bounds_check`, and simply pass the `GuardedIndex` into subroutines. Reduce `write_restricted_index` and `write_index_comparison` to case analysis and code generation. Note that this commit does have a benign effect on SPIR-V snapshot output for programs like this: let one_i = 1i; var vec0 = vec3<i32>(); vec0[one_i] = 1; The value indexing `vec0` here is an `i32`, but after this commit, the operand to `OpAccessChain` becomes a `u32` constant (with the same value). This is because `write_bounds_check` now calls `try_resolve_to_constant` itself, rather than deferring this work to its callees, so it may return `BoundsCheckResult::KnownInBounds` even when the `Unchecked` policy is in force. This directs the caller, `write_expression_pointer`, to treat the `OpAccessChain` operand as a fresh `u32` constant, rather than simply passing through the original `i32` expression.
Abstract the code from `write_expression_pointer` to handle one indexing operation out into its own function, `BlockContext::write_access_chain_index`.
Let `BoundsCheckResult::Conditional` provide both the condition to check before carrying out the access, and the index to use for that access. The `Conditional` variant indicates that we generated a runtime bounds check, which implies we must have had a SPIR-V id for the index to pass to that check, so there's no reason not to provide that to the callers - especially if the bounds check code was able to reduce it to a known constant. At the moment, this is not much of a refactor, but later commits will use `GuardedIndex` in more places, at which point this will avoid a re-matching and assertion.
Extend the snapshot tests for bounds checking to cover the case where a runtime-sized array is indexed by a constant.
jimblandy
added
type: bug
Something isn't working
area: naga back-end
Outputs of naga shader conversion
naga
Shader Translator
lang: SPIR-V
Vulkan's Shading Language
labels
Oct 1, 2024
Do not neglect to apply bounds checks to indexing operations on runtime-sized arrays, even when they are accessed via an `AccessIndex` instruction. Before this commit, `BlockContext::write_expression_pointer` would not apply bounds checks to `OpAccessChain` indices provided by an `AccessIndex` instruction, apparently with the rationale that any out-of-bounds accesses should have been reported by constant evaluation. While it is true that the `index` operand of an `AccessIndex` expression is known at compile time, and that the WGSL constant evaluation rules require accesses that can be statically determined to be out-of-bounds to be shader creation or pipeline creation time errors, accesses to runtime-sized arrays don't follow this pattern: even if the index is known, the length with which it must be compared is not. Fixes gfx-rs#4441.
jimblandy
force-pushed
the
fix-4441-spv-out-accessindex-bounds-checks
branch
from
October 1, 2024 20:14
eb3ec2f
to
cc134f1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got up to (but not including) the [naga spv-out] Consolidate code to find index values.
So far, the review experience has been nice!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
area: naga back-end
Outputs of naga shader conversion
lang: SPIR-V
Vulkan's Shading Language
naga
Shader Translator
type: bug
Something isn't working
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Do not neglect to apply bounds checks to indexing operations on runtime-sized arrays, even when they are accessed via an
AccessIndex
instruction.Before this commit,
BlockContext::write_expression_pointer
would not apply bounds checks toOpAccessChain
indices provided by anAccessIndex
instruction, apparently with the rationale that any out-of-bounds accesses should all have been reported by constant evaluation.While it is true that the
index
operand of anAccessIndex
expression is known at compile time, and that the WGSL constant evaluation rules require accesses that can be statically determined to be out-of-bounds to be shader creation or pipeline creation time errors, accesses to runtime-sized arrays don't follow this pattern: even if the index is known, the length with which it must be compared is not.Fixes #4441.
[naga] Extend snapshot tests for bounds checks.
Extend the snapshot tests for bounds checking to cover the case where a runtime-sized array is indexed by a constant.
[naga spv-out] Let
BoundsCheckResult
supply the index value.Let
BoundsCheckResult::Conditional
provide both the condition to check before carrying out the access, and the index to use for that access. TheConditional
variant indicates that we generated a runtime bounds check, which implies we must have had a SPIR-V id for the index to pass to that check, so there's no reason not to provide that to the callers - especially if the bounds check code was able to reduce it to a known constant.At the moment, this is not much of a refactor, but later commits will use
GuardedIndex
in more places, at which point this will avoid a re-matching and assertion.[naga spv-out] Abstract out
OpAccessChain
index production.Abstract the code from
write_expression_pointer
to handle one indexing operation out into its own function,BlockContext::write_access_chain_index
.[naga spv-out] Consolidate code to find index values.
Let the SPIR-V backend use
GuardedIndex::try_resolve_to_constant
, rather than writing out its definition inwrite_restricted_index
andwrite_index_comparison
.Call
try_resolve_to_constant
in one place, inwrite_bounds_check
, and simply pass theGuardedIndex
into subroutines.Reduce
write_restricted_index
andwrite_index_comparison
to case analysis and code generation.Note that this commit does have a benign effect on SPIR-V snapshot output for programs like this:
The value indexing
vec0
here is ani32
, but after this commit, the operand toOpAccessChain
becomes au32
constant (with the same value).This is because
write_bounds_check
now callstry_resolve_to_constant
itself, rather than deferring this work to its callees, so it may returnBoundsCheckResult::KnownInBounds
even when theUnchecked
policy is in force. This directs the caller,write_expression_pointer
, to treat theOpAccessChain
operand as a freshu32
constant, rather than simply passing through the originali32
expression.[naga spv-out] Abstract extending a bounds check condition chain.
Introduce a new function,
BlockContext::extend_bounds_check_condition_chain
, which adds a new boolean condition to the chain of bounds checks guarding anOpAccessChain
instruction.[naga spv-out] Doc fix: typo
[naga spv-out] Abstract out non-uniform binding array access test.
Introduce a new function,
BlockContext::is_nonuniform_binding_array_access
, which determines whether a given array access expression means that theOpAccessChain
instruction must have aNonUniform
decoration.