| // |
| // Copyright (c) 2017 The Khronos Group Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| #include "testBase.h" |
| #include "common.h" |
| |
| #if defined( __APPLE__ ) |
| #include <OpenGL/glu.h> |
| #else |
| #include <GL/glu.h> |
| #include <CL/cl_gl.h> |
| #endif |
| |
| extern int supportsHalf(cl_context context, bool* supports_half); |
| |
| static int test_image_info( cl_context context, cl_command_queue queue, |
| GLenum glTarget, GLuint glTexture, size_t imageWidth, size_t imageHeight, |
| size_t imageDepth, cl_image_format *outFormat, ExplicitType *outType, |
| void **outResultBuffer ) |
| { |
| clMemWrapper streams[ 2 ]; |
| |
| int error; |
| |
| // Create a CL image from the supplied GL texture |
| streams[ 0 ] = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY, |
| glTarget, 0, glTexture, &error ); |
| if( error != CL_SUCCESS ) |
| { |
| print_error( error, "Unable to create CL image from GL texture" ); |
| GLint fmt; |
| glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt ); |
| log_error( " Supplied GL texture was format %s\n", GetGLFormatName( fmt ) ); |
| return error; |
| } |
| |
| // Determine data type and format that CL came up with |
| error = clGetImageInfo( streams[ 0 ], CL_IMAGE_FORMAT, |
| sizeof( cl_image_format ), outFormat, NULL ); |
| test_error( error, "Unable to get CL image format" ); |
| |
| cl_gl_object_type object_type; |
| switch (glTarget) { |
| case GL_TEXTURE_1D: |
| object_type = CL_GL_OBJECT_TEXTURE1D; |
| break; |
| case GL_TEXTURE_BUFFER: |
| object_type = CL_GL_OBJECT_TEXTURE_BUFFER; |
| break; |
| case GL_TEXTURE_1D_ARRAY: |
| object_type = CL_GL_OBJECT_TEXTURE1D_ARRAY; |
| break; |
| case GL_TEXTURE_2D: |
| case GL_TEXTURE_RECTANGLE_EXT: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: |
| object_type = CL_GL_OBJECT_TEXTURE2D; |
| break; |
| case GL_TEXTURE_2D_ARRAY: |
| object_type = CL_GL_OBJECT_TEXTURE2D_ARRAY; |
| break; |
| case GL_TEXTURE_3D: |
| object_type = CL_GL_OBJECT_TEXTURE3D; |
| break; |
| default: |
| log_error("Unsupported texture target."); |
| return 1; |
| } |
| |
| return CheckGLObjectInfo(streams[0], object_type, glTexture, glTarget, 0); |
| } |
| |
| static int test_image_format_get_info( |
| cl_context context, cl_command_queue queue, |
| size_t width, size_t height, size_t depth, |
| GLenum target, struct format* fmt, MTdata data) |
| { |
| int error = 0; |
| |
| // If we're testing a half float format, then we need to determine the |
| // rounding mode of this machine. Punt if we fail to do so. |
| |
| if( fmt->type == kHalf ) |
| { |
| if( DetectFloatToHalfRoundingMode(queue) ) |
| return 0; |
| bool supports_half = false; |
| error = supportsHalf(context, &supports_half); |
| if( error != 0 ) |
| return error; |
| if (!supports_half) return 0; |
| } |
| |
| size_t w = width, h = height, d = depth; |
| |
| // Unpack the format and use it, along with the target, to create an |
| // appropriate GL texture. |
| |
| GLenum gl_fmt = fmt->formattype; |
| GLenum gl_internal_fmt = fmt->internal; |
| GLenum gl_type = fmt->datatype; |
| ExplicitType type = fmt->type; |
| |
| glTextureWrapper texture; |
| glBufferWrapper glbuf; |
| |
| // If we're testing a half float format, then we need to determine the |
| // rounding mode of this machine. Punt if we fail to do so. |
| |
| if( fmt->type == kHalf ) |
| if( DetectFloatToHalfRoundingMode(queue) ) |
| return 1; |
| |
| // Use the correct texture creation function depending on the target, and |
| // adjust width, height, depth as appropriate so subsequent size calculations |
| // succeed. |
| |
| switch (target) { |
| case GL_TEXTURE_1D: |
| h = 1; d = 1; |
| CreateGLTexture1D( width, target, gl_fmt, |
| gl_internal_fmt, gl_type, type, &texture, &error, false, data ); |
| break; |
| case GL_TEXTURE_BUFFER: |
| h = 1; d = 1; |
| CreateGLTextureBuffer( width, target, gl_fmt, |
| gl_internal_fmt, gl_type, type, &texture, &glbuf, &error, false, data ); |
| break; |
| case GL_TEXTURE_1D_ARRAY: |
| d = 1; |
| CreateGLTexture1DArray( width, height, target, gl_fmt, |
| gl_internal_fmt, gl_type, type, &texture, &error, false, data ); |
| break; |
| case GL_TEXTURE_RECTANGLE_EXT: |
| case GL_TEXTURE_2D: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: |
| d = 1; |
| CreateGLTexture2D( width, height, target, gl_fmt, |
| gl_internal_fmt, gl_type, type, &texture, &error, false, data ); |
| break; |
| case GL_TEXTURE_2D_ARRAY: |
| CreateGLTexture2DArray( width, height, depth, target, gl_fmt, |
| gl_internal_fmt, gl_type, type, &texture, &error, false, data ); |
| break; |
| case GL_TEXTURE_3D: |
| d = 1; |
| CreateGLTexture3D( width, height, depth, target, gl_fmt, |
| gl_internal_fmt, gl_type, type, &texture, &error, data, false ); |
| break; |
| default: |
| log_error("Unsupported texture target.\n"); |
| return 1; |
| } |
| |
| if ( error == -2 ) { |
| log_info("OpenGL texture couldn't be created, because a texture is too big. Skipping test.\n"); |
| return 0; |
| } |
| |
| if ( error != 0 ) { |
| if ((gl_fmt == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())) { |
| log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. " |
| "Skipping test.\n"); |
| return 0; |
| } else { |
| return error; |
| } |
| } |
| |
| cl_image_format clFormat; |
| ExplicitType actualType; |
| char *outBuffer; |
| |
| // Perform the info check: |
| return test_image_info( context, queue, target, texture, w, h, d, &clFormat, |
| &actualType, (void **)&outBuffer ); |
| } |
| |
| int test_images_get_info_common( cl_device_id device, cl_context context, |
| cl_command_queue queue, struct format* formats, size_t nformats, |
| GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes ) |
| { |
| int error = 0; |
| RandomSeed seed(gRandomSeed); |
| |
| // First, ensure this device supports images. |
| |
| if (checkForImageSupport(device)) { |
| log_info("Device does not support images. Skipping test.\n"); |
| return 0; |
| } |
| |
| size_t fidx, tidx, sidx; |
| |
| // Test each format on every target, every size. |
| |
| for ( fidx = 0; fidx < nformats; fidx++ ) { |
| for ( tidx = 0; tidx < ntargets; tidx++ ) { |
| |
| if ( formats[ fidx ].datatype == GL_UNSIGNED_INT_2_10_10_10_REV ) |
| { |
| // Check if the RGB 101010 format is supported |
| if ( is_rgb_101010_supported( context, targets[ tidx ] ) == 0 ) |
| break; // skip |
| } |
| |
| log_info( "Testing image info for GL format %s : %s : %s : %s\n", |
| GetGLTargetName( targets[ tidx ] ), |
| GetGLFormatName( formats[ fidx ].internal ), |
| GetGLBaseFormatName( formats[ fidx ].formattype ), |
| GetGLTypeName( formats[ fidx ].datatype ) ); |
| |
| for ( sidx = 0; sidx < nsizes; sidx++ ) { |
| |
| // Test this format + size: |
| |
| if ( test_image_format_get_info(context, queue, |
| sizes[sidx].width, sizes[sidx].height, sizes[sidx].depth, |
| targets[tidx], &formats[fidx], seed) ) |
| { |
| // We land here in the event of test failure. |
| |
| log_error( "ERROR: Image info test failed for %s : %s : %s : %s\n\n", |
| GetGLTargetName( targets[ tidx ] ), |
| GetGLFormatName( formats[ fidx ].internal ), |
| GetGLBaseFormatName( formats[ fidx ].formattype ), |
| GetGLTypeName( formats[ fidx ].datatype ) ); |
| error++; |
| |
| // Skip the other sizes for this format. |
| |
| break; |
| } |
| } |
| } |
| } |
| |
| return error; |
| } |