• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "harness/testHarness.h"
17 #include "harness/kernelHelpers.h"
18 #include "harness/typeWrappers.h"
19 
20 #include "common.h"
21 
get_memory_order_type_name(TExplicitMemoryOrderType orderType)22 const char *get_memory_order_type_name(TExplicitMemoryOrderType orderType)
23 {
24   switch (orderType)
25   {
26   case MEMORY_ORDER_EMPTY:
27     return "";
28   case MEMORY_ORDER_RELAXED:
29     return "memory_order_relaxed";
30   case MEMORY_ORDER_ACQUIRE:
31     return "memory_order_acquire";
32   case MEMORY_ORDER_RELEASE:
33     return "memory_order_release";
34   case MEMORY_ORDER_ACQ_REL:
35     return "memory_order_acq_rel";
36   case MEMORY_ORDER_SEQ_CST:
37     return "memory_order_seq_cst";
38   default:
39     return 0;
40   }
41 }
42 
get_memory_scope_type_name(TExplicitMemoryScopeType scopeType)43 const char *get_memory_scope_type_name(TExplicitMemoryScopeType scopeType)
44 {
45   switch (scopeType)
46   {
47       case MEMORY_SCOPE_EMPTY: return "";
48       case MEMORY_SCOPE_WORK_GROUP: return "memory_scope_work_group";
49       case MEMORY_SCOPE_DEVICE: return "memory_scope_device";
50       case MEMORY_SCOPE_ALL_DEVICES: return "memory_scope_all_devices";
51       case MEMORY_SCOPE_ALL_SVM_DEVICES: return "memory_scope_all_svm_devices";
52       default: return 0;
53   }
54 }
55 
56 
Size(cl_device_id device)57 cl_uint AtomicTypeInfo::Size(cl_device_id device)
58 {
59   switch(_type)
60   {
61   case TYPE_ATOMIC_INT:
62   case TYPE_ATOMIC_UINT:
63   case TYPE_ATOMIC_FLOAT:
64   case TYPE_ATOMIC_FLAG:
65     return sizeof(cl_int);
66   case TYPE_ATOMIC_LONG:
67   case TYPE_ATOMIC_ULONG:
68   case TYPE_ATOMIC_DOUBLE:
69     return sizeof(cl_long);
70   case TYPE_ATOMIC_INTPTR_T:
71   case TYPE_ATOMIC_UINTPTR_T:
72   case TYPE_ATOMIC_SIZE_T:
73   case TYPE_ATOMIC_PTRDIFF_T:
74     {
75       int error;
76       cl_uint addressBits = 0;
77 
78       error = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(addressBits), &addressBits, 0);
79       test_error_ret(error, "clGetDeviceInfo", 0);
80 
81       return addressBits/8;
82     }
83   default:
84     return 0;
85   }
86 }
87 
AtomicTypeName()88 const char *AtomicTypeInfo::AtomicTypeName()
89 {
90   switch(_type)
91   {
92   case TYPE_ATOMIC_INT:
93     return "atomic_int";
94   case TYPE_ATOMIC_UINT:
95     return "atomic_uint";
96   case TYPE_ATOMIC_FLOAT:
97     return "atomic_float";
98   case TYPE_ATOMIC_FLAG:
99     return "atomic_flag";
100   case TYPE_ATOMIC_LONG:
101     return "atomic_long";
102   case TYPE_ATOMIC_ULONG:
103     return "atomic_ulong";
104   case TYPE_ATOMIC_DOUBLE:
105     return "atomic_double";
106   case TYPE_ATOMIC_INTPTR_T:
107     return "atomic_intptr_t";
108   case TYPE_ATOMIC_UINTPTR_T:
109     return "atomic_uintptr_t";
110   case TYPE_ATOMIC_SIZE_T:
111     return "atomic_size_t";
112   case TYPE_ATOMIC_PTRDIFF_T:
113     return "atomic_ptrdiff_t";
114   default:
115     return 0;
116   }
117 }
118 
RegularTypeName()119 const char *AtomicTypeInfo::RegularTypeName()
120 {
121   switch(_type)
122   {
123   case TYPE_ATOMIC_INT:
124     return "int";
125   case TYPE_ATOMIC_UINT:
126     return "uint";
127   case TYPE_ATOMIC_FLOAT:
128     return "float";
129   case TYPE_ATOMIC_FLAG:
130     return "int";
131   case TYPE_ATOMIC_LONG:
132     return "long";
133   case TYPE_ATOMIC_ULONG:
134     return "ulong";
135   case TYPE_ATOMIC_DOUBLE:
136     return "double";
137   case TYPE_ATOMIC_INTPTR_T:
138     return "intptr_t";
139   case TYPE_ATOMIC_UINTPTR_T:
140     return "uintptr_t";
141   case TYPE_ATOMIC_SIZE_T:
142     return "size_t";
143   case TYPE_ATOMIC_PTRDIFF_T:
144     return "ptrdiff_t";
145   default:
146     return 0;
147   }
148 }
149 
AddSubOperandTypeName()150 const char *AtomicTypeInfo::AddSubOperandTypeName()
151 {
152   switch(_type)
153   {
154   case TYPE_ATOMIC_INTPTR_T:
155   case TYPE_ATOMIC_UINTPTR_T:
156     return AtomicTypeInfo(TYPE_ATOMIC_PTRDIFF_T).RegularTypeName();
157   default:
158     return RegularTypeName();
159   }
160 }
161 
IsSupported(cl_device_id device)162 int AtomicTypeInfo::IsSupported(cl_device_id device)
163 {
164   switch(_type)
165   {
166   case TYPE_ATOMIC_INT:
167   case TYPE_ATOMIC_UINT:
168   case TYPE_ATOMIC_FLOAT:
169   case TYPE_ATOMIC_FLAG:
170     return 1;
171   case TYPE_ATOMIC_LONG:
172   case TYPE_ATOMIC_ULONG:
173     return is_extension_available(device, "cl_khr_int64_base_atomics") &&
174       is_extension_available(device, "cl_khr_int64_extended_atomics");
175   case TYPE_ATOMIC_DOUBLE:
176     return is_extension_available(device, "cl_khr_int64_base_atomics") &&
177       is_extension_available(device, "cl_khr_int64_extended_atomics") &&
178       is_extension_available(device, "cl_khr_fp64");
179   case TYPE_ATOMIC_INTPTR_T:
180   case TYPE_ATOMIC_UINTPTR_T:
181   case TYPE_ATOMIC_SIZE_T:
182   case TYPE_ATOMIC_PTRDIFF_T:
183     if(Size(device) == 4)
184       return 1;
185     return is_extension_available(device, "cl_khr_int64_base_atomics") &&
186       is_extension_available(device, "cl_khr_int64_extended_atomics");
187   default:
188     return 0;
189   }
190 }
191 
MinValue()192 template<> cl_int AtomicTypeExtendedInfo<cl_int>::MinValue() {return CL_INT_MIN;}
MinValue()193 template<> cl_uint AtomicTypeExtendedInfo<cl_uint>::MinValue() {return 0;}
MinValue()194 template<> cl_long AtomicTypeExtendedInfo<cl_long>::MinValue() {return CL_LONG_MIN;}
MinValue()195 template<> cl_ulong AtomicTypeExtendedInfo<cl_ulong>::MinValue() {return 0;}
MinValue()196 template<> cl_float AtomicTypeExtendedInfo<cl_float>::MinValue() {return CL_FLT_MIN;}
MinValue()197 template<> cl_double AtomicTypeExtendedInfo<cl_double>::MinValue() {return CL_DBL_MIN;}
198 
MaxValue()199 template<> cl_int AtomicTypeExtendedInfo<cl_int>::MaxValue() {return CL_INT_MAX;}
MaxValue()200 template<> cl_uint AtomicTypeExtendedInfo<cl_uint>::MaxValue() {return CL_UINT_MAX;}
MaxValue()201 template<> cl_long AtomicTypeExtendedInfo<cl_long>::MaxValue() {return CL_LONG_MAX;}
MaxValue()202 template<> cl_ulong AtomicTypeExtendedInfo<cl_ulong>::MaxValue() {return CL_ULONG_MAX;}
MaxValue()203 template<> cl_float AtomicTypeExtendedInfo<cl_float>::MaxValue() {return CL_FLT_MAX;}
MaxValue()204 template<> cl_double AtomicTypeExtendedInfo<cl_double>::MaxValue() {return CL_DBL_MAX;}
205 
getSupportedMemoryOrdersAndScopes(cl_device_id device,std::vector<TExplicitMemoryOrderType> & memoryOrders,std::vector<TExplicitMemoryScopeType> & memoryScopes)206 cl_int getSupportedMemoryOrdersAndScopes(
207     cl_device_id device, std::vector<TExplicitMemoryOrderType> &memoryOrders,
208     std::vector<TExplicitMemoryScopeType> &memoryScopes)
209 {
210     // The CL_DEVICE_ATOMIC_MEMORY_CAPABILITES is missing before 3.0, but since
211     // all orderings and scopes are required for 2.X devices and this test is
212     // skipped before 2.0 we can safely return all orderings and scopes if the
213     // device is 2.X. Query device for the supported orders.
214     if (get_device_cl_version(device) < Version{ 3, 0 })
215     {
216         memoryOrders.push_back(MEMORY_ORDER_EMPTY);
217         memoryOrders.push_back(MEMORY_ORDER_RELAXED);
218         memoryOrders.push_back(MEMORY_ORDER_ACQUIRE);
219         memoryOrders.push_back(MEMORY_ORDER_RELEASE);
220         memoryOrders.push_back(MEMORY_ORDER_ACQ_REL);
221         memoryOrders.push_back(MEMORY_ORDER_SEQ_CST);
222         memoryScopes.push_back(MEMORY_SCOPE_EMPTY);
223         memoryScopes.push_back(MEMORY_SCOPE_WORK_GROUP);
224         memoryScopes.push_back(MEMORY_SCOPE_DEVICE);
225         memoryScopes.push_back(MEMORY_SCOPE_ALL_SVM_DEVICES);
226         return CL_SUCCESS;
227     }
228 
229     // For a 3.0 device we can query the supported orderings and scopes
230     // directly.
231     cl_device_atomic_capabilities atomic_capabilities{};
232     test_error(
233         clGetDeviceInfo(device, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES,
234                         sizeof(atomic_capabilities), &atomic_capabilities,
235                         nullptr),
236         "clGetDeviceInfo failed for CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES\n");
237 
238     // Provided we succeeded, we can start filling the vectors.
239     if (atomic_capabilities & CL_DEVICE_ATOMIC_ORDER_RELAXED)
240     {
241         memoryOrders.push_back(MEMORY_ORDER_RELAXED);
242     }
243 
244     if (atomic_capabilities & CL_DEVICE_ATOMIC_ORDER_ACQ_REL)
245     {
246         memoryOrders.push_back(MEMORY_ORDER_ACQUIRE);
247         memoryOrders.push_back(MEMORY_ORDER_RELEASE);
248         memoryOrders.push_back(MEMORY_ORDER_ACQ_REL);
249     }
250 
251     if (atomic_capabilities & CL_DEVICE_ATOMIC_ORDER_SEQ_CST)
252     {
253         // The functions not ending in explicit have the same semantics as the
254         // corresponding explicit function with memory_order_seq_cst for the
255         // memory_order argument.
256         memoryOrders.push_back(MEMORY_ORDER_EMPTY);
257         memoryOrders.push_back(MEMORY_ORDER_SEQ_CST);
258     }
259 
260     if (atomic_capabilities & CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP)
261     {
262         memoryScopes.push_back(MEMORY_SCOPE_WORK_GROUP);
263     }
264 
265     if (atomic_capabilities & CL_DEVICE_ATOMIC_SCOPE_DEVICE)
266     {
267         // The functions that do not have memory_scope argument have the same
268         // semantics as the corresponding functions with the memory_scope
269         // argument set to memory_scope_device.
270         memoryScopes.push_back(MEMORY_SCOPE_EMPTY);
271         memoryScopes.push_back(MEMORY_SCOPE_DEVICE);
272     }
273     if (atomic_capabilities & CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES)
274     {
275         // OpenCL 3.0 added memory_scope_all_devices as an alias for
276         // memory_scope_all_svm_devices, so test both.
277         memoryScopes.push_back(MEMORY_SCOPE_ALL_DEVICES);
278         memoryScopes.push_back(MEMORY_SCOPE_ALL_SVM_DEVICES);
279     }
280     return CL_SUCCESS;
281 }
282