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