Sitelet https://github.com/gpuweb/gpuweb/issues/978
Skip to content

support volatile atomics #978

Description

@dneto0

If WGSL supports atomic operations, it should support volatile atomic operations.

Since we haven't discussed atomic operations yet, it's too early to suggest syntax. We might want to use a 'volatile' keyword or attribute, or embed it in a built-in function name.

Justification:

In C++ much of the 'volatile' functionality has rightly moved into atomics. See P1152R0 Deprecating volatile

However it still has a reason to exist when used with atomics, and that use carries over into the GPU world.

Consider the following C++ program as the action of a single thread:

#include <atomic>

std::atomic<int> flag;
int main() {
  int sub_counter = 0;
  flag.store(0, std::memory_order_relaxed);
  // Wait for another thread to modify 'flag'.
  while(flag.load(std::memory_order_relaxed) == 0) {
    sub_counter++;
  }
  return sub_counter & 1;
}

The implementation is justified in the following transformation:

  • First, constrain and therefore assume a restricted set of schedules of the operations in this thread and the other signaling thread (that we don't see)
  • Therefore, assume that the atomic loads in this thread are scheduled "before" the writes in the other thread. Without progress fairness guarantees, this is justified
  • Therefore, all the atomic loads can be combined, and then moved before the loop.

So we could end up compiling into the equivalent of the following:

#include <atomic>

std::atomic<int> flag;
int main() {
  int sub_counter = 0;
  flag.store(0, std::memory_order_relaxed);
  const int loaded = flag.load(std::memory_order_relaxed);

  while(loaded == 0) {
    sub_counter++;
  }
  return sub_counter & 1;
}

This is probably not what the programmer wanted.

To the fix this, the programmer should use 'volatile' to indicate that the atomic loads on 'flag' are not to be combined with other memory operations.

Currently this is denoted in C++ by marking 'flag' itself with 'volatile'. If there were no legacy here we'd make the operation volatile, not the object itself. In SPIR-V with the Vulkan memory model, use the Volatile memory semantics bit (on atomic operations and fences/memory barriers), Volatile memory operand (on Load and Store), and VolatileTexel (on image operations).

More background:

(Actually, the signed integer overflow on sub_counter in the example is undefined behaviour and the compiler could delete the entire program or your hard drive. Changing sub_counter to unsigned fixes that issue, I think.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wgslWebGPU Shading Language Issues

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions