Skip to content

Commit 7460245

Browse files
authored
[SYCL][Bindless] Replace 'image_channel_order' field in 'image_descriptor' with number of channels (#13745)
'image_channel_order' field in 'image_descriptor' is and can only be used for the number of channels due to CUDA having no notion of image channel order. Replaced with the number of channels instead. Also deprecate 'get_channel_order' function from 'image_mem' as it is redundant because images no longer have or need a notion of channel order. Only channel size.
1 parent 309b167 commit 7460245

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+526
-745
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_bindless_images.asciidoc

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -159,23 +159,6 @@ of 3D USM images.
159159
```cpp
160160
namespace sycl::ext::oneapi::experimental {
161161

162-
enum class image_channel_order : /* unspecified */ {
163-
a,
164-
r,
165-
rx,
166-
rg,
167-
rgx,
168-
ra,
169-
rgb,
170-
rgbx,
171-
rgba,
172-
argb,
173-
bgra,
174-
intensity,
175-
luminance,
176-
abgr,
177-
};
178-
179162
enum class image_channel_type : /* unspecified */ {
180163
snorm_int8,
181164
snorm_int16,
@@ -202,25 +185,25 @@ struct image_descriptor {
202185
size_t width{0};
203186
size_t height{0};
204187
size_t depth{0};
205-
image_channel_order channel_order{image_channel_order::rgba};
188+
unsigned int num_channels{4};
206189
image_channel_type channel_type{image_channel_type::fp32};
207190
image_type type{image_type::standard};
208191
unsigned int num_levels{1};
209192
unsigned int array_size{1};
210193

211194
image_descriptor() = default;
212195

213-
image_descriptor(sycl::range<1> dims, image_channel_order channel_order,
196+
image_descriptor(sycl::range<1> dims, unsigned int num_channels,
214197
image_channel_type channel_type,
215198
image_type type = image_type::standard,
216199
unsigned int num_levels = 1, unsigned int array_size = 1);
217200

218-
image_descriptor(sycl::range<2> dims, image_channel_order channel_order,
201+
image_descriptor(sycl::range<2> dims, unsigned int num_channels,
219202
image_channel_type channel_type,
220203
image_type type = image_type::standard,
221204
unsigned int num_levels = 1, unsigned int array_size = 1);
222205

223-
image_descriptor(sycl::range<3> dims, image_channel_order channel_order,
206+
image_descriptor(sycl::range<3> dims, unsigned int num_channels,
224207
image_channel_type channel_type,
225208
image_type type = image_type::standard,
226209
unsigned int num_levels = 1, unsigned int array_size = 1);
@@ -233,9 +216,9 @@ struct image_descriptor {
233216
}
234217
```
235218

236-
The image descriptor represents the image dimensions, channel type, and channel
237-
order. An `image_type` member is also present to allow for implementation of
238-
mipmapped, image array, and cubemapped images.
219+
The image descriptor represents the image dimensions, number of channels, and
220+
channel type. An `image_type` member is also present to allow for implementation
221+
of mipmapped, image array, and cubemapped images.
239222

240223
The `image_descriptor` shall be default constructible and follow by-value
241224
semantics.
@@ -256,6 +239,8 @@ descriptor against the limitations outlined below. If the given descriptor is
256239
deemed invalid, then a `sycl::exception` will be thrown with error code
257240
`sycl::errc::invalid`.
258241

242+
For all image types, the value of `num_channels` must be `1`, `2`, or `4`.
243+
259244
For the `standard` image type, the value of `num_levels` and `array_size` must
260245
both be `1`.
261246

@@ -311,9 +296,8 @@ public:
311296
sycl::context get_context() const;
312297

313298
sycl::range<3> get_range() const;
314-
sycl::image_channel_type get_image_channel_type() const;
315-
sycl::image_channel_type get_image_channel_order() const;
316-
unsigned int get_image_num_channels() const;
299+
sycl::image_channel_type get_channel_type() const;
300+
unsigned int get_num_channels() const;
317301
image_type get_type() const;
318302

319303
image_mem_handle get_mip_level_mem_handle(unsigned int level) const;
@@ -394,7 +378,7 @@ using the `image_mem_alloc` function. These are similar to the member functions
394378
provided by `image_mem`. However, since the `image_mem_handle` is a minimal
395379
struct representing just the opaque handle the underlying memory object, there
396380
is some information that we cannot retrieve from it, namely the `image_type`,
397-
`image_channel_order`, the `sycl::context` or `sycl::device` the memory was
381+
`num_channels`, the `sycl::context` or `sycl::device` the memory was
398382
allocated in, and the `image_descriptor` used to allocate the memory.
399383

400384
```cpp
@@ -1072,13 +1056,13 @@ void write_image(unsampled_image_handle ImageHandle,
10721056
```
10731057

10741058
Inside a kernel, it's possible to retrieve data from an image via `fetch_image`
1075-
or `sample_image`, passing the appropirate image handle. The `fetch_image` API
1059+
or `sample_image`, passing the appropriate image handle. The `fetch_image` API
10761060
is applicable to sampled and unsampled images, and the data will be fetched
10771061
exactly as is in device memory. The `sample_image` API is only applicable to
10781062
sampled images, the image data will be sampled according to the
10791063
`bindless_image_sampler` that was passed to the image upon construction.
10801064

1081-
When fetching from a sampled image handle, data exatly as is in memory, no
1065+
When fetching from a sampled image handle, data exactly as is in memory, no
10821066
sampling operations will be performed, and the `bindless_image_sampler` passed
10831067
to the image upon creation has no effect on the returned image data. Note that
10841068
not all devices may support fetching of sampled image data depending on the
@@ -1669,7 +1653,7 @@ When calling `create_image` with an `image_mem_handle` mapped from an external
16691653
memory object, the user must ensure that the image descriptor they pass to
16701654
`create_image` has members that match or map to those of the external API.
16711655
A mismatch between any of the `width`, `height`, `depth`, `image_channel_type`,
1672-
or `image_channel_order` members will result in undefined behavior.
1656+
or `num_channels` members will result in undefined behavior.
16731657

16741658
Additionally, the `image_type` describing the image must match to the image of
16751659
the external API. The current supported importable image types are `standard`
@@ -1851,7 +1835,7 @@ for (int i = 0; i < width; i++) {
18511835

18521836
// Image descriptor - can use the same for both images
18531837
sycl::ext::oneapi::experimental::image_descriptor desc(
1854-
sycl::range{width}, sycl::ext::oneapi::experimental::image_channel_order::r,
1838+
sycl::range{width}, 1,
18551839
sycl::ext::oneapi::experimental::image_channel_type::fp32);
18561840

18571841
try {
@@ -1930,7 +1914,7 @@ for (int i = 0; i < width; i++) {
19301914

19311915
// Image descriptor - can use the same for all images
19321916
sycl::ext::oneapi::experimental::image_descriptor desc(
1933-
{width, height}, sycl::ext::oneapi::experimental::image_channel_order::r,
1917+
{width, height}, 1,
19341918
sycl::ext::oneapi::experimental::image_channel_type::fp32);
19351919

19361920
try {
@@ -2030,7 +2014,7 @@ try {
20302014

20312015
// Image descriptor -- number of levels
20322016
sycl::ext::oneapi::experimental::image_descriptor desc(
2033-
{width}, sycl::ext::oneapi::experimental::image_channel_order::r,
2017+
{width}, 1,
20342018
sycl::ext::oneapi::experimental::image_channel_type::fp32,
20352019
sycl::ext::oneapi::experimental::image_type::mipmap, num_levels);
20362020

@@ -2130,7 +2114,7 @@ for (int i = 0; i < width; i++) {
21302114
try {
21312115
// Extension: image descriptor -- number of layers
21322116
sycl::ext::oneapi::experimental::image_descriptor desc(
2133-
{width}, sycl::image_channel_order::rgba, sycl::image_channel_type::fp32,
2117+
{width}, 4, sycl::image_channel_type::fp32,
21342118
sycl::ext::oneapi::experimental::image_type::array, 1, array_size);
21352119

21362120
// Extension: allocate image array memory on device
@@ -2259,7 +2243,7 @@ int main() {
22592243

22602244
// Extension: image descriptor - Cubemap
22612245
syclexp::image_descriptor desc(
2262-
{width, height}, sycl::image_channel_order::rgba,
2246+
{width, height}, 4,
22632247
sycl::image_channel_type::fp32, syclexp::image_type::cubemap, 1, 6);
22642248

22652249
syclexp::bindless_image_sampler samp(
@@ -2362,17 +2346,17 @@ sycl::context context = queue.get_context();
23622346
size_t width = /* passed from external API */;
23632347
size_t height = /* passed from external API */;
23642348

2365-
sycl::ext::oneapi::experimental::image_channel_order channel_order =
2349+
unsigned int num_channels = 1;
23662350
/* mapped from external API */
2367-
/* we assume sycl::image_channel_order::r */;
2351+
/* we assume there is one channel */;
23682352

23692353
sycl::ext::oneapi::experimental::image_channel_type channel_type =
23702354
/* mapped from external API */
23712355
/* we assume sycl::image_channel_type::unsigned_int32 */;
23722356

23732357
// Image descriptor - mapped to external API image layout
23742358
sycl::ext::oneapi::experimental::image_descriptor desc(
2375-
{width, height}, channel_order, channel_type);
2359+
{width, height}, num_channels, channel_type);
23762360

23772361
size_t img_size_in_bytes = width * height * sizeof(uint32_t);
23782362

@@ -2689,4 +2673,13 @@ These features still need to be handled:
26892673
|5.8|2024-05-09| - Add missing cubemap `HintT` template parameter to
26902674
`fetch_cubemap` and `sample_cubemap`.
26912675
|5.9|2024-05-14| - Default constructor for `image_descriptor`.
2676+
|5.10|2024-05-20| - Replaced `channel_order` field in `image_descriptor` with
2677+
`num_channels`.
2678+
- Renamed `image_mem` functions `get_image_channel_type()`
2679+
to `get_channel_type()` and `get_image_num_channels()` to
2680+
`get_num_channels()`.
2681+
- Removed `get_channel_order()` function from `image_mem`.
2682+
This function is redundant since images don't have a notion
2683+
of channel order, only the channel size. Use
2684+
`get_num_channels()` instead.
26922685
|======================

sycl/include/sycl/ext/oneapi/bindless_images_descriptor.hpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,25 @@ namespace sycl {
2121
inline namespace _V1 {
2222
namespace ext::oneapi::experimental {
2323

24+
namespace detail {
25+
26+
inline image_channel_order
27+
get_image_default_channel_order(unsigned int num_channels) {
28+
switch (num_channels) {
29+
case 1:
30+
return image_channel_order::r;
31+
case 2:
32+
return image_channel_order::rg;
33+
case 4:
34+
return image_channel_order::rgba;
35+
default:
36+
assert(false && "Invalid channel number");
37+
return static_cast<image_channel_order>(0);
38+
}
39+
}
40+
41+
} // namespace detail
42+
2443
/// image type enum
2544
enum class image_type : unsigned int {
2645
standard = 0,
@@ -34,40 +53,40 @@ struct image_descriptor {
3453
size_t width{0};
3554
size_t height{0};
3655
size_t depth{0};
37-
image_channel_order channel_order{image_channel_order::rgba};
56+
unsigned int num_channels{4};
3857
image_channel_type channel_type{image_channel_type::fp32};
3958
image_type type{image_type::standard};
4059
unsigned int num_levels{1};
4160
unsigned int array_size{1};
4261

4362
image_descriptor() = default;
4463

45-
image_descriptor(range<1> dims, image_channel_order channel_order,
64+
image_descriptor(range<1> dims, unsigned int num_channels,
4665
image_channel_type channel_type,
4766
image_type type = image_type::standard,
4867
unsigned int num_levels = 1, unsigned int array_size = 1)
49-
: width(dims[0]), height(0), depth(0), channel_order(channel_order),
68+
: width(dims[0]), height(0), depth(0), num_channels(num_channels),
5069
channel_type(channel_type), type(type), num_levels(num_levels),
5170
array_size(array_size) {
5271
verify();
5372
}
5473

55-
image_descriptor(range<2> dims, image_channel_order channel_order,
74+
image_descriptor(range<2> dims, unsigned int num_channels,
5675
image_channel_type channel_type,
5776
image_type type = image_type::standard,
5877
unsigned int num_levels = 1, unsigned int array_size = 1)
59-
: width(dims[0]), height(dims[1]), depth(0), channel_order(channel_order),
78+
: width(dims[0]), height(dims[1]), depth(0), num_channels(num_channels),
6079
channel_type(channel_type), type(type), num_levels(num_levels),
6180
array_size(array_size) {
6281
verify();
6382
}
6483

65-
image_descriptor(range<3> dims, image_channel_order channel_order,
84+
image_descriptor(range<3> dims, unsigned int num_channels,
6685
image_channel_type channel_type,
6786
image_type type = image_type::standard,
6887
unsigned int num_levels = 1, unsigned int array_size = 1)
6988
: width(dims[0]), height(dims[1]), depth(dims[2]),
70-
channel_order(channel_order), channel_type(channel_type), type(type),
89+
num_channels(num_channels), channel_type(channel_type), type(type),
7190
num_levels(num_levels), array_size(array_size) {
7291
verify();
7392
};
@@ -93,14 +112,23 @@ struct image_descriptor {
93112

94113
// This will generate the new descriptor with image_type standard
95114
// since individual mip levels are standard images
96-
sycl::ext::oneapi::experimental::image_descriptor levelDesc(
97-
{width, height, depth}, this->channel_order, this->channel_type);
115+
image_descriptor levelDesc({width, height, depth}, this->num_channels,
116+
this->channel_type);
98117

99118
levelDesc.verify();
100119
return levelDesc;
101120
}
102121

103122
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+
104132
switch (this->type) {
105133
case image_type::standard:
106134
if (this->array_size > 1) {

sycl/include/sycl/info/ext_oneapi_device_traits.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ __SYCL_PARAM_TRAITS_SPEC(ext::oneapi::experimental, device,
6666
max_image_linear_height, uint32_t,
6767
PI_EXT_ONEAPI_DEVICE_INFO_MAX_IMAGE_LINEAR_HEIGHT)
6868

69-
// Bindles images mipmaps
69+
// Bindless images mipmaps
7070
__SYCL_PARAM_TRAITS_SPEC(ext::oneapi::experimental, device,
7171
mipmap_max_anisotropy, float,
7272
PI_EXT_ONEAPI_DEVICE_INFO_MIPMAP_MAX_ANISOTROPY)

sycl/plugins/unified_runtime/pi2ur.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2947,7 +2947,7 @@ static void pi2urImageDesc(const pi_image_format *ImageFormat,
29472947
UR_IMAGE_CHANNEL_ORDER_SRGBA)
29482948
#undef PI_TO_UR_MAP_IMAGE_CHANNEL_ORDER
29492949
default: {
2950-
die("piMemImageCreate: unsuppported image_channel_data_type.");
2950+
die("piMemImageCreate: unsuppported image_channel_order.");
29512951
}
29522952
}
29532953

sycl/source/detail/bindless_images.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ void populate_pi_structs(const image_descriptor &desc, pi_image_desc &piDesc,
5252
piFormat = {};
5353
piFormat.image_channel_data_type =
5454
sycl::detail::convertChannelType(desc.channel_type);
55-
piFormat.image_channel_order =
56-
sycl::detail::convertChannelOrder(desc.channel_order);
55+
piFormat.image_channel_order = sycl::detail::convertChannelOrder(
56+
sycl::ext::oneapi::experimental::detail::get_image_default_channel_order(
57+
desc.num_channels));
5758
}
5859

5960
detail::image_mem_impl::image_mem_impl(const image_descriptor &desc,
@@ -89,13 +90,15 @@ __SYCL_EXPORT sycl::image_channel_type image_mem::get_channel_type() const {
8990
return impl->get_descriptor().channel_type;
9091
}
9192

92-
__SYCL_EXPORT sycl::image_channel_order image_mem::get_channel_order() const {
93-
return impl->get_descriptor().channel_order;
93+
__SYCL_EXPORT_DEPRECATED("get_channel_order() is deprecated. "
94+
"Instead use get_channel_num().")
95+
sycl::image_channel_order image_mem::get_channel_order() const {
96+
return sycl::ext::oneapi::experimental::detail::
97+
get_image_default_channel_order(impl->get_descriptor().num_channels);
9498
}
9599

96100
__SYCL_EXPORT unsigned int image_mem::get_num_channels() const {
97-
return sycl::detail::getImageNumberChannels(
98-
impl->get_descriptor().channel_order);
101+
return impl->get_descriptor().num_channels;
99102
}
100103

101104
__SYCL_EXPORT image_type image_mem::get_type() const {
@@ -785,10 +788,8 @@ __SYCL_EXPORT void *pitched_alloc_device(size_t *resultPitch,
785788
const image_descriptor &desc,
786789
const sycl::device &syclDevice,
787790
const sycl::context &syclContext) {
788-
uint8_t numChannels =
789-
sycl::detail::getImageNumberChannels(desc.channel_order);
790791
unsigned int elementSizeBytes =
791-
sycl::detail::getImageElementSize(numChannels, desc.channel_type);
792+
sycl::detail::getImageElementSize(desc.num_channels, desc.channel_type);
792793

793794
size_t widthInBytes = desc.width * elementSizeBytes;
794795
size_t height = desc.height;

sycl/source/detail/device_info.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2203,7 +2203,7 @@ inline uint32_t get_device_info_host<
22032203
template <>
22042204
inline float get_device_info_host<
22052205
ext::oneapi::experimental::info::device::mipmap_max_anisotropy>() {
2206-
throw runtime_error("Bindless image mipaps are not supported on HOST device",
2206+
throw runtime_error("Bindless image mipmaps are not supported on HOST device",
22072207
PI_ERROR_INVALID_DEVICE);
22082208
}
22092209

0 commit comments

Comments
 (0)