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

Mitigation for MSL atomic bounds check. #1703

Merged
merged 4 commits into from
Feb 2, 2022
Merged

Conversation

glalonde
Copy link
Contributor

Will CI trigger automatically?

@glalonde
Copy link
Contributor Author

Mostly untested attempt for #1643. This moves the bounds check outside of the atomic expression, but I'm unsure if it is correct to just immediately go to self.put_access_chain(expr_handle, policy, context)?; within or if there can be a more complicated expression than just direct member or array access that wouldn't work in this case.

Also not sure about the is_scoped logic. I figured it should be safe to always wrap in () but for some reason that's discouraged.

@kvark kvark requested a review from jimblandy January 27, 2022 18:11
@glalonde
Copy link
Contributor Author

Looks like the CI failure is because I added the atomic tests which aren't implemented for spv. I guess I can remove those before submission, or maybe make a separate group of msl tests.

@kvark
Copy link
Member

kvark commented Jan 31, 2022

@jimblandy please review this
@glalonde sorry about the delay! Please ping us if this gets lost again.

@jimblandy
Copy link
Member

@glalonde The PR title says "Mitigation", but are you aware of any cases where this doesn't address the problem?

@glalonde
Copy link
Contributor Author

glalonde commented Feb 1, 2022

I'm not aware of situations it doesn't handle, but I wouldn't be surprised if they exist.

For example, I'm not sure if there are more complicated access patterns than just array access or struct access ( in the tests) which might break.

I just tried this locally as a more convoluted access:

struct AtomicArray {
   a: array<atomic<u32>, 10>;
};

struct Globals {
...
    e: array<AtomicArray, 10>;
};

fn fetch_add_atomic_array2(i: i32, j: i32) -> u32 {
   return atomicAdd(&globals.e[i].a[j], 1u);
}
metal::uint fetch_add_atomic_array2_(
    int i_14,
    int j_2,
    device Globals& globals,
    constant _mslBufferSizes& _buffer_sizes
) {
    metal::uint _e8 = metal::uint(j_2) < 10 && metal::uint(i_14) < 10 ? metal::atomic_fetch_add_explicit(&globals.e.inner[i_14].a.inner[j_2], 1u, metal::memory_order_relaxed) : DefaultConstructible();
    return _e8;
}

And that looks like it would work...

@jimblandy
Copy link
Member

jimblandy commented Feb 1, 2022 via email

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 like just the right approach. I have a few small comments, and a suggestion on how to fix the tests.

tests/in/bounds-check-zero.wgsl Outdated Show resolved Hide resolved
src/back/msl/writer.rs Outdated Show resolved Hide resolved
src/back/msl/writer.rs Outdated Show resolved Hide resolved
@glalonde
Copy link
Contributor Author

glalonde commented Feb 1, 2022

Thanks for the review, ptal

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. I wrote the bounds-checking code for Metal, so I humbly thank you for catching my mistake. I have one last change to request, and then I'll merge it.

@@ -0,0 +1,21 @@
// Tests for `naga::back::BoundsCheckPolicy::ReadZeroSkipWrite`.
Copy link
Member

Choose a reason for hiding this comment

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

Might want to add:

// for atomic types. These are separate from `bounds-check-zero.wgsl because
// SPIR-V does not yet support `ReadZeroSkipWrite` for atomics. Once it does,
// the test files could be combined.

Comment on lines 799 to 810
let put_unchecked_atomic_access = |writer: &mut Writer<W>| -> BackendResult {
write!(
writer.out,
"{}::atomic_fetch_{}_explicit({}",
NAMESPACE, key, ATOMIC_REFERENCE
)?;
writer.put_access_chain(expr_handle, policy, context)?;
write!(writer.out, ", ")?;
writer.put_expression(value, context, true)?;
write!(writer.out, ", {}::memory_order_relaxed)", NAMESPACE)?;
Ok(())
};
Copy link
Member

Choose a reason for hiding this comment

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

Yes, I noticed the duplicated code as well. Naga's style is to not use closures in this way, to keep control flow simple. This is certainly subjective, but it's what we've settled on.

Instead, please declare a bool, and then have two if statements on either side of the common code.

@jimblandy jimblandy merged commit bb604fd into gfx-rs:master Feb 2, 2022
@jimblandy
Copy link
Member

I sorted out the style points - this is a good fix and I want to get it in right away.

Thank you very much!

@glalonde
Copy link
Contributor Author

glalonde commented Feb 2, 2022

awesome, thanks! looking forward to the next release : )

caelunshun pushed a commit to caelunshun/naga that referenced this pull request Feb 24, 2022
[msl-out] Correct output for bounds-checked atomic accesses.
raphlinus added a commit to raphlinus/naga that referenced this pull request Oct 23, 2022
Generalize put_atomic_fetch to handle `exchange` as well, rather than special-cased code which didn't do the bounds check (the check handling as fixed in gfx-rs#1703 but only for the fetch cases, exchange was skipped).

Fixes gfx-rs#1848
jimblandy pushed a commit that referenced this pull request Oct 24, 2022
* Fix incorrect atomic bounds check on metal back-end

Generalize put_atomic_fetch to handle `exchange` as well, rather than special-cased code which didn't do the bounds check (the check handling as fixed in #1703 but only for the fetch cases, exchange was skipped).

Fixes #1848

* Add tests for atomic exchange
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants