1313#include < sycl/detail/core.hpp>
1414using namespace sycl ;
1515
16- void init (uint32_t *A, uint32_t *B, size_t NumI32Elts) {
17- for (int I = 0 ; I < NumI32Elts; I++) {
18- A[I] = I;
19- B[I] = 0 ;
20- }
21- }
16+ template <int Dimensions> class CopyKernel ;
2217
23- int check (uint32_t *B, size_t NumI32Elts) {
24- for (int I = 0 ; I < NumI32Elts; I++) {
25- if (B[I] != I) {
26- std::cout << " Failed" << std::endl;
27- std::cerr << " Error for the index: " << I << " , computed: " << B[I]
28- << std::endl;
29- return 1 ;
30- }
31- }
32- std::cout << " Passed" << std::endl;
33- return 0 ;
34- }
18+ template <int Dimensions>
19+ bool testND (queue &Q, size_t XSize, size_t YSize, size_t ZSize = 1 ) {
3520
36- int test2D (queue &Q, size_t XSize, size_t YSize) {
37- std::cout << " Starting the test with size = {" << XSize << " , " << YSize
38- << " } ... " ;
39- size_t NumI32Elts = XSize * YSize * 4 ;
40- uint32_t *A = (uint32_t *)malloc (NumI32Elts * sizeof (uint32_t ));
41- uint32_t *B = (uint32_t *)malloc (NumI32Elts * sizeof (uint32_t ));
42- init (A, B, NumI32Elts);
21+ static_assert (Dimensions == 2 || Dimensions == 3 ,
22+ " Only 2D and 3D images are supported." );
4323
44- try {
45- image<2 > ImgA (A, image_channel_order::rgba,
46- image_channel_type::unsigned_int32, range<2 >{XSize, YSize});
47- image<2 > ImgB (B, image_channel_order::rgba,
48- image_channel_type::unsigned_int32, range<2 >{XSize, YSize});
24+ if constexpr (Dimensions == 2 )
25+ std::cout << " Starting the test with size = {" << XSize << " , " << YSize
26+ << " } ... " ;
27+ else
28+ std::cout << " Starting the test with size = {" << XSize << " , " << YSize
29+ << " , " << ZSize << " } ... " ;
4930
50- Q.submit ([&](handler &CGH) {
51- auto AAcc = ImgA.get_access <uint4, access::mode::read>(CGH);
52- auto BAcc = ImgB.get_access <uint4, access::mode::write>(CGH);
53- CGH.parallel_for <class I2D >(range<2 >{XSize, YSize}, [=](id<2 > Id) {
54- sycl::int2 Coord (Id[0 ], Id[1 ]);
55- BAcc.write (Coord, AAcc.read (Coord));
56- });
57- }).wait ();
58- } catch (exception const &e) {
59- std::cout << " Failed" << std::endl;
60- std::cerr << " SYCL Exception caught: " << e.what ();
61- return 1 ;
62- }
31+ const size_t NumI32Elts = XSize * YSize * ZSize * 4 ;
32+ range<Dimensions> ImgRange;
33+ if constexpr (Dimensions == 2 )
34+ ImgRange = range<Dimensions>{XSize, YSize};
35+ else
36+ ImgRange = range<Dimensions>{XSize, YSize, ZSize};
6337
64- int NumErrors = check (B, NumI32Elts);
65- free (A);
66- free (B);
67- return NumErrors;
68- }
38+ // Allocate input buffer and initialize it with some values.
39+ uint32_t *Input = (uint32_t *)malloc (NumI32Elts * sizeof (uint32_t ));
40+ for (int i = 0 ; i < NumI32Elts; i++)
41+ Input[i] = i;
6942
70- int test3D (queue &Q, size_t XSize, size_t YSize, size_t ZSize) {
71- std::cout << " Starting the test with size = {" << XSize << " , " << YSize
72- << " , " << ZSize << " } ... " ;
73- size_t NumI32Elts = XSize * YSize * ZSize * 4 ;
74- uint32_t *A = (uint32_t *)malloc (NumI32Elts * sizeof (uint32_t ));
75- uint32_t *B = (uint32_t *)malloc (NumI32Elts * sizeof (uint32_t ));
76- init (A, B, NumI32Elts);
43+ // calloc to ensure that the output buffer is initialized to zero.
44+ uint32_t *Output = (uint32_t *)calloc (NumI32Elts, sizeof (uint32_t ));
7745
46+ // Create the image and submit the copy kernel.
7847 try {
79- image<3 > ImgA (A, image_channel_order::rgba,
80- image_channel_type::unsigned_int32,
81- range<3 >{XSize, YSize, ZSize});
82- image<3 > ImgB (B, image_channel_order::rgba,
83- image_channel_type::unsigned_int32,
84- range<3 >{XSize, YSize, ZSize});
48+ image<Dimensions> ImgA (Input, image_channel_order::rgba,
49+ image_channel_type::unsigned_int32, ImgRange);
50+ image<Dimensions> ImgB (Output, image_channel_order::rgba,
51+ image_channel_type::unsigned_int32, ImgRange);
8552
8653 Q.submit ([&](handler &CGH) {
87- auto AAcc = ImgA.get_access <uint4, access::mode::read>(CGH);
88- auto BAcc = ImgB.get_access <uint4, access::mode::write>(CGH);
89- CGH.parallel_for <class I3D >(range<3 >{XSize, YSize, ZSize},
90- [=](id<3 > Id) {
91- sycl::int4 Coord (Id[0 ], Id[1 ], Id[2 ], 0 );
92- BAcc.write (Coord, AAcc.read (Coord));
93- });
54+ auto AAcc = ImgA.template get_access <uint4, access::mode::read>(CGH);
55+ auto BAcc = ImgB.template get_access <uint4, access::mode::write>(CGH);
56+ CGH.parallel_for <CopyKernel<Dimensions>>(
57+ ImgRange, [=](id<Dimensions> Id) {
58+ // Use int2 for 2D and int4 for 3D images.
59+ if constexpr (Dimensions == 3 ) {
60+ sycl::int4 Coord (Id[0 ], Id[1 ], Id[2 ], 0 );
61+ BAcc.write (Coord, AAcc.read (Coord));
62+ } else {
63+ sycl::int2 Coord (Id[0 ], Id[1 ]);
64+ BAcc.write (Coord, AAcc.read (Coord));
65+ }
66+ });
9467 }).wait ();
9568 } catch (exception const &e) {
69+
9670 std::cout << " Failed" << std::endl;
9771 std::cerr << " SYCL Exception caught: " << e.what ();
72+ free (Input);
73+ free (Output);
9874 return 1 ;
9975 }
10076
101- int NumErrors = check (B, NumI32Elts);
102- free (A);
103- free (B);
104- return NumErrors;
77+ // Check the output buffer.
78+ bool HasError = false ;
79+ for (int i = 0 ; i < NumI32Elts; i++) {
80+ if (Output[i] != i) {
81+ HasError = true ;
82+ break ;
83+ }
84+ }
85+
86+ if (!HasError) {
87+ std::cout << " Passed" << std::endl;
88+ } else {
89+ std::cout << " Failed" << std::endl;
90+ }
91+
92+ free (Input);
93+ free (Output);
94+ return HasError;
10595}
10696
10797int main () {
108- int NumErrors = 0 ;
109-
11098 queue Q;
11199 device Dev = Q.get_device ();
112100 std::cout << " Running on " << Dev.get_info <info::device::name>()
@@ -127,17 +115,18 @@ int main() {
127115
128116 // Using max sizes in one image may require too much memory.
129117 // Check them one by one.
130- NumErrors += test2D (Q, MaxWidth2D, 2 );
131- NumErrors += test2D (Q, 2 , MaxHeight2D);
118+ bool HasError = false ;
119+ HasError |= testND<2 >(Q, MaxWidth2D, 2 );
120+ HasError |= testND<2 >(Q, 2 , MaxHeight2D);
132121
133- NumErrors += test3D (Q, MaxWidth3D, 2 , 3 );
134- NumErrors += test3D (Q, 2 , MaxHeight3D, 3 );
135- NumErrors += test3D (Q, 2 , 3 , MaxDepth3D);
122+ HasError |= testND< 3 > (Q, MaxWidth3D, 2 , 3 );
123+ HasError |= testND< 3 > (Q, 2 , MaxHeight3D, 3 );
124+ HasError |= testND< 3 > (Q, 2 , 3 , MaxDepth3D);
136125
137- if (NumErrors )
138- std::cerr << " Test failed." << std::endl;
126+ if (HasError )
127+ std::cout << " Test failed." << std::endl;
139128 else
140129 std::cout << " Test passed." << std::endl;
141130
142- return NumErrors ;
131+ return HasError ? 1 : 0 ;
143132}
0 commit comments