summaryrefslogtreecommitdiff
path: root/tests/experiments
diff options
context:
space:
mode:
Diffstat (limited to 'tests/experiments')
-rw-r--r--tests/experiments/README.md18
-rw-r--r--tests/experiments/algorithm/find-max-2.slang45
-rw-r--r--tests/experiments/algorithm/find-max.slang41
-rw-r--r--tests/experiments/algorithm/generic-int-controlled-2.slang33
-rw-r--r--tests/experiments/algorithm/generic-int-controlled.slang35
-rw-r--r--tests/experiments/generic/README.md7
-rw-r--r--tests/experiments/generic/alternative-array-type.slang25
-rw-r--r--tests/experiments/generic/built-in-add.slang26
-rw-r--r--tests/experiments/generic/built-in-extension.slang38
-rw-r--r--tests/experiments/generic/byte-address-ptr-2.slang85
-rw-r--r--tests/experiments/generic/byte-address-ptr.slang87
-rw-r--r--tests/experiments/generic/constraint.slang35
-rw-r--r--tests/experiments/generic/enum-flags.slang46
-rw-r--r--tests/experiments/generic/enum-int-flags.slang42
-rw-r--r--tests/experiments/generic/equality-2.slang42
-rw-r--r--tests/experiments/generic/equality-3.slang40
-rw-r--r--tests/experiments/generic/equality-4.slang56
-rw-r--r--tests/experiments/generic/equality-5.slang44
-rw-r--r--tests/experiments/generic/equality.slang43
-rw-r--r--tests/experiments/generic/field-inheritance-2.slang38
-rw-r--r--tests/experiments/generic/field-inheritance.slang48
-rw-r--r--tests/experiments/generic/fixed-array-2.slang69
-rw-r--r--tests/experiments/generic/fixed-array-3.slang68
-rw-r--r--tests/experiments/generic/fixed-array-4.slang60
-rw-r--r--tests/experiments/generic/fixed-array-5.slang61
-rw-r--r--tests/experiments/generic/fixed-array.slang30
-rw-r--r--tests/experiments/generic/inheritance.slang37
-rw-r--r--tests/experiments/generic/int-generic-param.slang32
-rw-r--r--tests/experiments/generic/interface.slang31
-rw-r--r--tests/experiments/generic/matrix.slang25
-rw-r--r--tests/experiments/generic/meta-2.slang23
-rw-r--r--tests/experiments/generic/meta.slang25
-rw-r--r--tests/experiments/generic/mutating-interface.slang51
-rw-r--r--tests/experiments/generic/operator-overload.slang39
-rw-r--r--tests/experiments/generic/param-specialize-2.slang44
-rw-r--r--tests/experiments/generic/param-specialize.slang44
-rw-r--r--tests/experiments/generic/resource.slang35
-rw-r--r--tests/experiments/generic/return-generic-2.slang38
-rw-r--r--tests/experiments/generic/return-generic-3.slang26
-rw-r--r--tests/experiments/generic/return-generic-4.slang36
-rw-r--r--tests/experiments/generic/return-generic-5.slang30
-rw-r--r--tests/experiments/generic/return-generic.slang38
-rw-r--r--tests/experiments/generic/scope-type.slang36
-rw-r--r--tests/experiments/generic/scope-value-2.slang37
-rw-r--r--tests/experiments/generic/scope-value.slang34
-rw-r--r--tests/experiments/generic/tuple.slang55
-rw-r--r--tests/experiments/generic/type-inference-2.slang26
-rw-r--r--tests/experiments/generic/type-inference-3.slang29
-rw-r--r--tests/experiments/generic/type-inference-4.slang30
-rw-r--r--tests/experiments/generic/type-inference-5.slang26
-rw-r--r--tests/experiments/generic/type-inference.slang33
-rw-r--r--tests/experiments/generic/type-to-value-2.slang48
-rw-r--r--tests/experiments/generic/type-to-value-3.slang43
-rw-r--r--tests/experiments/generic/type-to-value-4.slang49
-rw-r--r--tests/experiments/generic/type-to-value-5.slang56
-rw-r--r--tests/experiments/generic/type-to-value-6.slang49
-rw-r--r--tests/experiments/generic/type-to-value.slang33
-rw-r--r--tests/experiments/interface/README.md5
-rw-r--r--tests/experiments/interface/associated-type-2.slang61
-rw-r--r--tests/experiments/interface/associated-type.slang59
-rw-r--r--tests/experiments/interface/resource-associated-type.slang63
-rw-r--r--tests/experiments/interface/return-interface-2.slang55
-rw-r--r--tests/experiments/interface/return-interface.slang50
63 files changed, 2593 insertions, 0 deletions
diff --git a/tests/experiments/README.md b/tests/experiments/README.md
new file mode 100644
index 000000000..2fb7398c2
--- /dev/null
+++ b/tests/experiments/README.md
@@ -0,0 +1,18 @@
+Experiments
+===========
+
+The tests in this directory are all disabled. This set of tests is probably only temporary, and exists to document attempts to use certain language features.
+
+There may be multiple versions of an attempt, when this is the case a number will be added to the suffix. In general tests like this can be considered to have been attempts in that order.
+
+Some of these tests *do* compile, but are kept because they provide the end of a train of thought. The solution may not be ideal, or the best way to implement in Slang. So they are kept here for completeness.
+
+Some of the issues may be due to a bug, or unimplemented feature in the compiler.
+
+Others may not work because it is not the appropriate way to achieve the desired effect.
+
+Surprising Observations
+=======================
+
+* let is needed for int generic parameter.
+
diff --git a/tests/experiments/algorithm/find-max-2.slang b/tests/experiments/algorithm/find-max-2.slang
new file mode 100644
index 000000000..3aebbc997
--- /dev/null
+++ b/tests/experiments/algorithm/find-max-2.slang
@@ -0,0 +1,45 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Find max algorithm.
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IComparable
+{
+ bool isLess(This other);
+};
+
+extension int : IComparable
+{
+ bool isLess(int other) { return this < other; }
+};
+
+T findMax<T : IComparable, let SIZE : int>(T arr[SIZE])
+{
+ T m = arr[0];
+ for (int i = 1; i < 8; ++i)
+ {
+ if (m.isLess(arr[i]))
+ {
+ m = arr[i];
+ }
+ }
+ return m;
+}
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int values[] = { 1, 3, - 1};
+
+ outputBuffer[index] = findMax<int, 3>(values);
+}
+
+
diff --git a/tests/experiments/algorithm/find-max.slang b/tests/experiments/algorithm/find-max.slang
new file mode 100644
index 000000000..ba8499013
--- /dev/null
+++ b/tests/experiments/algorithm/find-max.slang
@@ -0,0 +1,41 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Find max algorithm.
+
+Doesn't work because, can't compare T as it is any type.
+
+.slang(15): error 39999: no overload for '>' applicable to arguments of type (T, T)
+ if (arr[i] > m)
+ ^
+core.meta.slang(2572): note 39999: candidate: func >(uint64_t, uint64_t) -> bool
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+T findMax<T, let SIZE : int>(T arr[SIZE])
+{
+ T m = arr[0];
+ for (int i = 1; i < 8; ++i)
+ {
+ if (arr[i] > m)
+ {
+ m = arr[i];
+ }
+ }
+ return i;
+}
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int values[] = { 1, 3, - 1};
+
+ outputBuffer[index] = findMax(values);
+}
+
+
diff --git a/tests/experiments/algorithm/generic-int-controlled-2.slang b/tests/experiments/algorithm/generic-int-controlled-2.slang
new file mode 100644
index 000000000..52ef02336
--- /dev/null
+++ b/tests/experiments/algorithm/generic-int-controlled-2.slang
@@ -0,0 +1,33 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test to control altering of an algorithm via generic compile time values.
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+int reduce<let Clustering : int, let DupTest : int>( int a)
+{
+ if (Clustering)
+ {
+ a = a + a;
+ }
+ if (DupTest)
+ {
+ a *= a;
+ }
+ return a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int r = reduce<1, 2>(index);
+
+ outputBuffer[index] = r;
+}
+
diff --git a/tests/experiments/algorithm/generic-int-controlled.slang b/tests/experiments/algorithm/generic-int-controlled.slang
new file mode 100644
index 000000000..5f698633c
--- /dev/null
+++ b/tests/experiments/algorithm/generic-int-controlled.slang
@@ -0,0 +1,35 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test to control altering of an algorithm via generic compile time values.
+
+slang(28): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unexpected: could not resolve target declaration for call
+
+Seems like it's the default value (=1) that leads to this crash. If we explicitly specify it's ok.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+int reduce<let Clustering : int, let DupTest : int = 1>( int a)
+{
+ if (Clustering)
+ {
+ a = a + a;
+ }
+ if (DupTest)
+ {
+ a *= a;
+ }
+ return a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int r = reduce<1>(index);
+
+ outputBuffer[index] = r;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/README.md b/tests/experiments/generic/README.md
new file mode 100644
index 000000000..ae062bb11
--- /dev/null
+++ b/tests/experiments/generic/README.md
@@ -0,0 +1,7 @@
+Generic Experiments
+===================
+
+Experiement tests around generics.
+
+All tests are disabled.
+
diff --git a/tests/experiments/generic/alternative-array-type.slang b/tests/experiments/generic/alternative-array-type.slang
new file mode 100644
index 000000000..1e28a85f5
--- /dev/null
+++ b/tests/experiments/generic/alternative-array-type.slang
@@ -0,0 +1,25 @@
+//DISABLE_TEST:SIMPLE:-target hlsl -entry computeMain -profile cs_6_2
+
+/* The docs claim that for arrays we can use the 'alternate' style
+
+https://github.com/shader-slang/slang/blob/master/docs/language-reference/04-types.md
+
+> int[10] a;
+
+But that produces an error:
+
+.slang(18): error 20001: unexpected '[', expected identifier
+ int[4] a = { 1, 2, 3, 4 };
+*/
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ int[4] a = { 1, 4, 2, 1 };
+
+ outputBuffer[x] = a[x];
+}
diff --git a/tests/experiments/generic/built-in-add.slang b/tests/experiments/generic/built-in-add.slang
new file mode 100644
index 000000000..c5751fe69
--- /dev/null
+++ b/tests/experiments/generic/built-in-add.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test use of a generic with a built in doing something simple.
+
+Doesn't work because cannot find +.
+
+.slang(3): error 39999: no overload for '+' applicable to arguments of type (typeof(V), int)
+int doThing<V : int>(int b) { return V + b; }
+
+NOTE! We can fix by adding *let*
+
+int doThing<let V : int>(int b) { return V + b; }
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+int doThing<V : int>(int b) { return V + b; }
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ outputBuffer[dispatchThreadID.x] = doThing<2>(index);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/built-in-extension.slang b/tests/experiments/generic/built-in-extension.slang
new file mode 100644
index 000000000..b71e3eaa6
--- /dev/null
+++ b/tests/experiments/generic/built-in-extension.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test around extension to a built in, to allow associating types with builtins.
+
+Doesn't work
+
+.slang(22): internal error 99999: unexpected condition encountered in Slang compiler: should not appear in input syntax
+ int.Unsigned v = (int.Unsigned)10;
+
+*/
+
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+interface IIntegral
+{
+ associatedtype Unsigned;
+};
+
+extension int : IIntegral
+{
+ typedef uint Unsigned;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // Works
+ int.Unsigned u = 10;
+
+ // Doesn't work
+ int.Unsigned v = (int.Unsigned)10;
+
+ outputBuffer[dispatchThreadID.x] = doThing<2>(index);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/byte-address-ptr-2.slang b/tests/experiments/generic/byte-address-ptr-2.slang
new file mode 100644
index 000000000..895c0dba4
--- /dev/null
+++ b/tests/experiments/generic/byte-address-ptr-2.slang
@@ -0,0 +1,85 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The purpose of these tests is to use generics to be able to traverse
+a 'linked list' of different related types.
+
+tests/current-bugs/generic/byte-address-ptr-2.slang(75): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: assert failure: witnessTableVal->getOp() != kIROp_StructKey
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+
+//TEST_INPUT:ubuffer(data=[0]):name=gB
+ByteAddressBuffer gB;
+
+enum Type : int
+{
+ A,
+ B,
+ C,
+};
+
+interface IBase
+{
+ static bool isType(Type type);
+};
+
+struct Base : IBase
+{
+ static bool isType(Type type) { return true; }
+ Type type;
+};
+
+struct Ptr
+{
+ Type getType() { return gB.Load<Base>(offset).type; }
+
+ __generic<T : IBase>
+ bool isType() { return T::isType(getType()); }
+ // Changing to T : IBase causes an internal compiler crash
+ __generic<T>
+ T as()
+ {
+ // I want a way to assert if not an appropriate cast.
+ return gB.Load<T>(offset);
+ }
+ int offset;
+};
+
+struct A : Base
+{
+ static bool isType(Type type) { return type == Type::A; }
+ Ptr next;
+ int something;
+};
+
+struct B : Base
+{
+ static bool isType(Type type) { return type == Type::C || type == Type::B; }
+ int someData;
+};
+
+struct C : B
+{
+ static bool isType(Type type) { return type == Type::C; }
+ int somethingElse;
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ Ptr ptr = { 0 };
+ int total = 0;
+
+ while (ptr.isType<A>())
+ {
+ A a = ptr.as<A>();
+ total += a.something;
+
+ ptr = a.next;
+ }
+
+ outputBuffer[dispatchThreadID.x] = total;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/byte-address-ptr.slang b/tests/experiments/generic/byte-address-ptr.slang
new file mode 100644
index 000000000..33096b70f
--- /dev/null
+++ b/tests/experiments/generic/byte-address-ptr.slang
@@ -0,0 +1,87 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The purpose of these tests is to use generics to be able to traverse
+a 'linked list' of different related types.
+
+tests/current-bugs/generic/byte-address-ptr.slang(77): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: assert failure: witnessTableVal->getOp() != kIROp_StructKey
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+
+//TEST_INPUT:ubuffer(data=[0]):name=gB
+ByteAddressBuffer gB;
+
+enum Type : int
+{
+ A,
+ B,
+ C,
+};
+
+interface IBase
+{
+ static bool isType(Type type);
+};
+
+struct Base : IBase
+{
+ static bool isType(Type type) { return true; }
+ Type type;
+};
+
+struct Ptr
+{
+ Type getType() { return gB.Load<Base>(offset).type; }
+
+ __generic<T : IBase>
+ bool isType() { return T::isType(getType()); }
+ // Changing to T : IBase causes an internal compiler crash
+ __generic<T : IBase>
+ T as()
+ {
+ bool isOk = isType<T>();
+ // I want a way to assert!
+ // assert(isOk);
+ return gB.Load<T>(offset);
+ }
+ int offset;
+};
+
+struct A : Base
+{
+ static bool isType(Type type) { return type == Type::A; }
+ Ptr next;
+ int something;
+};
+
+struct B : Base
+{
+ static bool isType(Type type) { return type == Type::C || type == Type::B; }
+ int someData;
+};
+
+struct C : B
+{
+ static bool isType(Type type) { return type == Type::C; }
+ int somethingElse;
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ Ptr ptr = { 0 };
+ int total = 0;
+
+ while (ptr.isType<A>())
+ {
+ A a = ptr.as<A>();
+ total += a.something;
+
+ ptr = a.next;
+ }
+
+ outputBuffer[dispatchThreadID.x] = total;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/constraint.slang b/tests/experiments/generic/constraint.slang
new file mode 100644
index 000000000..7143d3fd4
--- /dev/null
+++ b/tests/experiments/generic/constraint.slang
@@ -0,0 +1,35 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test is to try and see what effects type constraints have.
+
+This is a bit of a silly example.
+
+Fails with
+
+.slang(23): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unimplemented: value lowering
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum XXX {};
+
+__generic<T : XXX>
+Enum getEnum(T i)
+{
+ return Enum::A;
+}
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ XXX x;
+ let e = getEnum(x);
+
+ outputBuffer[index] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/enum-flags.slang b/tests/experiments/generic/enum-flags.slang
new file mode 100644
index 000000000..0ae992e6a
--- /dev/null
+++ b/tests/experiments/generic/enum-flags.slang
@@ -0,0 +1,46 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics to treat an enum as a set.
+
+.slang(15): error 30060: expected a type, got a '__BuiltinIntegerType'
+ B value = 0;
+
+.slang(23): error 30019: expected an expression of type 'int', got 'typeof(uint8_t)'
+ Flags<Enum, uint8_t> flags;
+ ^~~~~~~
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+enum Enum
+{
+ A = 0x1,
+ B = 0x2,
+ C = 0x4,
+};
+
+__generic<E, let B : __BuiltinIntegerType>
+struct Flags
+{
+ [mutating] void set(E e) { value |= (B)e; }
+ void isSet(E e) { return (((B)e) & value) != 0; }
+ B value = 0;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Flags<Enum, uint8_t> flags;
+
+ if (index & 1)
+ {
+ flags.set(Enum::A);
+ }
+ bool isASet = flags.isSet(Enum::A);
+
+ outputBuffer[index] = isASet ? 2 : 1;
+}
+
diff --git a/tests/experiments/generic/enum-int-flags.slang b/tests/experiments/generic/enum-int-flags.slang
new file mode 100644
index 000000000..d35b7e6ab
--- /dev/null
+++ b/tests/experiments/generic/enum-int-flags.slang
@@ -0,0 +1,42 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics to treat an enum as a set. */
+/* Doesn't work because doesn't know can convert E into an int type.
+
+If E could be specified as any enum type then perhaps this could work.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+enum Enum
+{
+ A = 0x1,
+ B = 0x2,
+ C = 0x4,
+};
+
+__generic<E>
+struct Flags
+{
+ [mutating] void set(E e) { value |= (int)e; }
+ void isSet(E e) { return (((int)e) & value) != 0; }
+ int value = 0;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Flags<Enum> flags;
+
+ if (index & 1)
+ {
+ flags.set(Enum::A);
+ }
+ bool isASet = flags.isSet(Enum::A);
+
+ outputBuffer[index] = isASet ? 2 : 1;
+}
+
diff --git a/tests/experiments/generic/equality-2.slang b/tests/experiments/generic/equality-2.slang
new file mode 100644
index 000000000..8a1f87463
--- /dev/null
+++ b/tests/experiments/generic/equality-2.slang
@@ -0,0 +1,42 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+This does work.
+
+It is here, because it seems like an awkward to do things, and only applys to struct like types.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ bool isEqual(Type rhs);
+};
+
+struct A : IEquality
+{
+ typedef A Type;
+ bool isEqual(IEquality rhs)
+ {
+ return value == rhs.value;
+ }
+ int value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ A a = { 1 };
+ A b = { 2 };
+
+ bool isEqual = a.isEqual(b);
+
+ outputBuffer[index] = 1 + int(isEqual);
+}
+
+
diff --git a/tests/experiments/generic/equality-3.slang b/tests/experiments/generic/equality-3.slang
new file mode 100644
index 000000000..e5e42aedf
--- /dev/null
+++ b/tests/experiments/generic/equality-3.slang
@@ -0,0 +1,40 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+This style is discussed in the documentation here:
+
+Still has limitiation that it only works for an an implementation of an interface.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ bool isEqual(This other);
+}
+
+struct A : IEquality
+{
+ bool isEqual(This other)
+ {
+ return value == other.value;
+ }
+ int value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ A a = { 1 };
+ A b = { 2 };
+
+ bool isEqual = a.isEqual(b);
+
+ outputBuffer[index] = 1 + int(isEqual);
+}
+
+
diff --git a/tests/experiments/generic/equality-4.slang b/tests/experiments/generic/equality-4.slang
new file mode 100644
index 000000000..44c049323
--- /dev/null
+++ b/tests/experiments/generic/equality-4.slang
@@ -0,0 +1,56 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+Here again trying to apply equality *outside* of the types (MyStruct) definition.
+
+Doesn't work:
+
+.slang(24): error 30019: expected an expression of type 'Type', got 'T'
+ return T::isEqual(a, b);
+
+Note! This may be somewhat of a silly example for equality. We could get what we want here by just
+implementing 'isEqual(MyStruct a, MyStruct b)` as a free function and use overloading.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+}
+
+extension MyStruct : IEquality
+{
+ // Do I need this? Is the type This?
+ typedef MyStruct Type;
+ static bool isEqual(Type a, Type b) { return a.a == b.a; }
+};
+
+__generic<T : IEquality>
+bool isEqual(T a, T b)
+{
+ return T::isEqual(a, b);
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ MyStruct a = { 1 };
+ MyStruct b = { 2 };
+
+ bool res = isEqual(a, b);
+
+ outputBuffer[index] = 1 + int(res);
+}
+
+
diff --git a/tests/experiments/generic/equality-5.slang b/tests/experiments/generic/equality-5.slang
new file mode 100644
index 000000000..41cadbbfc
--- /dev/null
+++ b/tests/experiments/generic/equality-5.slang
@@ -0,0 +1,44 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+This is an attempt to get the *outside* impl of equality to work. The simple case does, but just to throw
+a spanner in the works, lets mix in some inheritance.
+
+An issue here (perhaps) is that this will compile - the isEqual implementation will just slice and probably not do what the implementer expected.
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+struct MyStruct2 : MyStruct
+{
+ int b;
+};
+
+bool isEqual(MyStruct a, MyStruct b)
+{
+ return a.a == b.a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // I *suppose* it could be argued that this is problematic - that the b field is uninitialized
+ // but there is no warning or an error.
+
+ MyStruct2 a = { 1 };
+ MyStruct2 b = { 2 };
+
+ bool res = isEqual(a, b);
+
+ outputBuffer[index] = 1 + int(res);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/equality.slang b/tests/experiments/generic/equality.slang
new file mode 100644
index 000000000..eb4569df5
--- /dev/null
+++ b/tests/experiments/generic/equality.slang
@@ -0,0 +1,43 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test for equality around interface types
+
+Doesn't work because
+
+.slang(8): error 38100: type 'A' does not provide required interface member 'isEqual'
+struct A : IEquality
+ ^~~~~~~~~
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ bool isEqual(IEquality rhs);
+};
+
+struct A : IEquality
+{
+ bool isEqual(IEquality rhs)
+ {
+ // Hmm. How can I cant query rhs, and then cast, so not clear how to implement
+ return true;
+ }
+ int value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ A a = { 1 };
+ A b = { 2 };
+
+ bool isEqual = a.isEqual(b);
+
+ outputBuffer[index] = 1 + int(isEqual);
+}
+
+
diff --git a/tests/experiments/generic/field-inheritance-2.slang b/tests/experiments/generic/field-inheritance-2.slang
new file mode 100644
index 000000000..af3a153b4
--- /dev/null
+++ b/tests/experiments/generic/field-inheritance-2.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The test is for behavior with inheritance and two fields with the same name.
+
+.slang(24): error 39999: no overload for 'int' applicable to arguments of type (overload group)
+ outputBuffer[index] = 1 + int(a.a);
+
+Looks like the problem is that it sees 'a' as 'overloaded' - which I guess is one way to look at it. It is then followed with ...
+
+core.meta.slang(230): note 39999: candidate: int.init(uint64_t)
+core.meta.slang(230): note 39999: candidate: int.init(uint)
+
+Which doesn't seem appropriate
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+struct MyStruct2 : MyStruct
+{
+ int a = 10;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ MyStruct2 a;
+
+ outputBuffer[index] = 1 + int(a.a);
+}
+
diff --git a/tests/experiments/generic/field-inheritance.slang b/tests/experiments/generic/field-inheritance.slang
new file mode 100644
index 000000000..593ee81f1
--- /dev/null
+++ b/tests/experiments/generic/field-inheritance.slang
@@ -0,0 +1,48 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* The test here uses struct inheritance but has a field with the same name in the derived type.
+
+This error is for the MyStruct2 version.
+
+.slang(20): error 39999: no overload for '==' applicable to arguments of type (overload group, overload group)
+ return a.a == b.a;
+
+No error/warning is given for the shadowing of MyStruct.a.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct MyStruct
+{
+ int a = 10;
+};
+
+struct MyStruct2 : MyStruct
+{
+ int a = 10;
+};
+
+bool isEqual(MyStruct a, MyStruct b)
+{
+ return a.a == b.a;
+}
+
+bool isEqual(MyStruct2 a, MyStruct2 b)
+{
+ return a.a == b.a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ MyStruct a = { 1 };
+ MyStruct b = { 2 };
+
+ bool res = isEqual(a, b);
+
+ outputBuffer[index] = 1 + int(res);
+}
+
diff --git a/tests/experiments/generic/fixed-array-2.slang b/tests/experiments/generic/fixed-array-2.slang
new file mode 100644
index 000000000..00024f80e
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-2.slang
@@ -0,0 +1,69 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Here we just fix the array size, so can test out other characteristics.
+
+indexOf can't compile because v == elements[i] cannot determine equality.
+
+It would seem like I should have an IEquality interface, that I could then make
+a T require.
+
+Doesn't work because
+
+.slang(29): error 30019: expected an expression of type 'Type', got 'T'
+ if (T::isEqual(v, elements[i]))
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+};
+
+extension int : IEquality
+{
+ typedef int Type;
+ static bool isEqual(Type a, Type b)
+ {
+ return a == b;
+ }
+};
+
+
+struct FixedArray<T : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (T::isEqual(v, elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
+
diff --git a/tests/experiments/generic/fixed-array-3.slang b/tests/experiments/generic/fixed-array-3.slang
new file mode 100644
index 000000000..16c4c9931
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-3.slang
@@ -0,0 +1,68 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Here we just fix the array size, so can test out other characteristics.
+
+indexOf can't compile because v == elements[i] cannot determine equality.
+
+It would seem like I should have an IEquality interface, that I could then make
+a T require.
+
+Doesn't work because
+
+.slang(29): error 30019: expected an expression of type 'Type', got 'T'
+ if (T::isEqual(v, elements[i]))
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+};
+
+extension int : IEquality
+{
+ typedef int Type;
+ static bool isEqual(Type a, Type b)
+ {
+ return a == b;
+ }
+};
+
+
+struct FixedArray<T : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (T::isEqual(v, elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
diff --git a/tests/experiments/generic/fixed-array-4.slang b/tests/experiments/generic/fixed-array-4.slang
new file mode 100644
index 000000000..bf58398d0
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-4.slang
@@ -0,0 +1,60 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+/* Here is an attempt to provide an interface to check equality.
+But is the definition right anyway? Really I want the This and Type to be
+the same type. I guess this enforces that but in an odd manner.
+*/
+interface IEquality
+{
+ associatedtype Type;
+ bool isEqual(Type rhs);
+};
+
+extension int : IEquality
+{
+ typedef int Type;
+ bool isEqual(Type rhs)
+ {
+ // This use of `this` is going to seem odd to a C++ programmer
+ return this == rhs;
+ }
+};
+
+struct FixedArray<T : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (v.isEqual(elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
diff --git a/tests/experiments/generic/fixed-array-5.slang b/tests/experiments/generic/fixed-array-5.slang
new file mode 100644
index 000000000..6d0c6f8b9
--- /dev/null
+++ b/tests/experiments/generic/fixed-array-5.slang
@@ -0,0 +1,61 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Here the attempt is to make the equality test separate from the type.
+This isn't a great answer because it relies on the right types set
+for T and E to work together.
+
+This doesn't work because...
+.slang(25): error 30019: expected an expression of type 'Type', got 'T'
+ if (E::isEqual(v, elements[i]))
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+interface IEquality
+{
+ associatedtype Type;
+ static bool isEqual(Type a, Type b);
+};
+
+struct IntEquality : IEquality
+{
+ typedef int Type;
+ static bool isEqual(Type a, Type b) { return a == b; }
+};
+
+struct FixedArray<T, E : IEquality>
+{
+ static const int SIZE = 4;
+
+ [mutating] void setAt(int i, T value) { elements[i] = value; }
+ T getAt(int i) { return elements[i]; }
+ int indexOf(T v)
+ {
+ for (int i = 0; i < SIZE; ++i)
+ {
+ if (E::isEqual(v, elements[i]))
+ {
+ return i;
+ }
+ return -1;
+ }
+ }
+ T elements[SIZE];
+};
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int, IntEquality> arr;
+ arr.setAt(0, index);
+
+ outputBuffer[index] = 1 + arr.getAt(0);
+}
+
diff --git a/tests/experiments/generic/fixed-array.slang b/tests/experiments/generic/fixed-array.slang
new file mode 100644
index 000000000..8f8335aa2
--- /dev/null
+++ b/tests/experiments/generic/fixed-array.slang
@@ -0,0 +1,30 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around use of an array like container.
+
+Has error:
+
+.slang(5): error 30019: expected an expression of type 'int', got 'typeof(SIZE)'
+ T elements[SIZE];
+
+Problem here is SIZE doesn't have *let* in front. The error doesn't provide any useful insight into that. It's also not entirely clear *why* let is needed. Presumably because it's not a type?
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+struct FixedArray<T, SIZE : int>
+{
+ T elements[SIZE];
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ FixedArray<int, 8> arr;
+
+ outputBuffer[index] = 1;
+}
+
diff --git a/tests/experiments/generic/inheritance.slang b/tests/experiments/generic/inheritance.slang
new file mode 100644
index 000000000..6374ccd7f
--- /dev/null
+++ b/tests/experiments/generic/inheritance.slang
@@ -0,0 +1,37 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Tests around inheritance.
+
+Works.
+
+Docs state inheritance isn't available (although states it might in the future).
+
+https://github.com/shader-slang/slang/blob/master/docs/language-reference/07-declarations.md
+
+> Currently only interface types may be named in the inheritance clause of a structure type. When a structure type declares that it inherits from an interface, the programmer asserts that the structure type implements the required members of the interface.
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct A<T>
+{
+ T a;
+};
+
+struct B : A<float>
+{
+ int b;
+};
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ B b = { 1, 2 + index };
+
+ outputBuffer[index] = b.b * b.a;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/int-generic-param.slang b/tests/experiments/generic/int-generic-param.slang
new file mode 100644
index 000000000..f2f5ebb14
--- /dev/null
+++ b/tests/experiments/generic/int-generic-param.slang
@@ -0,0 +1,32 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test around integer generic parameters.
+
+Fails with:
+
+.slang(7): error 30019: expected an expression of type 'int', got 'typeof(N)'
+ return N;
+
+This is like *fixed-array.slang*. It needs let.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+int getN<N : int>()
+{
+ return N;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getN<10>();
+
+ outputBuffer[index] = val;
+}
+
diff --git a/tests/experiments/generic/interface.slang b/tests/experiments/generic/interface.slang
new file mode 100644
index 000000000..d1d8c60ab
--- /dev/null
+++ b/tests/experiments/generic/interface.slang
@@ -0,0 +1,31 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Tests around interface/generics
+
+.slang(7): error 20001: unexpected '<', expected '{'
+interface IThing<T>
+*/
+
+// Docs say this should work...
+// https://github.com/shader-slang/slang/blob/master/docs/language-reference/07-declarations.md
+
+interface IThing<T>
+{
+ T get();
+};
+
+struct X : IThing<int>
+{
+ int get() { return 10; }
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ X x;
+ IThing<int> i = x;
+
+ outputBuffer[index] = i.get();
+} \ No newline at end of file
diff --git a/tests/experiments/generic/matrix.slang b/tests/experiments/generic/matrix.slang
new file mode 100644
index 000000000..c55c7be33
--- /dev/null
+++ b/tests/experiments/generic/matrix.slang
@@ -0,0 +1,25 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics around resource/built in types.
+
+CRASHES the compiler.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Another<let W : int, let H : int>
+{
+ matrix<float, W, H> values;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Another<2, 4> a = {};
+
+ outputBuffer[index] = index;
+}
+
diff --git a/tests/experiments/generic/meta-2.slang b/tests/experiments/generic/meta-2.slang
new file mode 100644
index 000000000..98ae09ce5
--- /dev/null
+++ b/tests/experiments/generic/meta-2.slang
@@ -0,0 +1,23 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test meta programing.
+
+CRASHES the compiler(!). Stack overrun.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct GetValue<let N : int>
+{
+ static const int Value = N;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ outputBuffer[index] = GetValue<10>::Value;
+}
+
diff --git a/tests/experiments/generic/meta.slang b/tests/experiments/generic/meta.slang
new file mode 100644
index 000000000..8304593b5
--- /dev/null
+++ b/tests/experiments/generic/meta.slang
@@ -0,0 +1,25 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test meta programing.
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct GetVector4<T>
+{
+ typedef vector<T, 4> Value;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ GetVector4<float>::Value v = { 1, 2, 3, 4 };
+
+ outputBuffer[index] = dot(v, v);
+}
+
diff --git a/tests/experiments/generic/mutating-interface.slang b/tests/experiments/generic/mutating-interface.slang
new file mode 100644
index 000000000..2198b56b2
--- /dev/null
+++ b/tests/experiments/generic/mutating-interface.slang
@@ -0,0 +1,51 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test using interfaces with mutation.
+
+Doesn't work because
+
+.slang(18): error 30050: mutating method 'lock' cannot be called on an immutable value
+ lockable.lock();
+
+If that section is removed we get on `doThing(count)`
+
+.slang(31): error 30047: argument passed to parameter '0' must be l-value.
+
+Which perhaps means an inteface cannot be used as a lvalue?
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+interface ILockable
+{
+ [mutating] void lock();
+ [mutating] void unlock();
+};
+
+struct IntCount : ILockable
+{
+ [mutating] void lock() { count ++; }
+ [mutating] void unlock() { --count; }
+ int count = 0;
+};
+
+int doThing(inout ILockable lockable)
+{
+ lockable.lock();
+ // do something...
+
+ lockable.unlock();
+ return 0;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ IntCount count;
+ doThing(count);
+
+ outputBuffer[dispatchThreadID.x] = count.count;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/operator-overload.slang b/tests/experiments/generic/operator-overload.slang
new file mode 100644
index 000000000..590322171
--- /dev/null
+++ b/tests/experiments/generic/operator-overload.slang
@@ -0,0 +1,39 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is test out operator overloading. This may not be a feature
+that works in user code (it is used within the stdlib).
+
+This produces:
+.slang(10): error 30019: expected an expression of type 'Vec2d', got 'double'
+ return {a.x + b.x, a.y + b.y};
+
+Moreover...
+
+.slang(18): error 30019: expected an expression of type 'Vec2d', got 'int'
+ int a = 10 + 11;
+
+It's as if only this operator+ impl can now be seen.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Vec2d
+{
+ double x, y;
+};
+
+Vec2d operator+(Vec2d a, Vec2d b)
+{
+ return {a.x + b.x, a.y + b.y};
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int a = 10 + 11;
+
+ outputBuffer[dispatchThreadID.x] = int(v);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/param-specialize-2.slang b/tests/experiments/generic/param-specialize-2.slang
new file mode 100644
index 000000000..04dc2f61c
--- /dev/null
+++ b/tests/experiments/generic/param-specialize-2.slang
@@ -0,0 +1,44 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* This test trys to specialize an algorithm through generic parameters.
+
+Using parameters in this way ensures the algorithm in function form
+will have those values known at compile time, and presumably lead to a specialized version.
+
+Here (with 1 == 1) it's testing if a compile time knowable expression can be used.
+
+Does not work because
+
+.slang(25): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unexpected: ErrorType
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+// NOTE! Here we don't have let!
+int doThing<a : bool, b : int, c : Enum>()
+{
+ //if (a)
+ {
+ return 1;
+ }
+ return 0;
+ //return a ? b + b + int(c) : b - int(c);
+}
+
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let v = doThing<1 == 1, false, Enum::A>();
+
+ outputBuffer[dispatchThreadID.x] = v;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/param-specialize.slang b/tests/experiments/generic/param-specialize.slang
new file mode 100644
index 000000000..cff623827
--- /dev/null
+++ b/tests/experiments/generic/param-specialize.slang
@@ -0,0 +1,44 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* This test trys to specialize an algorithm through generic parameters.
+
+Using parameters in this way ensures the algorithm in function form
+will have those values known at compile time, and presumably lead to a specialized version.
+
+Does not work because
+
+.slang(24): error 30019: expected an expression of type 'int', got 'Enum'
+ let v = doThing<true, false, Enum::A>();
+ ^
+
+Note that docs say doesn't support any other than int, but error is a bit confusing. No error at declaration.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+int doThing<let a : bool, let b : int, let c : Enum>()
+{
+ if (a)
+ {
+ return 1;
+ }
+ return 0;
+ // A more complex scenario
+ //return a ? b + b + int(c) : b - int(c);
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let v = doThing<true, false, Enum::A>();
+
+ outputBuffer[dispatchThreadID.x] = v;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/resource.slang b/tests/experiments/generic/resource.slang
new file mode 100644
index 000000000..51cd8a00f
--- /dev/null
+++ b/tests/experiments/generic/resource.slang
@@ -0,0 +1,35 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test to use generics around resource/built in types.
+
+This test shouldn't compile (wrong type for the Texture1D, but gives this error, which doesn't really explain the problem.
+
+.slang(19): error 30019: expected an expression of type 'Texture1D', got 'Texture1D'
+ a.tex = tex;
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+// NOTE! This is purposefully wrong to test tex type checking
+Texture1D<float> tex;
+
+struct Another<T>
+{
+ T z;
+ Texture1D<T> tex;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Another<int> a;
+
+ a.z = index;
+ a.tex = tex;
+
+ outputBuffer[index] = a.z + a.tex.Load(index);
+}
+
diff --git a/tests/experiments/generic/return-generic-2.slang b/tests/experiments/generic/return-generic-2.slang
new file mode 100644
index 000000000..487b20e44
--- /dev/null
+++ b/tests/experiments/generic/return-generic-2.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct. types.
+
+Failed:
+
+.slang(20): note 99999: an internal error threw an exception while working on code near this location
+(0): error 99999: Slang compilation aborted due to an exception of class Slang::InternalError: unexpected: ErrorType
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+// NOTE, that really I'd prefer, but that won't work because
+// the : int doesn't currently allow
+// vector<T, SIZE> makeVector4<T, SIZE : int>(T values[SIZE])
+
+vector<T> makeVector4<T>(T values[4])
+{
+ vector<T, 4> v;
+ v.x = values[0];
+ v.y = values[1];
+ v.z = values[2];
+ v.w = values[3];
+ return v;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float values[] = { 1, 2, 3, 4};
+
+ let vec = makeVector4<float>(values);
+
+ outputBuffer[index] = dot(vec, vec);
+}
diff --git a/tests/experiments/generic/return-generic-3.slang b/tests/experiments/generic/return-generic-3.slang
new file mode 100644
index 000000000..9d6997deb
--- /dev/null
+++ b/tests/experiments/generic/return-generic-3.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct.
+
+Works, and deduces the input type of broadcast.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+vector<T, 4> broadcast4<T>(T v)
+{
+ vector<T, 4> vec;
+ vec.x = vec.y = vec.z = vec.w = v;
+ return vec;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let vec = broadcast4(2.0f);
+
+ outputBuffer[index] = dot(vec, vec);
+}
diff --git a/tests/experiments/generic/return-generic-4.slang b/tests/experiments/generic/return-generic-4.slang
new file mode 100644
index 000000000..d9454169e
--- /dev/null
+++ b/tests/experiments/generic/return-generic-4.slang
@@ -0,0 +1,36 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct. types.
+
+Was unable to determine T
+
+Failed:
+
+.slang(35): error 39999: could not specialize generic for arguments of type (float[4])
+ let vec = makeVector4(values);
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+vector<T> makeVector4<T>(T values[4])
+{
+ vector<T, 4> v;
+ v.x = values[0];
+ v.y = values[1];
+ v.z = values[2];
+ v.w = values[3];
+ return v;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float values[] = { 1, 2, 3, 4};
+
+ let vec = makeVector4(values);
+
+ outputBuffer[index] = dot(vec, vec);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/return-generic-5.slang b/tests/experiments/generic/return-generic-5.slang
new file mode 100644
index 000000000..34b90605f
--- /dev/null
+++ b/tests/experiments/generic/return-generic-5.slang
@@ -0,0 +1,30 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct (of built in type).
+
+Note somewhat silly example because could just use float4(2.0f)
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+vector<T, N> broadcast<T, let N : int>(T v)
+{
+ vector<T, N> vec;
+ for (int i = 0; i < N; ++i)
+ {
+ vec[i] = v;
+ }
+
+ return vec;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+ let vec = broadcast<float, 4>(2.0f);
+ outputBuffer[index] = dot(vec, vec);
+}
diff --git a/tests/experiments/generic/return-generic.slang b/tests/experiments/generic/return-generic.slang
new file mode 100644
index 000000000..d107bdafe
--- /dev/null
+++ b/tests/experiments/generic/return-generic.slang
@@ -0,0 +1,38 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic function returning a generic struct. types.
+
+Since T could be any type, the compiler can't determine if it's convertable from an int. That may be surprising.
+
+Fails because:
+
+.slang(11): error 30019: expected an expression of type 'T', got 'int'
+ a.value = i;
+ ^
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Another<T>
+{
+ T value;
+};
+
+Another<T> getAnother<T>(int i)
+{
+ Another<T> a;
+ a.value = i;
+ return a;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ Another<int> a = getAnother<int>(index);
+
+ outputBuffer[index] = a.value;
+}
+
diff --git a/tests/experiments/generic/scope-type.slang b/tests/experiments/generic/scope-type.slang
new file mode 100644
index 000000000..01c9bfc62
--- /dev/null
+++ b/tests/experiments/generic/scope-type.slang
@@ -0,0 +1,36 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This may be a similar problem as with scope-value-2.slang.
+This doesn't work *only* if Thing derives from IIntegral. Remove that and it's fine.
+
+.slang(19): internal error 99999: unexpected condition encountered in Slang compiler: should not appear in input syntax
+ let v = (Thing::Unsigned)10;
+ ^~
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+interface IIntegral
+{
+ associatedtype Unsigned;
+};
+
+struct Thing : IIntegral
+{
+ typedef uint Unsigned;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // Doesn't work
+ let v = (Thing::Unsigned)10;
+
+ outputBuffer[dispatchThreadID.x] = int(v);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/scope-value-2.slang b/tests/experiments/generic/scope-value-2.slang
new file mode 100644
index 000000000..9b30934b4
--- /dev/null
+++ b/tests/experiments/generic/scope-value-2.slang
@@ -0,0 +1,37 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Doesn't work
+D:\local\Temp\a3393a41-6d61-4049-816b-4edcc04f47fb.slang(24): error 30027: 'kE' is not a member of 'overload group'.
+ let e = A::Type::kE;
+
+The only change here was to make A implement IHasType
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IHasType
+{
+ associatedtype Type;
+};
+
+struct A : IHasType
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+ let e = A::Type::kE;
+ outputBuffer[index] = int(e);
+}
diff --git a/tests/experiments/generic/scope-value.slang b/tests/experiments/generic/scope-value.slang
new file mode 100644
index 000000000..8b71c7dcc
--- /dev/null
+++ b/tests/experiments/generic/scope-value.slang
@@ -0,0 +1,34 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Works
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+struct A
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+struct B
+{
+ typedef B Type;
+ static const Enum kE = Enum::B;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+ let e = B::Type::kE;
+ outputBuffer[index] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/tuple.slang b/tests/experiments/generic/tuple.slang
new file mode 100644
index 000000000..e5362ed6e
--- /dev/null
+++ b/tests/experiments/generic/tuple.slang
@@ -0,0 +1,55 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Tuple experiment.
+
+Works.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+struct Tuple2<T0, T1>
+{
+ T0 _0;
+ T1 _1;
+};
+
+struct Tuple3<T0, T1, T2>
+{
+ T0 _0;
+ T1 _1;
+ T2 _2;
+};
+
+Tuple2<T0, T1> makeTuple<T0, T1>(T0 t0, T1 t1)
+{
+ Tuple2<T0, T1> t;
+ t._0 = t0;
+ t._1 = t1;
+ return t;
+}
+
+Tuple3<T0, T1, T2> makeTuple<T0, T1, T2>(T0 t0, T1 t1, T2 t2)
+{
+ Tuple3<T0, T1, T2> t;
+ t._0 = t0;
+ t._1 = t1;
+ t._2 = t2;
+ return t;
+}
+
+int doThing(Tuple2<float, int> v)
+{
+ return v._0 + v._1;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let t = makeTuple(index + 1.0f, index - 1);
+
+ outputBuffer[index] = doThing(t);
+}
+
diff --git a/tests/experiments/generic/type-inference-2.slang b/tests/experiments/generic/type-inference-2.slang
new file mode 100644
index 000000000..5108ec90d
--- /dev/null
+++ b/tests/experiments/generic/type-inference-2.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+Does work.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T>(vector<T, 4> val)
+{
+ return val.x;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference-3.slang b/tests/experiments/generic/type-inference-3.slang
new file mode 100644
index 000000000..82691d8c3
--- /dev/null
+++ b/tests/experiments/generic/type-inference-3.slang
@@ -0,0 +1,29 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+.slang(5): internal error 99999: unimplemented feature in Slang compiler: swizzle on vector of unknown size
+ return val.x;
+
+Sort of plausible and in general. But .x would work for any size of vector.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T, let N : int>(vector<T, N> val)
+{
+ return val.x;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference-4.slang b/tests/experiments/generic/type-inference-4.slang
new file mode 100644
index 000000000..cee29e440
--- /dev/null
+++ b/tests/experiments/generic/type-inference-4.slang
@@ -0,0 +1,30 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+Fails in glslang.
+
+glslang: .slang(13): error : '[' : vector index out of range '2'
+glslang: .slang(13): error : '' : compilation terminated
+glslang: note : ERROR: 2 compilation errors. No code generated.
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T, let N : int>(vector<T, N> val)
+{
+ return val[2];
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float2 values = { 1, 2 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference-5.slang b/tests/experiments/generic/type-inference-5.slang
new file mode 100644
index 000000000..8254f6065
--- /dev/null
+++ b/tests/experiments/generic/type-inference-5.slang
@@ -0,0 +1,26 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+Works(!) (even though any swizzle does not)
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T getFirst<T, let N : int>(vector<T, N> val)
+{
+ return val[2];
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float4 values = { 1, 2, 3, 4 };
+
+ let val = getFirst(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-inference.slang b/tests/experiments/generic/type-inference.slang
new file mode 100644
index 000000000..5c8d7efe7
--- /dev/null
+++ b/tests/experiments/generic/type-inference.slang
@@ -0,0 +1,33 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* A test of a generic functions with type inference.
+
+.slang(17): error 39999: could not specialize generic for arguments of type (float[4])
+ let val = get0(values);
+ ^
+.slang(5): note 39999: see declaration of func get0<T>(T[4]) -> T
+
+ */
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+T get0<T>(T values[4])
+{
+ return values[0];
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ float values[] = { 1, 2, 3, 4};
+
+ // NOTE if we specify T then this works. Ie
+ // let val = get0<float>(values);
+
+ let val = get0(values);
+
+ outputBuffer[index] = val;
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-2.slang b/tests/experiments/generic/type-to-value-2.slang
new file mode 100644
index 000000000..1be4e59fc
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-2.slang
@@ -0,0 +1,48 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Lets see if we can do something with a built in type
+
+Doesn't work because
+
+error 30052: invalid swizzle pattern 'getType' on type 'int'
+ let type = i.getType();
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Type
+{
+ Unknown,
+ Float,
+ Int,
+};
+
+interface IHasType
+{
+ Type getType()
+};
+
+extension int : IHasType
+{
+ Type getType() { return Type::Int; }
+};
+
+extension float : IHasType
+{
+ Type getType() { return Type::Float; }
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ int i;
+ let type = i.getType();
+
+ outputBuffer[dispatchThreadID.x] = int(type);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-3.slang b/tests/experiments/generic/type-to-value-3.slang
new file mode 100644
index 000000000..773c0fe5c
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-3.slang
@@ -0,0 +1,43 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This does work.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Type
+{
+ Unknown,
+ Float,
+ Int,
+};
+
+interface IHasType
+{
+ static Type getType();
+};
+
+extension int : IHasType
+{
+ static Type getType() { return Type::Int; }
+};
+
+extension float : IHasType
+{
+ static Type getType() { return Type::Float; }
+};
+
+Type getType<T : IHasType>() { return T::getType(); }
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let type = getType<float>();
+
+ outputBuffer[dispatchThreadID.x] = int(type);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-4.slang b/tests/experiments/generic/type-to-value-4.slang
new file mode 100644
index 000000000..986fffaf7
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-4.slang
@@ -0,0 +1,49 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This doesn't work - it produces dynamic dispatch code, that is uncompilable because cases
+are missing.
+
+.slang(24): error : control reaches end of non-void function [-Wreturn-type]
+dxc: note : }
+dxc: note : ^
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IGetE
+{
+ static Enum getE();
+};
+
+struct A : IGetE
+{
+ static Enum getE() { return Enum::A; }
+};
+
+struct B : IGetE
+{
+ static Enum getE() { return Enum::B; }
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ // Err.. even though IGetE doesn't require an instanciation, not clear how to set it. So lets try with instanciation
+ B b;
+ IGetE g = b;
+
+ let e = g.getE();
+
+ outputBuffer[dispatchThreadID.x] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-5.slang b/tests/experiments/generic/type-to-value-5.slang
new file mode 100644
index 000000000..ce3271d47
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-5.slang
@@ -0,0 +1,56 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Here we try to associate by having a value defined on the type, and then set the type
+on the associated type.
+
+Doesn't work because ...
+
+.slang(29): error 30027: 'Type' is not a member of '.This'.
+ return e::Type::kE;
+
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IHasType
+{
+ associatedtype Type;
+};
+
+// This is a little perverse, because I'm defining as an associated type that is
+// the same as itself
+struct A : IHasType
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+struct B : IHasType
+{
+ typedef B Type;
+ static const Enum kE = Enum::B;
+};
+
+Enum getType(IHasType e)
+{
+ return e::Type::kE;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ B b;
+ let e = getType(b);
+
+ outputBuffer[dispatchThreadID.x] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value-6.slang b/tests/experiments/generic/type-to-value-6.slang
new file mode 100644
index 000000000..fa7b05cbd
--- /dev/null
+++ b/tests/experiments/generic/type-to-value-6.slang
@@ -0,0 +1,49 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+Here we try to associate by having a value defined on the type, and then set the type
+on the associated type.
+
+Doesn't work because ...
+
+.slang(34): error 30027: 'kE' is not a member of 'overload group'.
+ let e = B::Type::kE;
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A, B
+};
+
+interface IHasType
+{
+ associatedtype Type;
+};
+
+// This is a little perverse, because I'm defining as an associated type that is
+// the same as itself
+struct A : IHasType
+{
+ typedef A Type;
+ static const Enum kE = Enum::A;
+};
+
+struct B : IHasType
+{
+ typedef B Type;
+ static const Enum kE = Enum::B;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ let e = B::Type::kE;
+
+ outputBuffer[dispatchThreadID.x] = int(e);
+} \ No newline at end of file
diff --git a/tests/experiments/generic/type-to-value.slang b/tests/experiments/generic/type-to-value.slang
new file mode 100644
index 000000000..65442212f
--- /dev/null
+++ b/tests/experiments/generic/type-to-value.slang
@@ -0,0 +1,33 @@
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+
+/* Test here is to try and associate a value with a type
+
+This works.
+*/
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+enum class Enum
+{
+ A,
+ B,
+};
+
+struct A
+{
+ static const Enum kE = Enum::A;
+};
+
+struct B
+{
+ static const Enum kE = Enum::B;
+};
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int index = dispatchThreadID.x;
+
+ outputBuffer[dispatchThreadID.x] = int(B::kE);
+} \ No newline at end of file
diff --git a/tests/experiments/interface/README.md b/tests/experiments/interface/README.md
new file mode 100644
index 000000000..655c5e508
--- /dev/null
+++ b/tests/experiments/interface/README.md
@@ -0,0 +1,5 @@
+Interface Experiments
+=====================
+
+All tests are disabled.
+
diff --git a/tests/experiments/interface/associated-type-2.slang b/tests/experiments/interface/associated-type-2.slang
new file mode 100644
index 000000000..2dd3779d9
--- /dev/null
+++ b/tests/experiments/interface/associated-type-2.slang
@@ -0,0 +1,61 @@
+//DISABLE_TEST:SIMPLE:-target dxil -entry computeMain -profile cs_6_2
+
+/*
+Testing how an associated type can be used.
+
+Here we try and only use Type returned in IInterface with methods on IInterface, since presubably the
+impl knows how to deal with it.
+
+Doesn't work.
+
+.slang(52): error 30019: expected an expression of type 'Type', got 'Type'
+ outputBuffer[dispatchThreadID.x] = x + intf.getValue(r, 16);
+
+*/
+
+struct SomeType
+{
+ int getValue(int index) { return index + offset; }
+
+ int offset;
+};
+
+interface IInterface
+{
+ associatedtype Type;
+
+ Type get(int offset);
+ int getValue(Type type, int index);
+};
+
+struct InterfaceImpl : IInterface
+{
+ typedef SomeType Type;
+
+ Type get(int offset)
+ {
+ Type v;
+ v.offset = offset;
+ return v;
+ };
+ int getValue(Type type, int index)
+ {
+ return type.getValue(index);
+ }
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ InterfaceImpl impl;
+
+ IInterface intf = impl;
+
+ var r = intf.get(16);
+
+ outputBuffer[dispatchThreadID.x] = x + intf.getValue(r, 16);
+} \ No newline at end of file
diff --git a/tests/experiments/interface/associated-type.slang b/tests/experiments/interface/associated-type.slang
new file mode 100644
index 000000000..2cc4f7c68
--- /dev/null
+++ b/tests/experiments/interface/associated-type.slang
@@ -0,0 +1,59 @@
+//TEST_TEST:SIMPLE:-target dxil -entry computeMain -profile cs_6_2
+
+/*
+Testing how an associated type can be used.
+
+In this example because we get the Type from the interface, it doesn't know what actual type it is.
+
+.slang(43): error 30027: 'getValue' is not a member of 'Type'.
+ outputBuffer[dispatchThreadID.x] = x + r.getValue(x);
+
+From an error message point of view this perhaps somewhat confusing because there aren't any methods on Type in this context.
+
+It would be possible for an implementation to determine intf is impl, and do the right thing, although not in general.
+*/
+
+struct SomeType
+{
+ int getValue(int index) { return index + offset; }
+
+ int offset;
+};
+
+interface IInterface
+{
+ associatedtype Type;
+
+ Type get(int offset);
+};
+
+struct InterfaceImpl : IInterface
+{
+ typedef SomeType Type;
+
+ Type get(int offset)
+ {
+ Type v;
+ v.offset = offset;
+ return v;
+ };
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ InterfaceImpl impl;
+
+ IInterface intf = impl;
+
+ // Works if we get from impl. Doesn't work if we get from the interface
+ // saying that 'Type' doesn't define getValue.
+
+ var r = intf.get(16);
+
+ outputBuffer[dispatchThreadID.x] = x + r.getValue(x);
+} \ No newline at end of file
diff --git a/tests/experiments/interface/resource-associated-type.slang b/tests/experiments/interface/resource-associated-type.slang
new file mode 100644
index 000000000..e5d96a309
--- /dev/null
+++ b/tests/experiments/interface/resource-associated-type.slang
@@ -0,0 +1,63 @@
+//DISABLE_TEST:SIMPLE:-target dxil -entry computeMain -profile cs_6_2
+
+/*
+
+Doesn't work:
+
+.slang(51): error 30027: 'getValue' is not a member of 'Type'.
+ outputBuffer[dispatchThreadID.x] = x + r.getValue(x);
+ ^
+ */
+
+interface ISomeInterface
+{
+ int getValue(int index);
+};
+
+struct SomeType : ISomeInterface
+{
+ int getValue(int index) { return data.Load(index + offset); }
+
+ int offset;
+ ByteAddressBuffer data;
+};
+
+interface IInterface
+{
+ associatedtype Type;
+
+ Type get(int offset);
+};
+
+struct InterfaceImpl : IInterface
+{
+ typedef SomeType Type;
+
+ Type get(int offset)
+ {
+ Type a;
+ a.offset = offset;
+ a.data = byteAddressBuffer;
+ return a;
+ };
+};
+
+ByteAddressBuffer byteAddressBuffer;
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ InterfaceImpl impl;
+
+ IInterface intf = impl;
+
+ // Works if we get from impl. Doesn't work if we get from the interface
+ // saying that 'Type' doesn't define getValue.
+
+ var r = intf.get(16);
+
+ outputBuffer[dispatchThreadID.x] = x + r.getValue(x);
+} \ No newline at end of file
diff --git a/tests/experiments/interface/return-interface-2.slang b/tests/experiments/interface/return-interface-2.slang
new file mode 100644
index 000000000..1aa6fc5e3
--- /dev/null
+++ b/tests/experiments/interface/return-interface-2.slang
@@ -0,0 +1,55 @@
+//TEST_TEST:SIMPLE:-target dxil -entry computeMain -profile cs_6_2
+
+/*
+Testing returning an interface type.
+
+Fails with:
+
+.slang(6): error 41011: type 'SomeType' does not fit in the size required by its conforming interface.
+struct SomeType : IGetValue
+^~~~~~
+
+That's understandable in so far as dynamic dispatch appears to assume anyValue(16) by default. On the other hand, the compiler will know all conforming types (well at linkage anyway), and so potentially could work out an appropriate size.
+*/
+
+interface IGetValue
+{
+ int getValue(int index);
+};
+
+struct SomeType : IGetValue
+{
+ __init(int inOffset) { offset = inOffset; another = float4(inOffset); }
+ int getValue(int index) { return index + offset; }
+ int offset;
+ float4 another;
+};
+
+interface IInterface
+{
+ IGetValue get(int offset);
+};
+
+struct InterfaceImpl : IInterface
+{
+ IGetValue get(int offset)
+ {
+ return SomeType(offset);
+ };
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ InterfaceImpl impl;
+
+ IInterface intf = impl;
+
+ var r = intf.get(16);
+
+ outputBuffer[dispatchThreadID.x] = x + r.getValue(x);
+} \ No newline at end of file
diff --git a/tests/experiments/interface/return-interface.slang b/tests/experiments/interface/return-interface.slang
new file mode 100644
index 000000000..d7e55e40c
--- /dev/null
+++ b/tests/experiments/interface/return-interface.slang
@@ -0,0 +1,50 @@
+//TEST_TEST:SIMPLE:-target dxil -entry computeMain -profile cs_6_2
+
+/*
+Testing returning an interface type.
+
+Works.
+
+Uses dynamic dispatch like code - but in the end doesn't require any switches (there is only a single impl). That means it could in principal remove all the extraeous code used assuming it does dynamically dispatch.
+ */
+
+interface IGetValue
+{
+ int getValue(int index);
+};
+
+struct SomeType : IGetValue
+{
+ __init(int inOffset) { offset = inOffset; }
+ int getValue(int index) { return index + offset; }
+ int offset;
+};
+
+interface IInterface
+{
+ IGetValue get(int offset);
+};
+
+struct InterfaceImpl : IInterface
+{
+ IGetValue get(int offset)
+ {
+ return SomeType(offset);
+ };
+};
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int x = dispatchThreadID.x;
+
+ InterfaceImpl impl;
+
+ IInterface intf = impl;
+
+ var r = intf.get(16);
+
+ outputBuffer[dispatchThreadID.x] = x + r.getValue(x);
+} \ No newline at end of file