DPC++ Runtime
Runtime libraries for oneAPI DPC++
bindless_images_descriptor.hpp
Go to the documentation of this file.
1 //==------ bindless_images_descriptor.hpp --- SYCL bindless images ---------==//
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/array.hpp> // for array
12 #include <sycl/exception.hpp> // for errc, exception
13 #include <sycl/image.hpp> // for image_channel_order, image_channel_type
14 #include <sycl/range.hpp> // for range
15 
16 #include <algorithm> // for max
17 #include <stddef.h> // for size_t
18 #include <system_error> // for error_code
19 
20 namespace sycl {
21 inline namespace _V1 {
22 namespace ext::oneapi::experimental {
23 
24 namespace detail {
25 
27 get_image_default_channel_order(unsigned int num_channels) {
28  switch (num_channels) {
29  case 1:
31  case 2:
33  case 4:
35  default:
36  assert(false && "Invalid channel number");
37  return static_cast<image_channel_order>(0);
38  }
39 }
40 
41 } // namespace detail
42 
44 enum class image_type : unsigned int {
45  standard = 0,
46  mipmap = 1,
47  array = 2,
48  cubemap = 3,
49 };
50 
53  size_t width{0};
54  size_t height{0};
55  size_t depth{0};
56  unsigned int num_channels{4};
59  unsigned int num_levels{1};
60  unsigned int array_size{1};
61 
62  image_descriptor() = default;
63 
67  unsigned int num_levels = 1, unsigned int array_size = 1)
68  : width(dims[0]), height(0), depth(0), num_channels(num_channels),
71  verify();
72  }
73 
77  unsigned int num_levels = 1, unsigned int array_size = 1)
78  : width(dims[0]), height(dims[1]), depth(0), num_channels(num_channels),
81  verify();
82  }
83 
87  unsigned int num_levels = 1, unsigned int array_size = 1)
88  : width(dims[0]), height(dims[1]), depth(dims[2]),
91  verify();
92  };
93 
95  image_descriptor get_mip_level_desc(unsigned int level) const {
96  // Check that this descriptor describes a mipmap - otherwise throw
97  if (this->type != image_type::mipmap)
98  throw sycl::exception(
99  sycl::errc::invalid,
100  "Invalid descriptor `image_type` passed to "
101  "`get_mip_level_desc`. A mipmap level descriptor can only be "
102  "requested by a descriptor with mipmap image type!");
103 
104  // Generate a new descriptor which represents the level accordingly
105  // Do not allow height/depth values to be clamped to 1 when naturally 0
106  size_t width = std::max<size_t>(this->width >> level, 1);
107  size_t height = this->height == 0
108  ? this->height
109  : std::max<size_t>(this->height >> level, 1);
110  size_t depth = this->depth == 0 ? this->depth
111  : std::max<size_t>(this->depth >> level, 1);
112 
113  // This will generate the new descriptor with image_type standard
114  // since individual mip levels are standard images
115  image_descriptor levelDesc({width, height, depth}, this->num_channels,
116  this->channel_type);
117 
118  levelDesc.verify();
119  return levelDesc;
120  }
121 
122  void verify() const {
123 
124  if (this->num_channels != 1 && this->num_channels != 2 &&
125  this->num_channels != 4) {
126  // Images can only have 1, 2, or 4 channels.
127  throw sycl::exception(sycl::errc::invalid,
128  "Images must have only 1, 2, or 4 channels! Use a "
129  "valid number of channels instead.");
130  }
131 
132  switch (this->type) {
134  if (this->array_size > 1) {
135  // Not a standard image.
136  throw sycl::exception(
137  sycl::errc::invalid,
138  "Standard images cannot have array_size greater than 1! Use "
139  "image_type::array for image arrays.");
140  }
141  if (this->num_levels > 1) {
142  // Image arrays cannot be mipmaps.
143  throw sycl::exception(
144  sycl::errc::invalid,
145  "Standard images cannot have num_levels greater than 1! Use "
146  "image_type::mipmap for mipmap images.");
147  }
148  return;
149 
150  case image_type::array:
151  if (this->array_size <= 1) {
152  // Not an image array.
153  throw sycl::exception(sycl::errc::invalid,
154  "Image array must have array_size greater than "
155  "1! Use image_type::standard otherwise.");
156  }
157  if (this->depth != 0) {
158  // Image arrays must only be 1D or 2D.
159  throw sycl::exception(sycl::errc::invalid,
160  "Cannot have 3D image arrays! Either depth must "
161  "be 0 or array_size must be 1.");
162  }
163  if (this->num_levels != 1) {
164  // Image arrays cannot be mipmaps.
165  throw sycl::exception(sycl::errc::invalid,
166  "Cannot have mipmap image arrays! Either "
167  "num_levels or array_size must be 1.");
168  }
169  return;
170 
171  case image_type::mipmap:
172  if (this->array_size > 1) {
173  // Mipmap images cannot be arrays.
174  throw sycl::exception(
175  sycl::errc::invalid,
176  "Mipmap images cannot have array_size greater than 1! Use "
177  "image_type::array for image arrays.");
178  }
179  if (this->num_levels <= 1) {
180  // Mipmaps must have more than one level.
181  throw sycl::exception(sycl::errc::invalid,
182  "Mipmap images must have num_levels greater than "
183  "1! Use image_type::standard otherwise.");
184  }
185  return;
186 
187  case image_type::cubemap:
188  if (this->array_size != 6) {
189  // Cubemaps must have an array size of 6.
190  throw sycl::exception(sycl::errc::invalid,
191  "Cubemap images must have array_size of 6 only! "
192  "Use image_type::array instead.");
193  }
194  if (this->depth != 0 || this->height == 0 ||
195  this->width != this->height) {
196  // Cubemaps must be 2D
197  throw sycl::exception(
198  sycl::errc::invalid,
199  "Cubemap images must be square with valid and equivalent width and "
200  "height! Use image_type::array instead.");
201  }
202  if (this->num_levels != 1) {
203  // Cubemaps cannot be mipmaps.
204  throw sycl::exception(sycl::errc::invalid,
205  "Cannot have mipmap cubemaps! Either num_levels "
206  "or array_size must be 1.");
207  }
208  return;
209  }
210  }
211 };
212 
213 } // namespace ext::oneapi::experimental
214 } // namespace _V1
215 } // namespace sycl
image_channel_order get_image_default_channel_order(unsigned int num_channels)
image_channel_order
Definition: image.hpp:56
image_channel_type
Definition: image.hpp:74
Definition: access.hpp:18
A struct to describe the properties of an image.
image_descriptor(range< 1 > dims, unsigned int num_channels, image_channel_type channel_type, image_type type=image_type::standard, unsigned int num_levels=1, unsigned int array_size=1)
image_descriptor(range< 3 > dims, unsigned int num_channels, image_channel_type channel_type, image_type type=image_type::standard, unsigned int num_levels=1, unsigned int array_size=1)
image_descriptor get_mip_level_desc(unsigned int level) const
Get the descriptor for a mipmap level.
image_descriptor(range< 2 > dims, unsigned int num_channels, image_channel_type channel_type, image_type type=image_type::standard, unsigned int num_levels=1, unsigned int array_size=1)