xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/gl/test_renderbuffer.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
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