diff options
| author | Yong He <yonghe@outlook.com> | 2024-09-20 15:11:23 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-20 15:11:23 -0700 |
| commit | 490834924cc390cb812713c225b9a8227c66cf1f (patch) | |
| tree | 5644e2a18cb085692d5fe9625f42582db07447be /docs | |
| parent | b4c851fb1419f869bddaa08487f58376bc0a7144 (diff) | |
Initial `Atomic<T>` type implementation. (#5125)
* Initial Atomic<T> type implementation.
* Update design doc.
* Fix.
* Add test.
* Fixes and add tests.
* Fix WGSL.
* Fix glsl.
* Fix metal.
* experiemnt with github metal.
* experiment github metal 2
* github metal experiment 3
* experiment with github metal 4.
* experiment with metal 5.
* experiment 7.
* metal experiment 8.
* Fix metal tests.
---------
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/proposals/003-atomic-t.md | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/docs/proposals/003-atomic-t.md b/docs/proposals/003-atomic-t.md index 03df9bb5e..d05067714 100644 --- a/docs/proposals/003-atomic-t.md +++ b/docs/proposals/003-atomic-t.md @@ -7,11 +7,11 @@ Status Author: Yong He -Status: Design Discussion. +Status: Implementation in review. -Implementation: N/A +Implementation: [PR 5125](https://github.com/shader-slang/slang/pull/5125) -Reviewed by: N/A +Reviewed by: Theresa Foley, Jay Kwak Background ---------- @@ -31,42 +31,72 @@ Proposed Approach ----------------- We define an `Atomic<T>` type that functions as a wrapper of `T` and provides atomic operations: -``` -[sealed] interface IAtomicable {} -[sealed] interface IArithmeticAtomicable : IAtomicable {} -[sealed] interface IBitAtomicable : IArithmeticAtomicable {} +```csharp +enum MemoryOrder +{ + Relaxed = 0, + Acquire = 1, + Release = 2, + AcquireRelease = 3, + SeqCst = 4, +} -extension int : IArithmeticAtomicable {} -extension uint : IArithmeticAtomicable {} -extension int64_t : IBitAtomicable {} -extension uint64_t : IBitAtomicable {} -extension float : IArithmeticAtomicable {} -extension half : IArithmeticAtomicable {} +[sealed] interface IAtomicable {} +[sealed] interface IArithmeticAtomicable : IAtomicable, IArithmetic {} +[sealed] interface IBitAtomicable : IArithmeticAtomicable, IInteger {} +[require(cuda_glsl_hlsl_metal_spirv_wgsl)] struct Atomic<T : IAtomicable> { - T load(); - [ref] void store(T newValue); // Question: do we really need this? - [ref] T exchange(T newValue); // returns old value - [ref] T compareExchange(T compareValue, T newValue); // returns old value. + T load(MemoryOrder order = MemoryOrder.Relaxed); + + [__ref] void store(T newValue, MemoryOrder order = MemoryOrder.Relaxed); + + [__ref] T exchange(T newValue, MemoryOrder order = MemoryOrder.Relaxed); // returns old value + + [__ref] T compareExchange( + T compareValue, + T newValue, + MemoryOrder successOrder = MemoryOrder.Relaxed, + MemoryOrder failOrder = MemoryOrder.Relaxed); } -extension<T:IArithmeticAtomicable> Atomic<T> +extension<T : IArithmeticAtomicable> Atomic<T> { - [ref] T atomicAdd(T value); // returns original value - [ref] T atomicSub(T value); // returns original value - [ref] T atomicMax(T value); // returns original value - [ref] T atomicMin(T value); // returns original value - [ref] T atomicIncrement(); - [ref] T atomicDecrement(); + [__ref] T add(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T sub(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T max(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T min(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value } -extension<T:IBitAtomicable> Atomic<T> +extension<T : IBitAtomicable> Atomic<T> { - [ref] T atomicAnd(T value); // returns original value - [ref] T atomicOr(T value); // returns original value - [ref] T atomicXor(T value); // returns original value + [__ref] T and(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T or(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T xor(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T increment(MemoryOrder order = MemoryOrder.Relaxed); // returns original value + [__ref] T decrement(MemoryOrder order = MemoryOrder.Relaxed); // returns original value } + +extension int : IArithmeticAtomicable {} +extension uint : IArithmeticAtomicable {} +extension int64_t : IBitAtomicable {} +extension uint64_t : IBitAtomicable {} +extension double : IArithmeticAtomicable {} +extension float : IArithmeticAtomicable {} +extension half : IArithmeticAtomicable {} + +// Operator overloads: +// All operator overloads are using MemoryOrder.Relaxed semantics. +__prefix T operator++<T>(__ref Atomic<T> v); // returns new value. +__postfix T operator++<T>(__ref Atomic<T> v); // returns original value. +__prefix T operator--<T>(__ref Atomic<T> v); // returns new value. +__postfix T operator--<T>(__ref Atomic<T> v); // returns original value. +T operator+=(__ref Atomic<T> v, T operand); // returns new value. +T operator-=(__ref Atomic<T> v, T operand); // returns new value. +T operator|=(__ref Atomic<T> v, T operand); // returns new value. +T operator&=(__ref Atomic<T> v, T operand); // returns new value. +T operator^=(__ref Atomic<T> v, T operand); // returns new value. ``` We allow `Atomic<T>` to be defined anywhere: as struct fields, as array elements, as elements of `RWStructuredBuffer` types, |
