diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2021-12-21 16:35:34 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-21 16:35:34 -0500 |
| commit | 447b7e0e2be031409b1421b49c81f020353bf7c5 (patch) | |
| tree | 721a1e892b4dc0bcc8c62d7b7e3f9dbb843bf958 /tests/experiments/generic | |
| parent | d7ed829c3f85514fc08a12a5701d64390b31040c (diff) | |
Language experiments (#2068)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Moved to experiments.
Added some more tests.
* More tests around associated types.
* Return interface tests.
* More tests.
Diffstat (limited to 'tests/experiments/generic')
52 files changed, 2128 insertions, 0 deletions
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 |
