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 "testBase.h"
17
18 #if defined(__APPLE__)
19 #include <OpenGL/glu.h>
20 #else
21 #include <GL/glu.h>
22 #include <CL/cl_gl.h>
23 #endif
24
25 #if defined(__linux__)
gluCheckExtension(const GLubyte * extension,const GLubyte * extensions)26 GLboolean gluCheckExtension(const GLubyte *extension, const GLubyte *extensions)
27 {
28 const GLubyte *start;
29 GLubyte *where, *terminator;
30
31 /* Extension names should not have spaces. */
32 where = (GLubyte *)strchr((const char *)extension, ' ');
33 if (where || *extension == '\0') return 0;
34 /* It takes a bit of care to be fool-proof about parsing the
35 OpenGL extensions string. Don't be fooled by sub-strings,
36 etc. */
37 start = extensions;
38 for (;;)
39 {
40 where = (GLubyte *)strstr((const char *)start, (const char *)extension);
41 if (!where) break;
42 terminator = where + strlen((const char *)extension);
43 if (where == start || *(where - 1) == ' ')
44 if (*terminator == ' ' || *terminator == '\0') return 1;
45 start = terminator;
46 }
47 return 0;
48 }
49 #endif
50
51
52 // This is defined in the write common code:
53 extern int test_cl_image_write(cl_context context, cl_command_queue queue,
54 GLenum target, cl_mem clImage, size_t width,
55 size_t height, size_t depth,
56 cl_image_format *outFormat,
57 ExplicitType *outType, void **outSourceBuffer,
58 MTdata d, bool supports_half);
59
60 extern int test_cl_image_read(cl_context context, cl_command_queue queue,
61 GLenum gl_target, cl_mem image, size_t width,
62 size_t height, size_t depth, size_t sampleNum,
63 cl_image_format *outFormat, ExplicitType *outType,
64 void **outResultBuffer);
65
66 extern int supportsHalf(cl_context context, bool *supports_half);
67
test_attach_renderbuffer_read_image(cl_context context,cl_command_queue queue,GLenum glTarget,GLuint glRenderbuffer,size_t imageWidth,size_t imageHeight,cl_image_format * outFormat,ExplicitType * outType,void ** outResultBuffer)68 static int test_attach_renderbuffer_read_image(
69 cl_context context, cl_command_queue queue, GLenum glTarget,
70 GLuint glRenderbuffer, size_t imageWidth, size_t imageHeight,
71 cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer)
72 {
73 int error;
74
75 // Create a CL image from the supplied GL renderbuffer
76 cl_mem image = (*clCreateFromGLRenderbuffer_ptr)(context, CL_MEM_READ_ONLY,
77 glRenderbuffer, &error);
78 if (error != CL_SUCCESS)
79 {
80 print_error(error, "Unable to create CL image from GL renderbuffer");
81 return error;
82 }
83
84 return test_cl_image_read(context, queue, glTarget, image, imageWidth,
85 imageHeight, 1, 1, outFormat, outType,
86 outResultBuffer);
87 }
88
test_renderbuffer_read_image(cl_context context,cl_command_queue queue,GLsizei width,GLsizei height,GLenum attachment,GLenum format,GLenum internalFormat,GLenum glType,ExplicitType type,MTdata d)89 int test_renderbuffer_read_image(cl_context context, cl_command_queue queue,
90 GLsizei width, GLsizei height,
91 GLenum attachment, GLenum format,
92 GLenum internalFormat, GLenum glType,
93 ExplicitType type, MTdata d)
94 {
95 int error;
96
97 if (type == kHalf)
98 if (DetectFloatToHalfRoundingMode(queue)) return 1;
99
100 // Create the GL renderbuffer
101 glFramebufferWrapper glFramebuffer;
102 glRenderbufferWrapper glRenderbuffer;
103 void *tmp = CreateGLRenderbuffer(
104 width, height, attachment, format, internalFormat, glType, type,
105 &glFramebuffer, &glRenderbuffer, &error, d, true);
106 BufferOwningPtr<char> inputBuffer(tmp);
107 if (error != 0)
108 {
109 if ((format == GL_RGBA_INTEGER_EXT)
110 && (!CheckGLIntegerExtensionSupport()))
111 {
112 log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. "
113 "Skipping test.\n");
114 return 0;
115 }
116 else
117 {
118 return error;
119 }
120 }
121
122 // Run and get the results
123 cl_image_format clFormat;
124 ExplicitType actualType;
125 char *outBuffer;
126 error = test_attach_renderbuffer_read_image(
127 context, queue, attachment, glRenderbuffer, width, height, &clFormat,
128 &actualType, (void **)&outBuffer);
129 if (error != 0) return error;
130 BufferOwningPtr<char> actualResults(outBuffer);
131
132 log_info("- Read [%4d x %4d] : GL renderbuffer : %s : %s : %s => CL Image "
133 ": %s : %s \n",
134 width, height, GetGLFormatName(format),
135 GetGLFormatName(internalFormat), GetGLTypeName(glType),
136 GetChannelOrderName(clFormat.image_channel_order),
137 GetChannelTypeName(clFormat.image_channel_data_type));
138
139 #ifdef DEBUG
140 log_info("- start read GL data -- \n");
141 DumpGLBuffer(glType, width, height, actualResults);
142 log_info("- end read GL data -- \n");
143 #endif
144
145 // We have to convert our input buffer to the returned type, so we can
146 // validate.
147 BufferOwningPtr<char> convertedInput(convert_to_expected(
148 inputBuffer, width * height, type, actualType,
149 get_channel_order_channel_count(clFormat.image_channel_order)));
150
151 #ifdef DEBUG
152 log_info("- start input data -- \n");
153 DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height,
154 convertedInput);
155 log_info("- end input data -- \n");
156 #endif
157
158 #ifdef DEBUG
159 log_info("- start converted data -- \n");
160 DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height,
161 actualResults);
162 log_info("- end converted data -- \n");
163 #endif
164
165 // Now we validate
166 int valid = 0;
167 if (convertedInput)
168 {
169 if (actualType == kFloat)
170 valid = validate_float_results(
171 convertedInput, actualResults, width, height, 1,
172 get_channel_order_channel_count(clFormat.image_channel_order));
173 else
174 valid = validate_integer_results(
175 convertedInput, actualResults, width, height, 1,
176 get_explicit_type_size(actualType));
177 }
178
179 return valid;
180 }
181
test_renderbuffer_read(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)182 int test_renderbuffer_read(cl_device_id device, cl_context context,
183 cl_command_queue queue, int numElements)
184 {
185 GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
186
187 struct
188 {
189 GLenum internal;
190 GLenum format;
191 GLenum datatype;
192 ExplicitType type;
193
194 } formats[] = {
195 { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
196 { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
197 { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
198 { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
199
200 // Renderbuffers with integer formats do not seem to work reliably across
201 // platforms/implementations. Disabling this in version 1.0 of CL
202 // conformance tests.
203
204 #ifdef TEST_INTEGER_FORMATS
205
206 { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
207 { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
208 { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
209 { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
210 { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
211 { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
212 #endif
213 { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
214 { GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
215 };
216
217 size_t fmtIdx, attIdx;
218 int error = 0;
219 #ifdef DEBUG
220 size_t iter = 1;
221 #else
222 size_t iter = 6;
223 #endif
224 RandomSeed seed(gRandomSeed);
225
226 // Check if images are supported
227 if (checkForImageSupport(device))
228 {
229 log_info("Device does not support images. Skipping test.\n");
230 return 0;
231 }
232
233 if (!gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object",
234 glGetString(GL_EXTENSIONS)))
235 {
236 log_info("Renderbuffers are not supported by this OpenGL "
237 "implementation; skipping test\n");
238 return 0;
239 }
240
241 // Loop through a set of GL formats, testing a set of sizes against each one
242 for (fmtIdx = 0; fmtIdx < sizeof(formats) / sizeof(formats[0]); fmtIdx++)
243 {
244 for (attIdx = 0; attIdx < sizeof(attachments) / sizeof(attachments[0]);
245 attIdx++)
246 {
247 size_t i;
248
249 log_info("Testing renderbuffer read for %s : %s : %s : %s\n",
250 GetGLAttachmentName(attachments[attIdx]),
251 GetGLFormatName(formats[fmtIdx].internal),
252 GetGLBaseFormatName(formats[fmtIdx].format),
253 GetGLTypeName(formats[fmtIdx].datatype));
254
255 for (i = 0; i < iter; i++)
256 {
257 GLsizei width = random_in_range(16, 512, seed);
258 GLsizei height = random_in_range(16, 512, seed);
259 #ifdef DEBUG
260 width = height = 4;
261 #endif
262
263 if (test_renderbuffer_read_image(
264 context, queue, width, height, attachments[attIdx],
265 formats[fmtIdx].format, formats[fmtIdx].internal,
266 formats[fmtIdx].datatype, formats[fmtIdx].type, seed))
267
268 {
269 log_error("ERROR: Renderbuffer read test failed for %s : "
270 "%s : %s : %s\n\n",
271 GetGLAttachmentName(attachments[attIdx]),
272 GetGLFormatName(formats[fmtIdx].internal),
273 GetGLBaseFormatName(formats[fmtIdx].format),
274 GetGLTypeName(formats[fmtIdx].datatype));
275
276 error++;
277 break; // Skip other sizes for this combination
278 }
279 }
280 if (i == iter)
281 {
282 log_info("passed: Renderbuffer read test passed for %s : %s : "
283 "%s : %s\n\n",
284 GetGLAttachmentName(attachments[attIdx]),
285 GetGLFormatName(formats[fmtIdx].internal),
286 GetGLBaseFormatName(formats[fmtIdx].format),
287 GetGLTypeName(formats[fmtIdx].datatype));
288 }
289 }
290 }
291
292 return error;
293 }
294
295
296 #pragma mark -------------------- Write tests -------------------------
297
test_attach_renderbuffer_write_to_image(cl_context context,cl_command_queue queue,GLenum glTarget,GLuint glRenderbuffer,size_t imageWidth,size_t imageHeight,cl_image_format * outFormat,ExplicitType * outType,MTdata d,void ** outSourceBuffer,bool supports_half)298 int test_attach_renderbuffer_write_to_image(
299 cl_context context, cl_command_queue queue, GLenum glTarget,
300 GLuint glRenderbuffer, size_t imageWidth, size_t imageHeight,
301 cl_image_format *outFormat, ExplicitType *outType, MTdata d,
302 void **outSourceBuffer, bool supports_half)
303 {
304 int error;
305
306 // Create a CL image from the supplied GL renderbuffer
307 clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)(
308 context, CL_MEM_WRITE_ONLY, glRenderbuffer, &error);
309 if (error != CL_SUCCESS)
310 {
311 print_error(error, "Unable to create CL image from GL renderbuffer");
312 return error;
313 }
314
315 return test_cl_image_write(context, queue, glTarget, image, imageWidth,
316 imageHeight, 1, outFormat, outType,
317 outSourceBuffer, d, supports_half);
318 }
319
test_renderbuffer_image_write(cl_context context,cl_command_queue queue,GLsizei width,GLsizei height,GLenum attachment,GLenum format,GLenum internalFormat,GLenum glType,ExplicitType type,MTdata d)320 int test_renderbuffer_image_write(cl_context context, cl_command_queue queue,
321 GLsizei width, GLsizei height,
322 GLenum attachment, GLenum format,
323 GLenum internalFormat, GLenum glType,
324 ExplicitType type, MTdata d)
325 {
326 int error;
327
328 if (type == kHalf)
329 if (DetectFloatToHalfRoundingMode(queue)) return 1;
330
331 // Create the GL renderbuffer
332 glFramebufferWrapper glFramebuffer;
333 glRenderbufferWrapper glRenderbuffer;
334 CreateGLRenderbuffer(width, height, attachment, format, internalFormat,
335 glType, type, &glFramebuffer, &glRenderbuffer, &error,
336 d, false);
337 if (error != 0)
338 {
339 if ((format == GL_RGBA_INTEGER_EXT)
340 && (!CheckGLIntegerExtensionSupport()))
341 {
342 log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. "
343 "Skipping test.\n");
344 return 0;
345 }
346 else
347 {
348 return error;
349 }
350 }
351
352 // Run and get the results
353 cl_image_format clFormat;
354 ExplicitType sourceType;
355 ExplicitType validationType;
356 void *outSourceBuffer;
357
358 bool supports_half = false;
359 error = supportsHalf(context, &supports_half);
360 if (error != 0) return error;
361
362 error = test_attach_renderbuffer_write_to_image(
363 context, queue, attachment, glRenderbuffer, width, height, &clFormat,
364 &sourceType, d, (void **)&outSourceBuffer, supports_half);
365 if (error != 0 || ((sourceType == kHalf) && !supports_half)) return error;
366
367 // If actual source type was half, convert to float for validation.
368 if (sourceType == kHalf)
369 validationType = kFloat;
370 else
371 validationType = sourceType;
372
373 BufferOwningPtr<char> validationSource(convert_to_expected(
374 outSourceBuffer, width * height, sourceType, validationType,
375 get_channel_order_channel_count(clFormat.image_channel_order)));
376
377 log_info("- Write [%4d x %4d] : GL Renderbuffer : %s : %s : %s => CL Image "
378 ": %s : %s \n",
379 width, height, GetGLFormatName(format),
380 GetGLFormatName(internalFormat), GetGLTypeName(glType),
381 GetChannelOrderName(clFormat.image_channel_order),
382 GetChannelTypeName(clFormat.image_channel_data_type));
383
384 // Now read the results from the GL renderbuffer
385 BufferOwningPtr<char> resultData(
386 ReadGLRenderbuffer(glFramebuffer, glRenderbuffer, attachment, format,
387 internalFormat, glType, type, width, height));
388
389 #ifdef DEBUG
390 log_info("- start result data -- \n");
391 DumpGLBuffer(glType, width, height, resultData);
392 log_info("- end result data -- \n");
393 #endif
394
395 // We have to convert our input buffer to the returned type, so we can
396 // validate.
397 BufferOwningPtr<char> convertedData(convert_to_expected(
398 resultData, width * height, type, validationType,
399 get_channel_order_channel_count(clFormat.image_channel_order)));
400
401 #ifdef DEBUG
402 log_info("- start input data -- \n");
403 DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height,
404 validationSource);
405 log_info("- end input data -- \n");
406 #endif
407
408 #ifdef DEBUG
409 log_info("- start converted data -- \n");
410 DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height,
411 convertedData);
412 log_info("- end converted data -- \n");
413 #endif
414
415 // Now we validate
416 int valid = 0;
417 if (convertedData)
418 {
419 if (sourceType == kFloat || sourceType == kHalf)
420 valid = validate_float_results(
421 validationSource, convertedData, width, height, 1,
422 get_channel_order_channel_count(clFormat.image_channel_order));
423 else
424 valid = validate_integer_results(validationSource, convertedData,
425 width, height, 1,
426 get_explicit_type_size(type));
427 }
428
429 return valid;
430 }
431
test_renderbuffer_write(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)432 int test_renderbuffer_write(cl_device_id device, cl_context context,
433 cl_command_queue queue, int numElements)
434 {
435 GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
436
437 struct
438 {
439 GLenum internal;
440 GLenum format;
441 GLenum datatype;
442 ExplicitType type;
443
444 } formats[] = {
445 { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
446 { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
447 { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
448 { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
449
450 // Renderbuffers with integer formats do not seem to work reliably across
451 // platforms/implementations. Disabling this in version 1.0 of CL
452 // conformance tests.
453
454 #ifdef TEST_INTEGER_FORMATS
455
456 { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
457 { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
458 { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
459 { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
460 { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
461 { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
462 #endif
463 { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
464 { GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
465 };
466
467 size_t fmtIdx, attIdx;
468 int error = 0;
469 size_t iter = 6;
470 #ifdef DEBUG
471 iter = 1;
472 #endif
473 RandomSeed seed(gRandomSeed);
474
475 // Check if images are supported
476 if (checkForImageSupport(device))
477 {
478 log_info("Device does not support images. Skipping test.\n");
479 return 0;
480 }
481
482 if (!gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object",
483 glGetString(GL_EXTENSIONS)))
484 {
485 log_info("Renderbuffers are not supported by this OpenGL "
486 "implementation; skipping test\n");
487 return 0;
488 }
489
490 // Loop through a set of GL formats, testing a set of sizes against each one
491 for (fmtIdx = 0; fmtIdx < sizeof(formats) / sizeof(formats[0]); fmtIdx++)
492 {
493 for (attIdx = 0; attIdx < sizeof(attachments) / sizeof(attachments[0]);
494 attIdx++)
495 {
496 log_info("Testing Renderbuffer write test for %s : %s : %s : %s\n",
497 GetGLAttachmentName(attachments[attIdx]),
498 GetGLFormatName(formats[fmtIdx].internal),
499 GetGLBaseFormatName(formats[fmtIdx].format),
500 GetGLTypeName(formats[fmtIdx].datatype));
501
502 size_t i;
503 for (i = 0; i < iter; i++)
504 {
505 GLsizei width = random_in_range(16, 512, seed);
506 GLsizei height = random_in_range(16, 512, seed);
507 #ifdef DEBUG
508 width = height = 4;
509 #endif
510
511 if (test_renderbuffer_image_write(
512 context, queue, width, height, attachments[attIdx],
513 formats[fmtIdx].format, formats[fmtIdx].internal,
514 formats[fmtIdx].datatype, formats[fmtIdx].type, seed))
515 {
516 log_error("ERROR: Renderbuffer write test failed for %s : "
517 "%s : %s : %s\n\n",
518 GetGLAttachmentName(attachments[attIdx]),
519 GetGLFormatName(formats[fmtIdx].internal),
520 GetGLBaseFormatName(formats[fmtIdx].format),
521 GetGLTypeName(formats[fmtIdx].datatype));
522
523 error++;
524 break; // Skip other sizes for this combination
525 }
526 }
527 if (i == iter)
528 {
529 log_info("passed: Renderbuffer write test passed for %s : %s : "
530 "%s : %s\n\n",
531 GetGLAttachmentName(attachments[attIdx]),
532 GetGLFormatName(formats[fmtIdx].internal),
533 GetGLBaseFormatName(formats[fmtIdx].format),
534 GetGLTypeName(formats[fmtIdx].datatype));
535 }
536 }
537 }
538
539 return error;
540 }
541