1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "harness/compat.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23
24
25 #include "procs.h"
26
27 static unsigned char *
generate_rgba8_image(int w,int h,MTdata d)28 generate_rgba8_image(int w, int h, MTdata d)
29 {
30 unsigned char *ptr = (unsigned char*)malloc(w * h * 4);
31 int i;
32
33 for (i=0; i<w*h*4; i++)
34 ptr[i] = (unsigned char)genrand_int32(d);
35
36 return ptr;
37 }
38
39 static void
update_rgba8_image(unsigned char * p,int x,int y,int w,int h,int img_width,MTdata d)40 update_rgba8_image(unsigned char *p, int x, int y, int w, int h, int img_width, MTdata d)
41 {
42 int i, j, indx;
43
44 for (i=y; i<y+h; i++)
45 {
46 indx = (i * img_width + x) * 4;
47 for (j=x; j<x+w; j++,indx+=4)
48 {
49 p[indx+0] = (unsigned char)genrand_int32(d);
50 p[indx+1] = (unsigned char)genrand_int32(d);
51 p[indx+2] = (unsigned char)genrand_int32(d);
52 p[indx+3] = (unsigned char)genrand_int32(d);
53 }
54 }
55 }
56
57 static void
update_image_from_image(void * out,void * in,int x,int y,int w,int h,int img_width,int elem_size)58 update_image_from_image(void *out, void *in, int x, int y, int w, int h, int img_width, int elem_size)
59 {
60 int i, j, k, out_indx, in_indx;
61 in_indx = 0;
62
63 for (i=y; i<y+h; i++)
64 {
65 out_indx = (i * img_width + x) * elem_size;
66 for (j=x; j<x+w; j++,out_indx+=elem_size)
67 {
68 for (k=0; k<elem_size; k++)
69 {
70 ((char*)out)[out_indx + k] = ((char*)in)[in_indx];
71 in_indx++;
72 }
73 }
74 }
75 }
76
77 static int
verify_rgba8_image(unsigned char * image,unsigned char * outptr,int w,int h)78 verify_rgba8_image(unsigned char *image, unsigned char *outptr, int w, int h)
79 {
80 int i;
81
82 for (i=0; i<w*h*4; i++)
83 {
84 if (outptr[i] != image[i])
85 {
86 log_error("i = %d. Expected (%d %d %d %d), got (%d %d %d %d)\n", i, image[i], image[i+1], image[i+2], image[i+3], outptr[i], outptr[i+1], outptr[i+2], outptr[i+3]);
87 return -1;
88 }
89 }
90
91 return 0;
92 }
93
94
95 static unsigned short *
generate_rgba16_image(int w,int h,MTdata d)96 generate_rgba16_image(int w, int h, MTdata d)
97 {
98 unsigned short *ptr = (unsigned short*)malloc(w * h * 4 * sizeof(unsigned short));
99 int i;
100
101 for (i=0; i<w*h*4; i++)
102 ptr[i] = (unsigned short)genrand_int32(d);
103
104 return ptr;
105 }
106
107 static void
update_rgba16_image(unsigned short * p,int x,int y,int w,int h,int img_width,MTdata d)108 update_rgba16_image(unsigned short *p, int x, int y, int w, int h, int img_width, MTdata d)
109 {
110 int i, j, indx;
111
112 for (i=y; i<y+h; i++)
113 {
114 indx = (i * img_width + x) * 4;
115 for (j=x; j<x+w; j++,indx+=4)
116 {
117 p[indx+0] = (unsigned short)genrand_int32(d);
118 p[indx+1] = (unsigned short)genrand_int32(d);
119 p[indx+2] = (unsigned short)genrand_int32(d);
120 p[indx+3] = (unsigned short)genrand_int32(d);
121 }
122 }
123 }
124
125 static int
verify_rgba16_image(unsigned short * image,unsigned short * outptr,int w,int h)126 verify_rgba16_image(unsigned short *image, unsigned short *outptr, int w, int h)
127 {
128 int i;
129
130 for (i=0; i<w*h*4; i++)
131 {
132 if (outptr[i] != image[i])
133 {
134 log_error("i = %d. Expected (%d %d %d %d), got (%d %d %d %d)\n", i, image[i], image[i+1], image[i+2], image[i+3], outptr[i], outptr[i+1], outptr[i+2], outptr[i+3]);
135 return -1;
136 }
137 }
138
139 return 0;
140 }
141
142
143 static float *
generate_rgbafp_image(int w,int h,MTdata d)144 generate_rgbafp_image(int w, int h, MTdata d)
145 {
146 float *ptr = (float*)malloc(w * h * 4 * sizeof(float));
147 int i;
148
149 for (i=0; i<w*h*4; i++)
150 ptr[i] = get_random_float(-0x40000000, 0x40000000, d);
151
152 return ptr;
153 }
154
155 static void
update_rgbafp_image(float * p,int x,int y,int w,int h,int img_width,MTdata d)156 update_rgbafp_image(float *p, int x, int y, int w, int h, int img_width, MTdata d)
157 {
158 int i, j, indx;
159
160 for (i=y; i<y+h; i++)
161 {
162 indx = (i * img_width + x) * 4;
163 for (j=x; j<x+w; j++,indx+=4)
164 {
165 p[indx+0] = get_random_float(-0x40000000, 0x40000000, d);
166 p[indx+1] = get_random_float(-0x40000000, 0x40000000, d);
167 p[indx+2] = get_random_float(-0x40000000, 0x40000000, d);
168 p[indx+3] = get_random_float(-0x40000000, 0x40000000, d);
169 }
170 }
171 }
172
173 static int
verify_rgbafp_image(float * image,float * outptr,int w,int h)174 verify_rgbafp_image(float *image, float *outptr, int w, int h)
175 {
176 int i;
177
178 for (i=0; i<w*h*4; i++)
179 {
180 if (outptr[i] != image[i])
181 {
182 log_error("i = %d. Expected (%f %f %f %f), got (%f %f %f %f)\n", i, image[i], image[i+1], image[i+2], image[i+3], outptr[i], outptr[i+1], outptr[i+2], outptr[i+3]);
183 return -1;
184 }
185 }
186
187 return 0;
188 }
189
190
191 int
test_imagereadwrite(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)192 test_imagereadwrite(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
193 {
194 cl_image_format img_format;
195 unsigned char *rgba8_inptr, *rgba8_outptr;
196 unsigned short *rgba16_inptr, *rgba16_outptr;
197 float *rgbafp_inptr, *rgbafp_outptr;
198 clMemWrapper streams[3];
199 int img_width = 512;
200 int img_height = 512;
201 int num_tries = 200;
202 int i, j, err;
203 MTdata d;
204
205 PASSIVE_REQUIRE_IMAGE_SUPPORT( device )
206
207 d = init_genrand( gRandomSeed );
208 rgba8_inptr = (unsigned char *)generate_rgba8_image(img_width, img_height, d);
209 rgba16_inptr = (unsigned short *)generate_rgba16_image(img_width, img_height, d);
210 rgbafp_inptr = (float *)generate_rgbafp_image(img_width, img_height, d);
211
212 rgba8_outptr = (unsigned char*)malloc(sizeof(unsigned char) * 4 * img_width * img_height);
213 rgba16_outptr = (unsigned short*)malloc(sizeof(unsigned short) * 4 * img_width * img_height);
214 rgbafp_outptr = (float*)malloc(sizeof(float) * 4 * img_width * img_height);
215
216 img_format.image_channel_order = CL_RGBA;
217 img_format.image_channel_data_type = CL_UNORM_INT8;
218 streams[0] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format,
219 img_width, img_height, 0, NULL, &err);
220 test_error(err, "create_image_2d failed");
221
222 img_format.image_channel_order = CL_RGBA;
223 img_format.image_channel_data_type = CL_UNORM_INT16;
224 streams[1] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format,
225 img_width, img_height, 0, NULL, &err);
226 test_error(err, "create_image_2d failed");
227
228 img_format.image_channel_order = CL_RGBA;
229 img_format.image_channel_data_type = CL_FLOAT;
230 streams[2] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format,
231 img_width, img_height, 0, NULL, &err);
232 test_error(err, "create_image_2d failed");
233
234 for (i=0; i<3; i++)
235 {
236 void *p;
237
238 if (i == 0)
239 p = (void *)rgba8_inptr;
240 else if (i == 1)
241 p = (void *)rgba16_inptr;
242 else
243 p = (void *)rgbafp_inptr;
244 size_t origin[3] = {0,0,0}, region[3] = {img_width, img_height, 1};
245 err = clEnqueueWriteImage(queue, streams[i], CL_TRUE,
246 origin, region, 0, 0,
247 p, 0, NULL, NULL);
248 if (err != CL_SUCCESS)
249 {
250 log_error("clWriteImage2D failed\n");
251 return -1;
252 }
253 }
254
255 for (i=0,j=0; i<num_tries*3; i++,j++)
256 {
257 int x = (int)get_random_float(0, img_width, d);
258 int y = (int)get_random_float(0, img_height, d);
259 int w = (int)get_random_float(1, (img_width - x), d);
260 int h = (int)get_random_float(1, (img_height - y), d);
261 size_t input_pitch;
262 int set_input_pitch = (int)(genrand_int32(d) & 0x01);
263 int packed_update = (int)(genrand_int32(d) & 0x01);
264 void *p, *outp;
265 int elem_size;
266
267 if (j == 3)
268 j = 0;
269
270 switch (j)
271 {
272 case 0:
273 //if ((w<=10) || (h<=10)) continue;
274 elem_size = 4;
275 if(packed_update)
276 {
277 p = generate_rgba8_image(w, h, d);
278 update_image_from_image(rgba8_inptr, p, x, y, w, h, img_width, elem_size);
279 }
280 else
281 {
282 update_rgba8_image(rgba8_inptr, x, y, w, h, img_width, d);
283 p = (void *)(rgba8_inptr + ((y * img_width + x) * 4));
284 }
285 outp = (void *)rgba8_outptr;
286 break;
287 case 1:
288 //if ((w<=8) || (h<=8)) continue;
289 elem_size = 2*4;
290 if(packed_update)
291 {
292 p = generate_rgba16_image(w, h, d);
293 update_image_from_image(rgba16_inptr, p, x, y, w, h, img_width, elem_size);
294 }
295 else
296 {
297 update_rgba16_image(rgba16_inptr, x, y, w, h, img_width, d);
298 p = (void *)(rgba16_inptr + ((y * img_width + x) * 4));
299 }
300 outp = (void *)rgba16_outptr;
301 break;
302 case 2:
303 //if ((w<=8) || (h<=8)) continue;
304 elem_size = 4*4;
305 if(packed_update)
306 {
307 p = generate_rgbafp_image(w, h, d);
308 update_image_from_image(rgbafp_inptr, p, x, y, w, h, img_width, elem_size);
309 }
310 else
311 {
312 update_rgbafp_image(rgbafp_inptr, x, y, w, h, img_width, d);
313 p = (void *)(rgbafp_inptr + ((y * img_width + x) * 4));
314 }
315 outp = (void *)rgbafp_outptr;
316 break;
317 }
318
319 const char* update_packed_pitch_name = "";
320 if(packed_update)
321 {
322 if(set_input_pitch)
323 {
324 // for packed updates the pitch does not need to be calculated here (but can be)
325 update_packed_pitch_name = "'packed with pitch'";
326 input_pitch = w*elem_size;
327 }
328 else
329 {
330 // for packed updates the pitch does not need to be calculated here
331 update_packed_pitch_name = "'packed without pitch'";
332 input_pitch = 0;
333 }
334 }
335 else
336 {
337 // for unpacked updates the pitch is required
338 update_packed_pitch_name = "'unpacked with pitch'";
339 input_pitch = img_width*elem_size;
340 }
341
342 size_t origin[3] = {x,y,0}, region[3] = {w, h, 1};
343 err = clEnqueueWriteImage(queue, streams[j], CL_TRUE,
344 origin, region, input_pitch, 0, p,
345 0, NULL, NULL);
346 if (err != CL_SUCCESS)
347 {
348 log_error("clWriteImage update failed for %s %s: %d\n",
349 (packed_update) ? "packed" : "unpacked",
350 (set_input_pitch) ? "set pitch" : "unset pitch", err);
351 free_mtdata(d);
352 return -1;
353 }
354
355 if(packed_update)
356 {
357 free(p);
358 p = NULL;
359 }
360
361 memset(outp, 0x7, img_width*img_height*elem_size);
362
363 origin[0]=0; origin[1]=0; origin[2]=0;
364 region[0]=img_width; region[1]=img_height; region[2]=1;
365 err = clEnqueueReadImage(queue, streams[j], CL_TRUE,
366 origin, region, 0,0,
367 outp, 0, NULL, NULL);
368 if (err != CL_SUCCESS)
369 {
370 log_error("clReadImage failed\n");
371 free_mtdata(d);
372 return -1;
373 }
374
375 switch (j)
376 {
377 case 0:
378 err = verify_rgba8_image(rgba8_inptr, rgba8_outptr, img_width, img_height);
379 if (err)
380 {
381 log_error("x=%d y=%d w=%d h=%d, pitch=%d, try=%d\n", x, y, w, h, (int)input_pitch, (int)i);
382 log_error("IMAGE RGBA8 read, write %s test failed\n", update_packed_pitch_name);
383 }
384 break;
385 case 1:
386 err = verify_rgba16_image(rgba16_inptr, rgba16_outptr, img_width, img_height);
387 if (err)
388 {
389 log_error("x=%d y=%d w=%d h=%d, pitch=%d, try=%d\n", x, y, w, h, (int)input_pitch, (int)i);
390 log_error("IMAGE RGBA16 read, write %s test failed\n", update_packed_pitch_name);
391 }
392 break;
393 case 2:
394 err = verify_rgbafp_image(rgbafp_inptr, rgbafp_outptr, img_width, img_height);
395 if (err)
396 {
397 log_error("x=%d y=%d w=%d h=%d, pitch=%d, try=%d\n", x, y, w, h, (int)input_pitch, (int)i);
398 log_error("IMAGE RGBA FP read, write %s test failed\n", update_packed_pitch_name);
399 }
400 break;
401 }
402
403 if (err) break;
404 }
405
406 free_mtdata(d);
407 free(rgba8_inptr);
408 free(rgba16_inptr);
409 free(rgbafp_inptr);
410 free(rgba8_outptr);
411 free(rgba16_outptr);
412 free(rgbafp_outptr);
413
414 if (!err)
415 log_info("IMAGE read, write test passed\n");
416
417 return err;
418 }
419
420
421
422