summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-09-20 15:11:23 -0700
committerGitHub <noreply@github.com>2024-09-20 15:11:23 -0700
commit490834924cc390cb812713c225b9a8227c66cf1f (patch)
tree5644e2a18cb085692d5fe9625f42582db07447be /docs
parentb4c851fb1419f869bddaa08487f58376bc0a7144 (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.md86
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,