Rust-GPU / Rust-GPU/rust-gpu

[Migrated] Unsynchronized memory accesses outside of `Function`/`Private` need to use `NonPrivatePointer`.

Open
#115 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
3.4k
Forks
125
PR merge metrics
No merged PRs in 30d

Description

Issue automatically imported from old repo: https://github.com/EmbarkStudios/rust-gpu/issues/838
Old labels: t: bug,s: qptr may fix
Originally creatd by eddyb on 2022-01-09T14:30:48Z


The description from the spec of NonPrivatePointer is:

NonPrivatePointer
The memory access obeys inter-thread ordering, as specified by the client API.

Missing before version 1.5.

My understanding is that with NonPrivatePointer, unsynchronized accesses can be used to access the same memory from different threads, as long as there is a barrier (or an equivalent atomic access) separating them - AFAICT, this matches Rust's concurrency semantics (likely rooted in the C++11 memory model, but I'm far from an expert).

To give a practical example, this is what allows Mutex<SomeData> to work, as well as passing Box<SomeData> between threads (or even &mut SomeData, with scoped threads - rayon relies on this a lot) - all accesses to SomeData will be unsynchronized, but they can't race between threads because of the synchronization used to get access to the pointer in the first place.

Without NonPrivatePointer, however, opting into the Vulkan memory model isn't enough to make anything other than atomic accesses thread-safe. Even something as potentially-common as reading data written per-invocation, from a single chosen invocation (i.e. the "join" step in a "fork-join" model), would be UB unless the per-invocation writes and the single-chosen-invocation read, are all atomic (and the data would only be considered available after the shader completes, to the Vulkan host, i.e. the CPU).

Overall it seems like a strange historical accident, but the default in SPIR-V doesn't seem compatible with Rust semantics.

The safest thing would probably be to always add NonPrivatePointer, and remove it only for Function and Private accesses (and maybe anything that's read-only memory?) in a pass - that way, it's conservative if that pass misses anything, instead of the opposite.

There's probably also a similar issue involving NonPrivateTexel and writable images, but I haven't looked closer.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No source files, tests, or entry points are named in this migrated issue. Start by locating the code that emits SPIR-V memory operands and compare it with the linked NonPrivatePointer specification; done means accesses outside Function and Private use the operand, with coverage for the relevant cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.