rocPRIM
texture_cache_iterator.hpp
1 // Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef ROCPRIM_ITERATOR_TEXTURE_CACHE_ITERATOR_HPP_
22 #define ROCPRIM_ITERATOR_TEXTURE_CACHE_ITERATOR_HPP_
23 
24 #include <iterator>
25 #include <cstddef>
26 #include <type_traits>
27 
28 #include "../config.hpp"
29 #include "../functional.hpp"
30 #include "../detail/various.hpp"
31 
34 
35 BEGIN_ROCPRIM_NAMESPACE
36 
37 namespace detail
38 {
39 // Takes a scalar type T and matches to a texture type based on NumElements.
40 template <class T, unsigned int NumElements>
42 {
43  using type = void;
44 };
45 
46 template <>
47 struct make_texture_type<char, 1>
48 {
49  using type = char;
50 };
51 
52 template <>
53 struct make_texture_type<int, 1>
54 {
55  using type = int;
56 };
57 
58 template <>
59 struct make_texture_type<short, 1>
60 {
61  using type = short;
62 };
63 
64 #define DEFINE_MAKE_TEXTURE_TYPE(base, suffix) \
65 \
66 template<> \
67 struct make_texture_type<base, suffix> \
68 { \
69  using type = ::base##suffix; \
70 };
71 
72 DEFINE_MAKE_TEXTURE_TYPE(char, 2);
73 DEFINE_MAKE_TEXTURE_TYPE(char, 4);
74 DEFINE_MAKE_TEXTURE_TYPE(int, 2);
75 DEFINE_MAKE_TEXTURE_TYPE(int, 4);
76 DEFINE_MAKE_TEXTURE_TYPE(short, 2);
77 DEFINE_MAKE_TEXTURE_TYPE(short, 4);
78 
79 // Selects an appropriate vector_type based on the input T and size N.
80 // The byte size is calculated and used to select an appropriate vector_type.
81 template<class T>
83 {
84  static constexpr unsigned int size = sizeof(T);
85  using texture_base_type =
86  typename std::conditional<
87  sizeof(T) >= 4,
88  int,
89  typename std::conditional<
90  sizeof(T) >= 2,
91  short,
92  char
93  >::type
94  >::type;
95 
96  using texture_4 = typename make_texture_type<texture_base_type, 4>::type;
97  using texture_2 = typename make_texture_type<texture_base_type, 2>::type;
98  using texture_1 = typename make_texture_type<texture_base_type, 1>::type;
99 
100  using type =
101  typename std::conditional<
102  size % sizeof(texture_4) == 0,
103  texture_4,
104  typename std::conditional<
105  size % sizeof(texture_2) == 0,
106  texture_2,
107  texture_1
108  >::type
109  >::type;
110 };
111 }
112 
129 template<
130  class T,
131  class Difference = std::ptrdiff_t
132 >
134 {
135 public:
137  using value_type = typename std::remove_const<T>::type;
139  using reference = const value_type&;
141  using pointer = const value_type*;
143  using difference_type = Difference;
145  using iterator_category = std::random_access_iterator_tag;
146 
147 #ifndef DOXYGEN_SHOULD_SKIP_THIS
149 #endif
150 
151  ROCPRIM_HOST_DEVICE inline
152  ~texture_cache_iterator() = default;
153 
154  ROCPRIM_HOST_DEVICE inline
156  : ptr(NULL), texture_offset(0), texture_object(0)
157  {
158  }
159 
168  template<class Qualified>
169  inline
170  hipError_t bind_texture(Qualified* ptr,
171  size_t bytes = size_t(-1),
172  size_t texture_offset = 0)
173  {
174  this->ptr = const_cast<typename std::remove_cv<Qualified>::type*>(ptr);
175  this->texture_offset = texture_offset;
176 
177  hipChannelFormatDesc channel_desc = hipCreateChannelDesc<texture_type>();
178  hipResourceDesc resourse_desc;
179  hipTextureDesc texture_desc;
180  memset(&resourse_desc, 0, sizeof(hipResourceDesc));
181  memset(&texture_desc, 0, sizeof(hipTextureDesc));
182  resourse_desc.resType = hipResourceTypeLinear;
183  resourse_desc.res.linear.devPtr = this->ptr;
184  resourse_desc.res.linear.desc = channel_desc;
185  resourse_desc.res.linear.sizeInBytes = bytes;
186  texture_desc.readMode = hipReadModeElementType;
187 
188  return hipCreateTextureObject(&texture_object, &resourse_desc, &texture_desc, NULL);
189  }
190 
192  inline
193  hipError_t unbind_texture()
194  {
195  return hipDestroyTextureObject(texture_object);
196  }
197 
198  #ifndef DOXYGEN_SHOULD_SKIP_THIS
199  ROCPRIM_HOST_DEVICE inline
200  texture_cache_iterator& operator++()
201  {
202  ptr++;
203  texture_offset++;
204  return *this;
205  }
206 
207  ROCPRIM_HOST_DEVICE inline
208  texture_cache_iterator operator++(int)
209  {
210  texture_cache_iterator old_tc = *this;
211  ptr++;
212  texture_offset++;
213  return old_tc;
214  }
215 
216  ROCPRIM_HOST_DEVICE inline
217  value_type operator*() const
218  {
219  #ifndef __HIP_DEVICE_COMPILE__
220  return ptr[texture_offset];
221  #else
222  texture_type words[multiple];
223 
224  #if defined(__gfx940__) || defined(__gfx941__) || defined(__gfx942__)
225  #pragma message "Texture cache iterator is not supported on gfx94x as the texture fetch functions in HIP are not available."
226  ROCPRIM_PRINT_ERROR_ONCE("WARNING: Usage of texture_cache_iterator on gfx94x device is not supported and will not produce valid results.")
227  #else
228  ROCPRIM_UNROLL
229  for(unsigned int i = 0; i < multiple; i++)
230  {
231  tex1Dfetch(
232  &words[i],
233  texture_object,
234  (texture_offset * multiple) + i
235  );
236  }
237  #endif
238  return *reinterpret_cast<value_type*>(words);
239  #endif
240  }
241 
242  ROCPRIM_HOST_DEVICE inline
243  pointer operator->() const
244  {
245  return &(*(*this));
246  }
247 
248  ROCPRIM_HOST_DEVICE inline
249  texture_cache_iterator operator+(difference_type distance) const
250  {
251  self_type retval;
252  retval.ptr = ptr + distance;
253  retval.texture_object = texture_object;
254  retval.texture_offset = texture_offset + distance;
255  return retval;
256  }
257 
258  ROCPRIM_HOST_DEVICE inline
259  texture_cache_iterator& operator+=(difference_type distance)
260  {
261  ptr += distance;
262  texture_offset += distance;
263  return *this;
264  }
265 
266  ROCPRIM_HOST_DEVICE inline
267  texture_cache_iterator operator-(difference_type distance) const
268  {
269  self_type retval;
270  retval.ptr = ptr - distance;
271  retval.texture_object = texture_object;
272  retval.texture_offset = texture_offset - distance;
273  return retval;
274  }
275 
276  ROCPRIM_HOST_DEVICE inline
277  texture_cache_iterator& operator-=(difference_type distance)
278  {
279  ptr -= distance;
280  texture_offset -= distance;
281  return *this;
282  }
283 
284  ROCPRIM_HOST_DEVICE inline
285  difference_type operator-(texture_cache_iterator other) const
286  {
287  return ptr - other.ptr;
288  }
289 
290  ROCPRIM_HOST_DEVICE inline
291  value_type operator[](difference_type distance) const
292  {
293  texture_cache_iterator i = (*this) + distance;
294  return *i;
295  }
296 
297  ROCPRIM_HOST_DEVICE inline
298  bool operator==(texture_cache_iterator other) const
299  {
300  return (ptr == other.ptr) && (texture_offset == other.texture_offset);
301  }
302 
303  ROCPRIM_HOST_DEVICE inline
304  bool operator!=(texture_cache_iterator other) const
305  {
306  return (ptr != other.ptr) || (texture_offset != other.texture_offset);
307  }
308 
309  ROCPRIM_HOST_DEVICE inline
310  bool operator<(texture_cache_iterator other) const
311  {
312  return (ptr - other.ptr) > 0;
313  }
314 
315  ROCPRIM_HOST_DEVICE inline
316  bool operator<=(texture_cache_iterator other) const
317  {
318  return (ptr - other.ptr) >= 0;
319  }
320 
321  ROCPRIM_HOST_DEVICE inline
322  bool operator>(texture_cache_iterator other) const
323  {
324  return (ptr - other.ptr) < 0;
325  }
326 
327  ROCPRIM_HOST_DEVICE inline
328  bool operator>=(texture_cache_iterator other) const
329  {
330  return (ptr - other.ptr) <= 0;
331  }
332 
333  friend std::ostream& operator<<(std::ostream& os, const texture_cache_iterator& /* iter */)
334  {
335  return os;
336  }
337  #endif // DOXYGEN_SHOULD_SKIP_THIS
338 
339 private:
340  using texture_type = typename ::rocprim::detail::match_texture_type<T>::type;
341  static constexpr unsigned int multiple = sizeof(T) / sizeof(texture_type);
342  value_type* ptr;
343  difference_type texture_offset;
344  hipTextureObject_t texture_object;
345 };
346 
347 #ifndef DOXYGEN_SHOULD_SKIP_THIS
348 template<
349  class T,
350  class Difference
351 >
352 ROCPRIM_HOST_DEVICE inline
356 {
357  return iterator + distance;
358 }
359 #endif // DOXYGEN_SHOULD_SKIP_THIS
360 
361 END_ROCPRIM_NAMESPACE
362 
364 // end of group iteratormodule
365 
366 #endif // ROCPRIM_ITERATOR_TEXTURE_CACHE_ITERATOR_HPP_
Definition: texture_cache_iterator.hpp:41
ROCPRIM_HOST_DEVICE bool operator>=(const tuple< TTypes... > &lhs, const tuple< UTypes... > &rhs)
Greater than or equal to operator for tuples.
Definition: tuple.hpp:915
ROCPRIM_HOST_DEVICE bool operator<(const tuple< TTypes... > &lhs, const tuple< UTypes... > &rhs)
Less than operator for tuples.
Definition: tuple.hpp:864
hipError_t unbind_texture()
Destroys the texture object that this iterator points at.
Definition: texture_cache_iterator.hpp:193
std::random_access_iterator_tag iterator_category
The category of the iterator.
Definition: texture_cache_iterator.hpp:145
ROCPRIM_HOST_DEVICE bool operator!=(const tuple< TTypes... > &lhs, const tuple< UTypes... > &rhs)
Not equal to operator for tuples.
Definition: tuple.hpp:838
Difference difference_type
A type used for identify distance between iterators.
Definition: texture_cache_iterator.hpp:143
Deprecated: Configuration of device-level scan primitives.
Definition: block_histogram.hpp:62
const value_type & reference
A reference type of the type iterated over (value_type).
Definition: texture_cache_iterator.hpp:139
ROCPRIM_HOST_DEVICE bool operator<=(const tuple< TTypes... > &lhs, const tuple< UTypes... > &rhs)
Less than or equal to operator for tuples.
Definition: tuple.hpp:898
typename std::remove_const< T >::type value_type
The type of the value that can be obtained by dereferencing the iterator.
Definition: texture_cache_iterator.hpp:137
const value_type * pointer
A pointer type of the type iterated over (value_type).
Definition: texture_cache_iterator.hpp:141
#define ROCPRIM_PRINT_ERROR_ONCE(message)
Prints the supplied error message only once (using only one of the active threads).
Definition: functional.hpp:42
hipError_t bind_texture(Qualified *ptr, size_t bytes=size_t(-1), size_t texture_offset=0)
Creates a hipTextureObject_t and binds this iterator to it.
Definition: texture_cache_iterator.hpp:170
ROCPRIM_HOST_DEVICE bool operator>(const tuple< TTypes... > &lhs, const tuple< UTypes... > &rhs)
Greater than operator for tuples.
Definition: tuple.hpp:881
ROCPRIM_HOST_DEVICE bool operator==(const tuple< TTypes... > &lhs, const tuple< UTypes... > &rhs)
Equal to operator for tuples.
Definition: tuple.hpp:819
Definition: texture_cache_iterator.hpp:82
A random-access input (read-only) iterator adaptor for dereferencing array values through texture cac...
Definition: texture_cache_iterator.hpp:133