Skip to content

Commit b437083

Browse files
authored
[SYCL][E2E][BINDLESS] Add ptr to ptr of image_handle test failing on level zero only (#18721)
This test passes on the cuda backend but fails on level_zero. It allocates a single element array of `unsampled_image_handle*`, pointing to a valid `unsampled_image_handle` that is dereferenced on the device. The casting to generic `void*` is not necessary to make the test fail on l0, but is done to keep this test matching the original bug report we received. Note that rewriting this test to make an identical dereference with for example a single 2d C array of `long` passes on level_zero, indicating that this issue is specific to image_handles. --------- Signed-off-by: JackAKirk <[email protected]>
1 parent 0b19860 commit b437083

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// REQUIRES: aspect-ext_oneapi_bindless_images
2+
// XFAIL: level_zero && windows
3+
// XFAIL-TRACKER: https://github.com/intel/llvm/issues/18727
4+
// UNSUPPORTED: hip
5+
// UNSUPPORTED-INTENDED: Undetermined issue in 'create_image' in this test.
6+
7+
// RUN: %{build} -o %t.out
8+
// RUN: %{run} env NEOReadDebugKeys=1 UseBindlessMode=1 UseExternalAllocatorForSshAndDsh=1 %t.out
9+
10+
#include <sycl/detail/core.hpp>
11+
#include <sycl/ext/oneapi/bindless_images.hpp>
12+
#include <sycl/usm.hpp>
13+
14+
namespace syclexp = sycl::ext::oneapi::experimental;
15+
16+
int main() {
17+
18+
sycl::queue q{};
19+
20+
// Initialize input data
21+
constexpr size_t width = 512;
22+
std::vector<float> dataIn(width);
23+
std::vector<float> dataOut(width);
24+
for (int i = 0; i < width; i++) {
25+
dataIn[i] = static_cast<float>(i);
26+
}
27+
28+
// Image descriptor - can use the same for both images
29+
syclexp::image_descriptor desc(sycl::range{width}, 1,
30+
sycl::image_channel_type::fp32);
31+
32+
// Extension: returns the device pointer to the allocated memory
33+
syclexp::image_mem imgMemoryIn(desc, q);
34+
syclexp::image_mem imgMemoryOut(desc, q);
35+
36+
q.ext_oneapi_copy(dataIn.data(), imgMemoryIn.get_handle(), desc);
37+
q.wait_and_throw();
38+
// Extension: create the image and return the handle
39+
syclexp::unsampled_image_handle imgIn =
40+
syclexp::create_image(imgMemoryIn, desc, q);
41+
syclexp::unsampled_image_handle imgOut =
42+
syclexp::create_image(imgMemoryOut, desc, q);
43+
44+
// Copy the input data to the image_mem of the device unsampled_image_handle
45+
q.ext_oneapi_copy(dataIn.data(), imgMemoryIn.get_handle(), desc);
46+
q.wait_and_throw();
47+
48+
// Allocate an unsampled_image_handle manually instead of using create_image
49+
// so we can allocate it on the heap
50+
void *imageHandlePtrGen =
51+
sycl::malloc_device(sizeof(syclexp::unsampled_image_handle), q);
52+
53+
// Copy the create_image returned device unsampled_image_handle to the
54+
// contents of the void* pointing to the heap allocated
55+
// unsampled_image_handle
56+
q.memcpy(static_cast<void *>(imageHandlePtrGen),
57+
static_cast<const void *>(&imgIn),
58+
sizeof(syclexp::unsampled_image_handle));
59+
60+
q.wait_and_throw();
61+
62+
// Allocate a device generic pointer pointing to an unsampled_image_handle*
63+
void *imageHandlePtrPtrGen =
64+
sycl::malloc_device(sizeof(syclexp::unsampled_image_handle *), q);
65+
66+
// Copy the address of the manually allocated unsampled_image_handle to the
67+
// contents of the generic device pointer allocated above
68+
q.memcpy(static_cast<void *>(imageHandlePtrPtrGen),
69+
static_cast<const void *>(&imageHandlePtrGen),
70+
sizeof(syclexp::unsampled_image_handle *));
71+
72+
q.wait_and_throw();
73+
74+
q.submit([&](sycl::handler &cgh) {
75+
cgh.parallel_for(
76+
sycl::nd_range<1>{{width}, {width}}, [=](sycl::nd_item<1> it) {
77+
syclexp::unsampled_image_handle **imageHandlePtrPtr =
78+
static_cast<syclexp::unsampled_image_handle **>(
79+
imageHandlePtrPtrGen);
80+
// Dereference the generic pointer to the unsampled_image_handle
81+
// pointer
82+
syclexp::unsampled_image_handle *imageHandlePtr =
83+
static_cast<syclexp::unsampled_image_handle *>(
84+
imageHandlePtrPtr[0]);
85+
// Dereference the unsampled_image_handle pointer
86+
syclexp::unsampled_image_handle imageHandle = imageHandlePtr[0];
87+
88+
size_t dim0 = it.get_local_id(0);
89+
// Extension: read image data from handle
90+
float pixel = syclexp::fetch_image<float>(imageHandle, int(dim0));
91+
92+
// Extension: write to image data using handle
93+
syclexp::write_image(imgOut, int(dim0), pixel);
94+
});
95+
});
96+
97+
q.wait_and_throw();
98+
99+
// Copy data written to imgOut to host
100+
q.ext_oneapi_copy(imgMemoryOut.get_handle(), dataOut.data(), desc);
101+
102+
// Ensure copying data from the device to host is finished before validate
103+
q.wait_and_throw();
104+
105+
// Cleanup
106+
syclexp::destroy_image_handle(imgIn, q);
107+
syclexp::destroy_image_handle(imgOut, q);
108+
sycl::free(imageHandlePtrGen, q);
109+
sycl::free(imageHandlePtrPtrGen, q);
110+
111+
for (size_t i = 0; i < width; i++) {
112+
if (dataOut[i] != dataIn[i]) {
113+
std::cout << "Test failed"
114+
<< "\n";
115+
return 1;
116+
}
117+
}
118+
return 0;
119+
}

0 commit comments

Comments
 (0)