diff options
Diffstat (limited to 'tests/language-feature/pointer')
10 files changed, 331 insertions, 4 deletions
diff --git a/tests/language-feature/pointer/const-ptr-variations.slang b/tests/language-feature/pointer/const-ptr-variations.slang new file mode 100644 index 000000000..a2619d6c4 --- /dev/null +++ b/tests/language-feature/pointer/const-ptr-variations.slang @@ -0,0 +1,40 @@ +//TEST:SIMPLE(filecheck=CHECK_1):-stage compute -entry computeMain -target spirv -DT1 +//TEST:SIMPLE(filecheck=CHECK_2):-stage compute -entry computeMain -target spirv -DT2 +//TEST:SIMPLE(filecheck=CHECK_3):-stage compute -entry computeMain -target spirv -DT3 +//TEST:SIMPLE(filecheck=CHECK_4):-stage compute -entry computeMain -target spirv -DT4 + +// Tests for invalid use of `const` with Ptr/T* +// Due to bad syntax breaking the parser, it is more robust to use disjoint tests with +// #define's. +cbuffer Globals +{ + int* ptr; +} + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ + // disallowed syntax with modifier `const` +#ifdef T1 + // CHECK_1: ([[# @LINE+1]]): error + int const* ptr1 = ptr; +#endif + +#ifdef T2 + // CHECK_2: ([[# @LINE+1]]): error + int* const ptr2 = ptr; +#endif + +#ifdef T3 + // CHECK_3: ([[# @LINE+1]]): error 20017 + const int* ptr3 = ptr; + // CHECK_3: ([[# @LINE+1]]): error 20018 + Ptr<const int> ptr4 = ptr; +#endif + +#ifdef T4 + // CHECK_4: OpEntryPoint + // CHECK_4-NOT: error + const Ptr<int> ptr5 = ptr; +#endif +}
\ No newline at end of file diff --git a/tests/language-feature/pointer/get-address-validation.slang b/tests/language-feature/pointer/get-address-validation.slang new file mode 100644 index 000000000..3931c13a2 --- /dev/null +++ b/tests/language-feature/pointer/get-address-validation.slang @@ -0,0 +1,82 @@ +//TEST:SIMPLE(filecheck=CHECK):-stage compute -entry computeMain -target spirv + +// Tests for invalid/valid use of `__getAddress` + +struct DeviceStruct +{ + int data1; + int data2; +} + +struct StructPtrInStruct +{ + DeviceStruct* ptr; +} + +uniform int* bufferUserPointer; +RWStructuredBuffer<int> bufferStorage; +groupshared int bufferGroupShared[100]; +uniform DeviceStruct* bufferUserPointerStruct; +uniform int2* bufferUserPointerVector; + +int* output; + +typealias GroupSharedPtr<T> = Ptr<T, Access::ReadWrite, AddressSpace::GroupShared>; + +GroupSharedPtr<T> paramGroupShared<T : __BuiltinIntegerType>(out groupshared T[100] ptr) +{ + // CHECK: ([[# @LINE+1]]): error 30019 + T* ptr1 = __getAddress(ptr[5]); + + // CHECK-NOT: ([[# @LINE+1]]): error + GroupSharedPtr<T> ptr2 = __getAddress(ptr[5]); + + return ptr2; +} + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ + // CHECK: ([[# @LINE+1]]): error 31160 + int* ptr1 = __getAddress(bufferStorage[id.x]); + + // CHECK ([[# @LINE+1]]): error + int[100]* ptr2 = __getAddress(bufferGroupShared); + + // CHECK: ([[# @LINE+1]]): error + int* ptr3 = __getAddress(bufferGroupShared[id.x]); + + // CHECK-NOT: ([[# @LINE+1]]): error + int* ptr4 = __getAddress(bufferUserPointer[id.x]); + + // CHECK-NOT: ([[# @LINE+1]]): error + GroupSharedPtr<int[100]> ptr5 = __getAddress(bufferGroupShared); + + // CHECK-NOT: ([[# @LINE+1]]): error + GroupSharedPtr<int> ptr6 = __getAddress(bufferGroupShared[id.x]); + + // CHECK-NOT: ([[# @LINE+1]]): error + GroupSharedPtr<int> ptr7 = paramGroupShared(bufferGroupShared); + + // CHECK-NOT: ([[# @LINE+1]]): error + int* ptr8 = __getAddress(bufferUserPointerStruct.data1); + + StructPtrInStruct structPtrInStruct; + structPtrInStruct.ptr = bufferUserPointerStruct; + // CHECK-NOT: ([[# @LINE+1]]): error + int* ptr9 = __getAddress(structPtrInStruct.ptr[id.x].data1); + + // CHECK-NOT: ([[# @LINE+1]]): error + int* ptr10 = __getAddress(bufferUserPointerVector[0].x); + + output[id] = ptr1[id]; + output[id] = ptr2[id][0]; + output[id] = ptr3[id]; + output[id] = ptr4[id]; + output[id] = ptr5[id]; + output[id] = ptr6[id]; + output[id] = ptr7[id]; + output[id] = ptr8[id]; + output[id] = ptr9[id]; + output[id] = ptr10[id]; +} diff --git a/tests/language-feature/pointer/globallycoherent-ptr.slang b/tests/language-feature/pointer/globallycoherent-ptr.slang new file mode 100644 index 000000000..4909537d7 --- /dev/null +++ b/tests/language-feature/pointer/globallycoherent-ptr.slang @@ -0,0 +1,20 @@ +//TEST:SIMPLE(filecheck=CHECK):-stage compute -entry computeMain -target spirv + +// Tests for invalid use of `globallycoherent` with Ptr/T* + +cbuffer Globals +{ + // CHECK: ([[# @LINE+1]]): error 30078 + globallycoherent Ptr<int> ptr1; + // CHECK: ([[# @LINE+1]]): error 30078 + globallycoherent int* ptr2; + // CHECK: ([[# @LINE+1]]): error 30078 + coherent Ptr<int> ptr3; + // CHECK: ([[# @LINE+1]]): error 30078 + coherent int* ptr4; +} + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ +} diff --git a/tests/language-feature/pointer/groupshared-ptr-of-device.slang b/tests/language-feature/pointer/groupshared-ptr-of-device.slang new file mode 100644 index 000000000..31703819e --- /dev/null +++ b/tests/language-feature/pointer/groupshared-ptr-of-device.slang @@ -0,0 +1,28 @@ +//TEST:SIMPLE(filecheck=SPIRV):-stage compute -entry computeMain -target spirv -capability vk_mem_model+sm_6_0+spvGroupNonUniformBallot +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-vk -output-using-type -emit-spirv-directly -capability vk_mem_model+sm_6_0+spvGroupNonUniformBallot + +// Tests if we pass-through and handle pointers via groupshared-memory correctly. +// Ensure SPIRV emits coherent operations here +// SPIRV: OpEntryPoint +// SPIRV-NOT: error + +// CHECK: 1 +// CHECK-NEXT: 0 +// CHECK-NEXT: 2 +// CHECK-NEXT: 0 +// CHECK-NEXT: 3 + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0], stride=4):out,name=outputBuffer +uniform int* outputBuffer; + +groupshared int* sharedPtr[3]; + +[numthreads(3, 1, 1)] +void computeMain(uint3 group_thread_id: SV_GroupThreadID) +{ + sharedPtr[group_thread_id.x] = outputBuffer + group_thread_id.x; + sharedPtr[group_thread_id.x] = sharedPtr[group_thread_id.x]+group_thread_id.x; + GroupMemoryBarrierWithGroupSync(); + + *sharedPtr[group_thread_id.x] = group_thread_id.x+1; +}
\ No newline at end of file diff --git a/tests/language-feature/pointer/pointer-access/pointer-access-frontend.slang b/tests/language-feature/pointer/pointer-access/pointer-access-frontend.slang new file mode 100644 index 000000000..98a2a076d --- /dev/null +++ b/tests/language-feature/pointer/pointer-access/pointer-access-frontend.slang @@ -0,0 +1,14 @@ +//TEST:SIMPLE(filecheck=CHECK):-stage compute -entry computeMain -target spirv + +//CHECK: OpEntryPoint +//CHECK-NOT: error + +int* processMemory; +int* output; + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ + Ptr<int, Access::ReadWrite, AddressSpace::Device> ptr1 = processMemory + id.x + 5; + Ptr<int> ptr2 = processMemory + id.x + 4; +}
\ No newline at end of file diff --git a/tests/language-feature/pointer/pointer-access/read-only-pointer-1.slang b/tests/language-feature/pointer/pointer-access/read-only-pointer-1.slang new file mode 100644 index 000000000..e7f1ad534 --- /dev/null +++ b/tests/language-feature/pointer/pointer-access/read-only-pointer-1.slang @@ -0,0 +1,41 @@ +//TEST:SIMPLE(filecheck=CHECK):-stage compute -entry computeMain -target spirv + +// Writing with a read-only pointer should be an error + +int* processMemory; +RWStructuredBuffer<int> output; + +typealias ReadPtr = Ptr<int, Access::Read, AddressSpace::Device>; + +void writeToReadOnlyPointer(ReadPtr ptr) +{ + // CHECK: ([[# @LINE+1]]): error 30011 + ptr[0] = 1; +} + +void writeToReadOnlyPointerOut(out int ptrVal) +{ + ptrVal = 1; +} + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ + // CHECK-NOT: ([[# @LINE+1]]): error + ReadPtr ptr1 = ReadPtr(processMemory + id.x); + + // CHECK: ([[# @LINE+1]]): error 30011 + ptr1[id + 1] = 1; + // CHECK: ([[# @LINE+1]]): error 30011 + *ptr1 = 1; + + writeToReadOnlyPointer(ptr1); + + // CHECK: ([[# @LINE+1]]): error 30047 + writeToReadOnlyPointerOut(ptr1[1]); + + // CHECK: ([[# @LINE+1]]): error 30047 + writeToReadOnlyPointerOut(*(ptr1+2)); + + output[id] = ptr1[id]; +} diff --git a/tests/language-feature/pointer/pointer-access/read-only-pointer-2.slang b/tests/language-feature/pointer/pointer-access/read-only-pointer-2.slang new file mode 100644 index 000000000..c5288caba --- /dev/null +++ b/tests/language-feature/pointer/pointer-access/read-only-pointer-2.slang @@ -0,0 +1,19 @@ +//TEST:SIMPLE(filecheck=CHECK):-stage compute -entry computeMain -target spirv + +// Tests valid use of read-only pointer + +// CHECK: OpEntryPoint +// CHECK-NOT: error + +int* processMemory; +int* output; + +typealias ReadPtr = Ptr<int, Access::Read, AddressSpace::Device>; + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ + ReadPtr ptr1 = ReadPtr(processMemory + id.x); + + output[id] = ptr1[id]; +} diff --git a/tests/language-feature/pointer/pointer-casting/pointer-casting-rules.slang b/tests/language-feature/pointer/pointer-casting/pointer-casting-rules.slang new file mode 100644 index 000000000..d0a016fe5 --- /dev/null +++ b/tests/language-feature/pointer/pointer-casting/pointer-casting-rules.slang @@ -0,0 +1,51 @@ +//TEST:SIMPLE(filecheck=CHECK):-stage compute -entry computeMain -target spirv + +// Tests pointer casting rules: Only explicit casting is allowed between pointer types. +// All implicit conversions between pointer types should fail. +int* processMemory; +RWStructuredBuffer<int> output; + +[numthreads(1, 1, 1)] +void computeMain(int id : SV_DispatchThreadID) +{ + // regular address-of + // CHECK-NOT: ([[# @LINE+1]]): error + Ptr<int, Access::ReadWrite, AddressSpace::Device> rwPtr = processMemory + id.x; + // copying a pointer of T* syntax + // CHECK-NOT: ([[# @LINE+1]]): error + Ptr<int, Access::ReadWrite, AddressSpace::Device> copiedPtrOfLegacySyntax = processMemory; + // casting to Read ptr + // CHECK-NOT: ([[# @LINE+1]]): error + Ptr<int, Access::Read> rPtr = Ptr<int, Access::Read>(processMemory + id.x); + + // casting to RW ptr from a R ptr + // CHECK-NOT: ([[# @LINE+1]]): error + Ptr<int, Access::ReadWrite, AddressSpace::Device> p1 = Ptr<int, Access::ReadWrite, AddressSpace::Device>(rPtr); + // casting to R ptr from a RW ptr + // CHECK-NOT: ([[# @LINE+1]]): error + Ptr<int, Access::Read, AddressSpace::Device> p2 = Ptr<int, Access::Read, AddressSpace::Device>(rwPtr); + // casting to ptr of different type + // CHECK-NOT: ([[# @LINE+1]]): error + Ptr<float, Access::ReadWrite, AddressSpace::Device> p3 = Ptr<float, Access::ReadWrite, AddressSpace::Device>(rPtr); + + // Cannot implicit cast ptr's + // CHECK: ([[# @LINE+1]]): error 30019 + Ptr<float, Access::ReadWrite, AddressSpace::Device> p4 = rPtr; + // cannot implcitly cast between different access qualifiers + // CHECK: ([[# @LINE+1]]): error 30019 + Ptr<int, Access::Read> p5 = Ptr<int, Access::ReadWrite>(processMemory + id.x); + // cannot implcitly cast between different access qualifiers + // CHECK: ([[# @LINE+1]]): error 30019 + Ptr<int, Access::ReadWrite> p6 = Ptr<int, Access::Read>(processMemory + id.x); + + // TODO: Enable this when we allow user-defined group-shared address space, Issue #8173. + // Cannot cast between different address spaces. + // CHECK: ([[# @LINE+1]]): error + Ptr<float, Access::ReadWrite, AddressSpace::GroupShared> p7 = Ptr<float, Access::ReadWrite, AddressSpace::GroupShared>(rwPtr); + // CHECK: ([[# @LINE+1]]): error + Ptr<float, Access::ReadWrite, AddressSpace::GroupShared> p8 = Ptr<float, Access::ReadWrite, AddressSpace::GroupShared>(p1); + // CHECK: ([[# @LINE+1]]): error + Ptr<float, Access::ReadWrite, AddressSpace::GroupShared> p9 = rwPtr; + + output[id] = *rwPtr; +} diff --git a/tests/language-feature/pointer/pointer-self-reference.slang b/tests/language-feature/pointer/pointer-self-reference.slang index e78b70db0..75ff4e7a9 100644 --- a/tests/language-feature/pointer/pointer-self-reference.slang +++ b/tests/language-feature/pointer/pointer-self-reference.slang @@ -1,6 +1,8 @@ // pointer-self-reference.slang -//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -output-using-type -shaderobj +// We are disabling this test because '&' is intentionally not supported. +// Design for pointers in Slang are not yet finalized. +//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -output-using-type -shaderobj //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; @@ -18,13 +20,13 @@ void computeMain(int3 dispatchThreadID: SV_DispatchThreadID) Thing things[2]; - things[0].next = &things[1]; + things[0].next = __getAddress(things[1]); things[0].value = 27; - things[1].next = &things[0]; + things[1].next = __getAddress(things[0]); things[1].value = idx * idx; - Ptr<Thing> cur = &things[0]; + Ptr<Thing> cur = __getAddress(things[0]); for (int i = 0; cur && i < idx; ++i) { diff --git a/tests/language-feature/pointer/ptr-to-groupshared.slang b/tests/language-feature/pointer/ptr-to-groupshared.slang new file mode 100644 index 000000000..3ad4c5e0b --- /dev/null +++ b/tests/language-feature/pointer/ptr-to-groupshared.slang @@ -0,0 +1,30 @@ +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-vk -output-using-type -emit-spirv-directly + +// Tests if we handle passing groupshared address-space pointers correctly to a function +// when that data-type needs legalization (Data -> Data_natural due to `lower-buffer-element-type`). +// CHECK: 1 +// CHECK-NEXT: 2 +// CHECK-NEXT: 0 + +struct Data +{ + int value1; + int value2; +} + +//TEST_INPUT:ubuffer(data=[0 0 0], stride=4):out,name=outputBuffer +uniform int* outputBuffer; +groupshared Data shared; + +void foo(Ptr<Data, Access::ReadWrite, AddressSpace::GroupShared> ptr) +{ + outputBuffer[0] = ptr.value1; + outputBuffer[1] = ptr.value2; +} + +[numthreads(3, 1, 1)] +void computeMain(uint3 group_thread_id: SV_GroupThreadID) +{ + shared = Data(1, 2); + foo(__getAddress(shared)); +}
\ No newline at end of file |
