Skip to content

Commit 8facecd

Browse files
authored
[sycl][e2e][bindless-images] Refactor bindless tests: separate out functionality (#17045)
This separates out bindless-image tests into more unit-test like tests for orthogonal functionality. This reduces the number of tests that fail in #16503 when the upstream commit, f9c8c01 , is pulled down, from 7 to three. This also demonstrates that essentially all bindless-image functionality that maps directly to cuda (those using nd range or USM) work correctly even with the upstream pulldown, whereas some functionality that is SYCL specific (range parallel_for or buffers) fail. Complete information is described in the associated issue #16503 (comment) All the tests pass with the current DPC++ tip, but three of the tests fail when the above mentioned upstream commit is pulled down. - read_write_1D_buffer.cpp - read_write_1D_range.cpp - examples/example_2_2D_dynamic_read.cpp Additionally this PR removes the duplicate read_write_1D.cpp and read_2D_dynamic.cpp tests which match almost identically with the corresponding named tests in the examples folder. This is done to reduce unnecessary maintenance overhead. --------- Signed-off-by: JackAKirk <[email protected]>
1 parent 24989ab commit 8facecd

7 files changed

+222
-199
lines changed

sycl/test-e2e/bindless_images/examples/example_1_1D_read_write.cpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,17 @@ int main() {
4848
q.submit([&](sycl::handler &cgh) {
4949
// No need to request access, handles captured by value
5050

51-
cgh.parallel_for(width, [=](sycl::id<1> id) {
52-
// Extension: read image data from handle
53-
float pixel = sycl::ext::oneapi::experimental::fetch_image<float>(
54-
imgIn, int(id[0]));
55-
56-
// Extension: write to image data using handle
57-
sycl::ext::oneapi::experimental::write_image(imgOut, int(id[0]), pixel);
58-
});
51+
cgh.parallel_for(
52+
sycl::nd_range<1>{{width}, {width}}, [=](sycl::nd_item<1> it) {
53+
size_t dim0 = it.get_local_id(0);
54+
// Extension: read image data from handle
55+
float pixel = sycl::ext::oneapi::experimental::fetch_image<float>(
56+
imgIn, int(dim0));
57+
58+
// Extension: write to image data using handle
59+
sycl::ext::oneapi::experimental::write_image(imgOut, int(dim0),
60+
pixel);
61+
});
5962
});
6063

6164
// Using image handles requires manual synchronization

sycl/test-e2e/bindless_images/examples/example_4_1D_array_read_write.cpp

+31-25
Original file line numberDiff line numberDiff line change
@@ -64,31 +64,37 @@ int main() {
6464
sycl::ext::oneapi::experimental::create_image(outMem, desc, dev, ctxt);
6565

6666
q.submit([&](sycl::handler &cgh) {
67-
cgh.parallel_for<class kernel>(N, [=](sycl::id<1> id) {
68-
float sum1 = 0;
69-
float sum2 = 0;
70-
71-
// Extension: read image layers 0 and 1
72-
VecType px1 = sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
73-
arrayHandle1, int(id[0]), 0);
74-
VecType px2 = sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
75-
arrayHandle1, int(id[0]), 1);
76-
77-
// Extension: read image layers 0 and 1
78-
VecType px3 = sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
79-
arrayHandle2, int(id[0]), 0);
80-
VecType px4 = sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
81-
arrayHandle2, int(id[0]), 1);
82-
83-
sum1 = px1[0] + px3[0];
84-
sum2 = px2[0] + px4[0];
85-
86-
// Extension: write to image layers with handle
87-
sycl::ext::oneapi::experimental::write_image_array<VecType>(
88-
outHandle, int(id[0]), 0, VecType(sum1));
89-
sycl::ext::oneapi::experimental::write_image_array<VecType>(
90-
outHandle, int(id[0]), 1, VecType(sum2));
91-
});
67+
cgh.parallel_for<class kernel>(
68+
sycl::nd_range<1>{{N}, {N}}, [=](sycl::nd_item<1> it) {
69+
size_t dim0 = it.get_local_id(0);
70+
float sum1 = 0;
71+
float sum2 = 0;
72+
73+
// Extension: read image layers 0 and 1
74+
VecType px1 =
75+
sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
76+
arrayHandle1, int(dim0), 0);
77+
VecType px2 =
78+
sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
79+
arrayHandle1, int(dim0), 1);
80+
81+
// Extension: read image layers 0 and 1
82+
VecType px3 =
83+
sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
84+
arrayHandle2, int(dim0), 0);
85+
VecType px4 =
86+
sycl::ext::oneapi::experimental::fetch_image_array<VecType>(
87+
arrayHandle2, int(dim0), 1);
88+
89+
sum1 = px1[0] + px3[0];
90+
sum2 = px2[0] + px4[0];
91+
92+
// Extension: write to image layers with handle
93+
sycl::ext::oneapi::experimental::write_image_array<VecType>(
94+
outHandle, int(dim0), 0, VecType(sum1));
95+
sycl::ext::oneapi::experimental::write_image_array<VecType>(
96+
outHandle, int(dim0), 1, VecType(sum2));
97+
});
9298
});
9399

94100
q.wait_and_throw();

sycl/test-e2e/bindless_images/read_2D_dynamic.cpp

-135
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// REQUIRES: aspect-ext_oneapi_bindless_images
2+
3+
// UNSUPPORTED: hip
4+
// UNSUPPORTED-INTENDED: Undetermined issue in 'create_image' in this test.
5+
6+
// RUN: %{build} -o %t.out
7+
// RUN: %{run-unfiltered-devices} env NEOReadDebugKeys=1 UseBindlessMode=1 UseExternalAllocatorForSshAndDsh=1 %t.out
8+
9+
// This tests that sycl::buffer works with image fetches
10+
// Currently this fails when
11+
// https://github.com/intel/llvm/commit/f9c8c01d38f8fbea81db99ab90b7d0f2bdcc8b4d
12+
// is cherry-picked. See https://github.com/intel/llvm/issues/16503
13+
14+
#include <iostream>
15+
#include <sycl/detail/core.hpp>
16+
17+
#include <sycl/ext/oneapi/bindless_images.hpp>
18+
19+
// Uncomment to print additional test information
20+
// #define VERBOSE_PRINT
21+
22+
class image_addition;
23+
24+
int main() {
25+
26+
sycl::device dev;
27+
sycl::queue q(dev);
28+
auto ctxt = q.get_context();
29+
30+
// declare image data
31+
constexpr size_t width = 512;
32+
std::vector<sycl::float4> out(width);
33+
std::vector<float> expected(width);
34+
std::vector<sycl::float4> dataIn1(width);
35+
std::vector<sycl::float4> dataIn2(width);
36+
float exp = 512;
37+
for (int i = 0; i < width; i++) {
38+
expected[i] = exp;
39+
dataIn1[i] = sycl::float4(i, i, i, i);
40+
dataIn2[i] = sycl::float4(width - i, width - i, width - i, width - i);
41+
}
42+
43+
try {
44+
// Extension: image descriptor - can use the same for both images
45+
sycl::ext::oneapi::experimental::image_descriptor desc(
46+
{width}, 4, sycl::image_channel_type::fp32);
47+
48+
// Extension: allocate memory on device and create the handle
49+
// Input images memory
50+
sycl::ext::oneapi::experimental::image_mem imgMem0(desc, dev, ctxt);
51+
sycl::ext::oneapi::experimental::image_mem imgMem1(desc, dev, ctxt);
52+
53+
// Output image memory
54+
sycl::ext::oneapi::experimental::image_mem imgMem2(desc, dev, ctxt);
55+
56+
// Extension: copy over data to device
57+
q.ext_oneapi_copy(dataIn1.data(), imgMem0.get_handle(), desc);
58+
q.ext_oneapi_copy(dataIn2.data(), imgMem1.get_handle(), desc);
59+
q.wait_and_throw();
60+
61+
// Extension: create the image and return the handle
62+
sycl::ext::oneapi::experimental::unsampled_image_handle imgIn1 =
63+
sycl::ext::oneapi::experimental::create_image(imgMem0, desc, dev, ctxt);
64+
sycl::ext::oneapi::experimental::unsampled_image_handle imgIn2 =
65+
sycl::ext::oneapi::experimental::create_image(imgMem1, desc, dev, ctxt);
66+
67+
sycl::ext::oneapi::experimental::unsampled_image_handle imgOut =
68+
sycl::ext::oneapi::experimental::create_image(imgMem2, desc, dev, ctxt);
69+
sycl::range<1> r(1);
70+
sycl::buffer<sycl::ext::oneapi::experimental::unsampled_image_handle, 1>
71+
imgHandlesBuf{&imgIn1, r};
72+
sycl::buffer<sycl::float4, 1> buf(out.data(), sycl::range<1>{width});
73+
q.submit([&](sycl::handler &cgh) {
74+
sycl::accessor imgHandleAcc{imgHandlesBuf, cgh, sycl::read_only};
75+
sycl::accessor outAcc{buf, cgh, sycl::write_only};
76+
cgh.parallel_for<image_addition>(
77+
sycl::nd_range<1>{{width}, {width}}, [=](sycl::nd_item<1> it) {
78+
size_t dim0 = it.get_local_id(0);
79+
float sum = 0;
80+
// Extension: fetch image data from handle
81+
sycl::float4 px1 =
82+
sycl::ext::oneapi::experimental::fetch_image<sycl::float4>(
83+
imgHandleAcc[0], int(dim0));
84+
sycl::float4 px2 =
85+
sycl::ext::oneapi::experimental::fetch_image<sycl::float4>(
86+
imgIn2, int(dim0));
87+
88+
sum = px1[0] + px2[0];
89+
// Extension: write to image with handle
90+
outAcc[dim0][0] = sum;
91+
});
92+
});
93+
94+
q.wait_and_throw();
95+
// Extension: copy data from device to host
96+
q.ext_oneapi_copy(imgMem2.get_handle(), out.data(), desc);
97+
q.wait_and_throw();
98+
99+
// Extension: cleanup
100+
sycl::ext::oneapi::experimental::destroy_image_handle(imgIn1, dev, ctxt);
101+
sycl::ext::oneapi::experimental::destroy_image_handle(imgIn2, dev, ctxt);
102+
sycl::ext::oneapi::experimental::destroy_image_handle(imgOut, dev, ctxt);
103+
} catch (sycl::exception e) {
104+
std::cerr << "SYCL exception caught! : " << e.what() << "\n";
105+
return 1;
106+
} catch (...) {
107+
std::cerr << "Unknown exception caught!\n";
108+
return 2;
109+
}
110+
111+
// collect and validate output
112+
bool validated = true;
113+
for (int i = 0; i < width; i++) {
114+
bool mismatch = false;
115+
if (out[i][0] != expected[i]) {
116+
mismatch = true;
117+
validated = false;
118+
}
119+
120+
if (mismatch) {
121+
#ifdef VERBOSE_PRINT
122+
std::cout << "Result mismatch! Expected: " << expected[i]
123+
<< ", Actual: " << out[i][0] << std::endl;
124+
#else
125+
break;
126+
#endif
127+
}
128+
}
129+
if (validated) {
130+
std::cout << "Test passed!" << std::endl;
131+
return 0;
132+
}
133+
134+
std::cout << "Test failed!" << std::endl;
135+
return 3;
136+
}

0 commit comments

Comments
 (0)