DPC++ Runtime
Runtime libraries for oneAPI DPC++
access.hpp
Go to the documentation of this file.
1 //==---------------- access.hpp --- SYCL access ----------------------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <sycl/detail/defines_elementary.hpp> // for __SYCL2020_DEPRECATED
12 
13 #ifdef __SYCL_DEVICE_ONLY__
14 #include <CL/__spirv/spirv_ops.hpp>
15 #include <type_traits>
16 #endif
17 
18 namespace sycl {
19 inline namespace _V1 {
20 namespace access {
21 
22 enum class target {
23  global_buffer __SYCL2020_DEPRECATED("use 'target::device' instead") = 2014,
24  constant_buffer __SYCL2020_DEPRECATED("use 'target::device' instead") = 2015,
25  local __SYCL2020_DEPRECATED("use `local_accessor` instead") = 2016,
26  image = 2017,
27  host_buffer __SYCL2020_DEPRECATED("use 'host_accessor' instead") = 2018,
28  host_image = 2019,
29  image_array = 2020,
30  host_task = 2021,
31  device = global_buffer,
32 };
33 
34 enum class mode {
35  read = 1024,
36  write = 1025,
37  read_write = 1026,
38  discard_write = 1027,
39  discard_read_write = 1028,
40  atomic = 1029
41 };
42 
43 enum class fence_space {
44  local_space = 0,
45  global_space = 1,
47 };
48 
49 enum class placeholder { false_t = 0, true_t = 1 };
50 
51 enum class address_space : int {
52  private_space = 0,
53  global_space = 1,
54  constant_space __SYCL2020_DEPRECATED("sycl::access::address_space::constant_"
55  "space is deprecated since SYCL 2020") =
56  2,
57  local_space = 3,
60  generic_space = 6, // TODO generic_space address space is not supported yet
61 };
62 
63 enum class decorated : int {
64  no = 0,
65  yes = 1,
66  legacy __SYCL2020_DEPRECATED("sycl::access::decorated::legacy "
67  "is deprecated since SYCL 2020") = 2
68 };
69 } // namespace access
70 
71 using access::target;
73 
74 enum class image_target : unsigned int { device = 0, host_task = 1 };
75 
76 template <access_mode mode> struct mode_tag_t {
77  explicit mode_tag_t() = default;
78 };
79 
80 template <access_mode mode, target trgt> struct mode_target_tag_t {
81  explicit mode_target_tag_t() = default;
82 };
83 
87 inline constexpr mode_target_tag_t<access_mode::read, target::constant_buffer>
89 inline constexpr mode_target_tag_t<access_mode::read, target::host_task>
95 
96 namespace detail {
97 
99  return T == access::target::host_buffer || T == access::target::host_image;
100 }
101 
102 constexpr bool modeNeedsOldData(access::mode m) {
103  return m == access::mode::read || m == access::mode::write ||
105 }
106 
107 constexpr bool modeWritesNewData(access::mode m) {
108  return m != access::mode::read;
109 }
110 
111 template <access::decorated Decorated> struct NegateDecorated;
112 template <> struct NegateDecorated<access::decorated::yes> {
113  static constexpr access::decorated value = access::decorated::no;
114 };
115 template <> struct NegateDecorated<access::decorated::no> {
116  static constexpr access::decorated value = access::decorated::yes;
117 };
118 
119 #ifdef __SYCL_DEVICE_ONLY__
120 #define __OPENCL_GLOBAL_AS__ __attribute__((opencl_global))
121 #ifdef __ENABLE_USM_ADDR_SPACE__
122 #define __OPENCL_GLOBAL_DEVICE_AS__ __attribute__((opencl_global_device))
123 #define __OPENCL_GLOBAL_HOST_AS__ __attribute__((opencl_global_host))
124 #else
125 #define __OPENCL_GLOBAL_DEVICE_AS__ __attribute__((opencl_global))
126 #define __OPENCL_GLOBAL_HOST_AS__ __attribute__((opencl_global))
127 #endif // __ENABLE_USM_ADDR_SPACE__
128 #define __OPENCL_LOCAL_AS__ __attribute__((opencl_local))
129 #define __OPENCL_CONSTANT_AS__ __attribute__((opencl_constant))
130 #define __OPENCL_PRIVATE_AS__ __attribute__((opencl_private))
131 #else
132 #define __OPENCL_GLOBAL_AS__
133 #define __OPENCL_GLOBAL_DEVICE_AS__
134 #define __OPENCL_GLOBAL_HOST_AS__
135 #define __OPENCL_LOCAL_AS__
136 #define __OPENCL_CONSTANT_AS__
137 #define __OPENCL_PRIVATE_AS__
138 #endif
139 
140 template <access::target accessTarget> struct TargetToAS {
141  constexpr static access::address_space AS =
143 };
144 
145 #ifdef __ENABLE_USM_ADDR_SPACE__
146 template <> struct TargetToAS<access::target::device> {
147  constexpr static access::address_space AS =
149 };
150 #endif // __ENABLE_USM_ADDR_SPACE__
151 
152 template <> struct TargetToAS<access::target::local> {
153  constexpr static access::address_space AS =
155 };
156 
157 template <> struct TargetToAS<access::target::constant_buffer> {
158  constexpr static access::address_space AS =
159  access::address_space::constant_space;
160 };
161 
162 template <typename ElementType, access::address_space addressSpace>
164 
165 template <typename ElementType>
166 struct DecoratedType<ElementType, access::address_space::private_space> {
167  using type = __OPENCL_PRIVATE_AS__ ElementType;
168 };
169 
170 template <typename ElementType>
171 struct DecoratedType<ElementType, access::address_space::generic_space> {
172  using type = ElementType;
173 };
174 
175 template <typename ElementType>
176 struct DecoratedType<ElementType, access::address_space::global_space> {
177  using type = __OPENCL_GLOBAL_AS__ ElementType;
178 };
179 
180 template <typename ElementType>
181 struct DecoratedType<ElementType,
182  access::address_space::ext_intel_global_device_space> {
183  using type = __OPENCL_GLOBAL_DEVICE_AS__ ElementType;
184 };
185 
186 template <typename ElementType>
187 struct DecoratedType<ElementType,
188  access::address_space::ext_intel_global_host_space> {
189  using type = __OPENCL_GLOBAL_HOST_AS__ ElementType;
190 };
191 
192 template <typename ElementType>
193 struct DecoratedType<ElementType, access::address_space::constant_space> {
194  // Current implementation of address spaces handling leads to possibility
195  // of emitting incorrect (in terms of OpenCL) address space casts from
196  // constant to generic (and vise-versa). So, global address space is used
197  // here instead of constant to avoid incorrect address space casts in the
198  // produced device code.
199 #if defined(RESTRICT_WRITE_ACCESS_TO_CONSTANT_PTR)
200  using type = const __OPENCL_GLOBAL_AS__ ElementType;
201 #else
202  using type = __OPENCL_GLOBAL_AS__ ElementType;
203 #endif
204 };
205 
206 template <typename ElementType>
207 struct DecoratedType<ElementType, access::address_space::local_space> {
208  using type = __OPENCL_LOCAL_AS__ ElementType;
209 };
210 
211 #ifdef __SYCL_DEVICE_ONLY__
212 template <class T> struct deduce_AS_impl {
213  // Undecorated pointers are considered generic.
214  // TODO: This assumes that the implementation uses generic as default. If
215  // address space inference is used this may need to change.
216  static constexpr access::address_space value =
218 };
219 
220 #ifdef __ENABLE_USM_ADDR_SPACE__
221 template <class T> struct deduce_AS_impl<__OPENCL_GLOBAL_DEVICE_AS__ T> {
222  static constexpr access::address_space value =
224 };
225 
226 template <class T> struct deduce_AS_impl<__OPENCL_GLOBAL_HOST_AS__ T> {
227  static constexpr access::address_space value =
229 };
230 #endif // __ENABLE_USM_ADDR_SPACE__
231 
232 template <class T> struct deduce_AS_impl<__OPENCL_GLOBAL_AS__ T> {
233  static constexpr access::address_space value =
235 };
236 
237 template <class T> struct deduce_AS_impl<__OPENCL_PRIVATE_AS__ T> {
238  static constexpr access::address_space value =
240 };
241 
242 template <class T> struct deduce_AS_impl<__OPENCL_LOCAL_AS__ T> {
243  static constexpr access::address_space value =
245 };
246 
247 template <class T> struct deduce_AS_impl<__OPENCL_CONSTANT_AS__ T> {
248  static constexpr access::address_space value =
249  access::address_space::constant_space;
250 };
251 
252 template <class T>
253 struct deduce_AS
254  : deduce_AS_impl<
255  std::remove_pointer_t<std::remove_reference_t<std::remove_cv_t<T>>>> {
256 };
257 #endif
258 
259 template <typename T> struct remove_decoration_impl {
260  using type = T;
261 };
262 
263 #ifdef __SYCL_DEVICE_ONLY__
264 template <typename T> struct remove_decoration_impl<__OPENCL_GLOBAL_AS__ T> {
265  using type = T;
266 };
267 
268 #ifdef __ENABLE_USM_ADDR_SPACE__
269 template <typename T>
270 struct remove_decoration_impl<__OPENCL_GLOBAL_DEVICE_AS__ T> {
271  using type = T;
272 };
273 
274 template <typename T>
275 struct remove_decoration_impl<__OPENCL_GLOBAL_HOST_AS__ T> {
276  using type = T;
277 };
278 
279 #endif // __ENABLE_USM_ADDR_SPACE__
280 
281 template <typename T> struct remove_decoration_impl<__OPENCL_PRIVATE_AS__ T> {
282  using type = T;
283 };
284 
285 template <typename T> struct remove_decoration_impl<__OPENCL_LOCAL_AS__ T> {
286  using type = T;
287 };
288 
289 template <typename T> struct remove_decoration_impl<__OPENCL_CONSTANT_AS__ T> {
290  using type = T;
291 };
292 #endif // __SYCL_DEVICE_ONLY__
293 } // namespace detail
294 
295 template <typename T> struct remove_decoration {
297 };
298 
299 // Propagate through const qualifier.
300 template <typename T> struct remove_decoration<const T> {
301  using type = const typename remove_decoration<T>::type;
302 };
303 
304 // Propagate through pointer.
305 template <typename T> struct remove_decoration<T *> {
306  using type = typename remove_decoration<T>::type *;
307 };
308 
309 // Propagate through const qualified pointer.
310 template <typename T> struct remove_decoration<const T *> {
311  using type = const typename remove_decoration<T>::type *;
312 };
313 
314 // Propagate through reference.
315 template <typename T> struct remove_decoration<T &> {
316  using type = typename remove_decoration<T>::type &;
317 };
318 
319 // Propagate through const qualified reference.
320 template <typename T> struct remove_decoration<const T &> {
321  using type = const typename remove_decoration<T>::type &;
322 };
323 
324 template <typename T>
326 
327 namespace detail {
328 
329 // Helper function for selecting appropriate casts between address spaces.
330 template <typename ToT, typename FromT> inline ToT cast_AS(FromT from) {
331 #ifdef __SYCL_DEVICE_ONLY__
332  constexpr access::address_space ToAS = deduce_AS<ToT>::value;
333  constexpr access::address_space FromAS = deduce_AS<FromT>::value;
334  if constexpr (FromAS == access::address_space::generic_space) {
335 #if defined(__NVPTX__) || defined(__AMDGCN__) || defined(__SYCL_NATIVE_CPU__)
336  // TODO: NVPTX and AMDGCN backends do not currently support the
337  // __spirv_GenericCastToPtrExplicit_* builtins, so to work around this
338  // we do C-style casting. This may produce warnings when targetting
339  // these backends.
340  return (ToT)from;
341 #else
342  using ToElemT = std::remove_pointer_t<remove_decoration_t<ToT>>;
343  if constexpr (ToAS == access::address_space::global_space)
344  return __SYCL_GenericCastToPtrExplicit_ToGlobal<ToElemT>(from);
345  else if constexpr (ToAS == access::address_space::local_space)
346  return __SYCL_GenericCastToPtrExplicit_ToLocal<ToElemT>(from);
347  else if constexpr (ToAS == access::address_space::private_space)
348  return __SYCL_GenericCastToPtrExplicit_ToPrivate<ToElemT>(from);
349 #ifdef __ENABLE_USM_ADDR_SPACE__
350  else if constexpr (ToAS == access::address_space::
351  ext_intel_global_device_space ||
352  ToAS ==
354  // For extended address spaces we do not currently have a SPIR-V
355  // conversion function, so we do a C-style cast. This may produce
356  // warnings.
357  return (ToT)from;
358 #endif // __ENABLE_USM_ADDR_SPACE__
359  else
360  return reinterpret_cast<ToT>(from);
361 #endif // defined(__NVPTX__) || defined(__AMDGCN__)
362  } else
363 #ifdef __ENABLE_USM_ADDR_SPACE__
364  if constexpr (FromAS == access::address_space::global_space &&
365  (ToAS ==
367  ToAS ==
369  // Casting from global address space to the global device and host address
370  // spaces is allowed.
371  return (ToT)from;
372  } else
373 #endif // __ENABLE_USM_ADDR_SPACE__
374 #endif // __SYCL_DEVICE_ONLY__
375  {
376  return reinterpret_cast<ToT>(from);
377  }
378 }
379 
380 } // namespace detail
381 
382 #undef __OPENCL_GLOBAL_AS__
383 #undef __OPENCL_GLOBAL_DEVICE_AS__
384 #undef __OPENCL_GLOBAL_HOST_AS__
385 #undef __OPENCL_LOCAL_AS__
386 #undef __OPENCL_CONSTANT_AS__
387 #undef __OPENCL_PRIVATE_AS__
388 
389 } // namespace _V1
390 } // namespace sycl
#define __OPENCL_PRIVATE_AS__
Definition: access.hpp:137
#define __OPENCL_GLOBAL_DEVICE_AS__
Definition: access.hpp:133
#define __OPENCL_LOCAL_AS__
Definition: access.hpp:135
#define __OPENCL_CONSTANT_AS__
Definition: access.hpp:136
#define __OPENCL_GLOBAL_AS__
Definition: access.hpp:132
#define __OPENCL_GLOBAL_HOST_AS__
Definition: access.hpp:134
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
Defines a shared image data.
Definition: image.hpp:443
ToT cast_AS(FromT from)
Definition: access.hpp:330
constexpr bool isTargetHostAccess(access::target T)
Definition: access.hpp:98
constexpr bool modeNeedsOldData(access::mode m)
Definition: access.hpp:102
constexpr bool modeWritesNewData(access::mode m)
Definition: access.hpp:107
access::mode access_mode
Definition: access.hpp:72
image_target
Definition: access.hpp:74
constexpr mode_tag_t< access_mode::read > read_only
Definition: access.hpp:84
constexpr mode_tag_t< access_mode::read_write > read_write
Definition: access.hpp:85
constexpr mode_target_tag_t< access_mode::read, target::host_task > read_only_host_task
Definition: access.hpp:90
constexpr mode_target_tag_t< access_mode::read_write, target::host_task > read_write_host_task
Definition: access.hpp:92
constexpr mode_target_tag_t< access_mode::read, target::constant_buffer > read_constant
Definition: access.hpp:88
constexpr mode_target_tag_t< access_mode::write, target::host_task > write_only_host_task
Definition: access.hpp:94
typename remove_decoration< T >::type remove_decoration_t
Definition: access.hpp:325
constexpr mode_tag_t< access_mode::write > write_only
Definition: access.hpp:86
Definition: access.hpp:18
constexpr static access::address_space AS
Definition: access.hpp:141
typename remove_decoration< T >::type * type
Definition: access.hpp:306
typename remove_decoration< T >::type & type
Definition: access.hpp:316
const typename remove_decoration< T >::type type
Definition: access.hpp:301
const typename remove_decoration< T >::type * type
Definition: access.hpp:311
const typename remove_decoration< T >::type & type
Definition: access.hpp:321
typename detail::remove_decoration_impl< T >::type type
Definition: access.hpp:296