Initial open source release of OpenCL 2.2 CTS.

This commit is contained in:
Kedar Patil
2017-05-16 18:25:37 +05:30
parent 6911ba5116
commit 2821bf1323
1035 changed files with 343518 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
set (MODULE_NAME GLES)
set (${MODULE_NAME}_SOURCES
main.cpp
test_buffers.cpp
test_images_2D.cpp
test_images_3D.cpp
test_renderbuffer.cpp
test_images_2D_info.cpp
test_images_3D_info.cpp
test_renderbuffer_info.cpp
test_fence_sync.cpp
helpers.cpp
setup_egl.cpp
../../test_common/gles/helpers.cpp
../../test_common/harness/genericThread.cpp
../../test_common/harness/errorHelpers.c
../../test_common/harness/threadTesting.c
../../test_common/harness/testHarness.c
../../test_common/harness/kernelHelpers.c
../../test_common/harness/mt19937.c
../../test_common/harness/conversions.c
../../test_common/harness/msvc9.c
../../test_common/harness/parseParameters.cpp
)
if(ANDROID)
list(APPEND CLConform_LIBRARIES GLESv2)
elseif(WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLES3")
list(APPEND CLConform_LIBRARIES libEGL libGLESv2 )
endif(ANDROID)
include(../CMakeCommon.txt)

View File

@@ -0,0 +1,481 @@
//
// 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 "gl_headers.h"
const char *get_kernel_suffix( cl_image_format *format )
{
switch( format->image_channel_data_type )
{
case CL_UNORM_INT8:
case CL_UNORM_INT16:
case CL_SNORM_INT8:
case CL_SNORM_INT16:
case CL_FLOAT:
return "f";
case CL_HALF_FLOAT:
return "h";
case CL_SIGNED_INT8:
case CL_SIGNED_INT16:
case CL_SIGNED_INT32:
return "i";
case CL_UNSIGNED_INT8:
case CL_UNSIGNED_INT16:
case CL_UNSIGNED_INT32:
return "ui";
default:
return "";
}
}
ExplicitType get_read_kernel_type( cl_image_format *format )
{
switch( format->image_channel_data_type )
{
case CL_UNORM_INT8:
case CL_UNORM_INT16:
case CL_SNORM_INT8:
case CL_SNORM_INT16:
case CL_FLOAT:
return kFloat;
case CL_HALF_FLOAT:
return kHalf;
case CL_SIGNED_INT8:
case CL_SIGNED_INT16:
case CL_SIGNED_INT32:
return kInt;
case CL_UNSIGNED_INT8:
case CL_UNSIGNED_INT16:
case CL_UNSIGNED_INT32:
return kUInt;
default:
return kInt;
}
}
ExplicitType get_write_kernel_type( cl_image_format *format )
{
switch( format->image_channel_data_type )
{
case CL_UNORM_INT8:
return kFloat;
case CL_UNORM_INT16:
return kFloat;
case CL_SNORM_INT8:
return kFloat;
case CL_SNORM_INT16:
return kFloat;
case CL_HALF_FLOAT:
return kHalf;
case CL_FLOAT:
return kFloat;
case CL_SIGNED_INT8:
return kChar;
case CL_SIGNED_INT16:
return kShort;
case CL_SIGNED_INT32:
return kInt;
case CL_UNSIGNED_INT8:
return kUChar;
case CL_UNSIGNED_INT16:
return kUShort;
case CL_UNSIGNED_INT32:
return kUInt;
default:
return kInt;
}
}
const char* get_write_conversion( cl_image_format *format, ExplicitType type )
{
switch( format->image_channel_data_type )
{
case CL_UNORM_INT8:
case CL_UNORM_INT16:
case CL_SNORM_INT8:
case CL_SNORM_INT16:
case CL_FLOAT:
if(type != kFloat) return "convert_float4";
break;
case CL_HALF_FLOAT:
break;
case CL_SIGNED_INT8:
case CL_SIGNED_INT16:
case CL_SIGNED_INT32:
if(type != kInt) return "convert_int4";
break;
case CL_UNSIGNED_INT8:
case CL_UNSIGNED_INT16:
case CL_UNSIGNED_INT32:
if(type != kUInt) return "convert_uint4";
break;
default:
return "";
}
return "";
}
// The only three input types to this function are kInt, kUInt and kFloat, due to the way we set up our tests
// The output types, though, are pretty much anything valid for GL to receive
#define DOWNSCALE_INTEGER_CASE( enum, type, bitShift ) \
case enum: \
{ \
cl_##type *dst = new cl_##type[ numPixels * 4 ]; \
for( size_t i = 0; i < numPixels * 4; i++ ) \
dst[ i ] = src[ i ]; \
return (char *)dst; \
}
#define UPSCALE_FLOAT_CASE( enum, type, typeMax ) \
case enum: \
{ \
cl_##type *dst = new cl_##type[ numPixels * 4 ]; \
for( size_t i = 0; i < numPixels * 4; i++ ) \
dst[ i ] = (cl_##type)( src[ i ] * typeMax ); \
return (char *)dst; \
}
char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType )
{
#ifdef GLES_DEBUG
log_info( "- Converting from input type '%s' to output type '%s'\n",
get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
#endif
if( inType == outType )
{
char *outData = new char[ numPixels * 4 * get_explicit_type_size(outType) ] ; // sizeof( cl_int ) ];
memcpy( outData, inputBuffer, numPixels * 4 * get_explicit_type_size(inType) );
return outData;
}
else if( inType == kChar )
{
cl_char *src = (cl_char *)inputBuffer;
switch( outType )
{
case kInt:
{
cl_int *outData = new cl_int[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_int)((src[ i ]));
}
return (char *)outData;
}
case kFloat:
{
// If we're converting to float, then CL decided that we should be normalized
cl_float *outData = new cl_float[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_float)src[ i ] / 127.0f;
}
return (char *)outData;
}
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
else if( inType == kUChar )
{
cl_uchar *src = (cl_uchar *)inputBuffer;
switch( outType )
{
case kUInt:
{
cl_uint *outData = new cl_uint[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_uint)((src[ i ]));
}
return (char *)outData;
}
case kFloat:
{
// If we're converting to float, then CL decided that we should be normalized
cl_float *outData = new cl_float[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_float)(src[ i ]) / 256.0f;
}
return (char *)outData;
}
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
else if( inType == kShort )
{
cl_short *src = (cl_short *)inputBuffer;
switch( outType )
{
case kInt:
{
cl_int *outData = new cl_int[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_int)((src[ i ]));
}
return (char *)outData;
}
case kFloat:
{
// If we're converting to float, then CL decided that we should be normalized
cl_float *outData = new cl_float[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_float)src[ i ] / 32768.0f;
}
return (char *)outData;
}
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
else if( inType == kUShort )
{
cl_ushort *src = (cl_ushort *)inputBuffer;
switch( outType )
{
case kUInt:
{
cl_uint *outData = new cl_uint[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_uint)((src[ i ]));
}
return (char *)outData;
}
case kFloat:
{
// If we're converting to float, then CL decided that we should be normalized
cl_float *outData = new cl_float[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_float)(src[ i ]) / 65535.0f;
}
return (char *)outData;
}
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
else if( inType == kInt )
{
cl_int *src = (cl_int *)inputBuffer;
switch( outType )
{
DOWNSCALE_INTEGER_CASE( kShort, short, 16 )
DOWNSCALE_INTEGER_CASE( kChar, char, 24 )
case kFloat:
{
// If we're converting to float, then CL decided that we should be normalized
cl_float *outData = new cl_float[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_float)fmaxf( (float)src[ i ] / 2147483647.f, -1.f );
}
return (char *)outData;
}
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
else if( inType == kUInt )
{
cl_uint *src = (cl_uint *)inputBuffer;
switch( outType )
{
DOWNSCALE_INTEGER_CASE( kUShort, ushort, 16 )
DOWNSCALE_INTEGER_CASE( kUChar, uchar, 24 )
case kFloat:
{
// If we're converting to float, then CL decided that we should be normalized
cl_float *outData = new cl_float[ numPixels * 4 ];
for( size_t i = 0; i < numPixels * 4; i++ )
{
outData[ i ] = (cl_float)src[ i ] / 4294967295.f;
}
return (char *)outData;
}
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
else
{
cl_float *src = (cl_float *)inputBuffer;
switch( outType )
{
UPSCALE_FLOAT_CASE( kChar, char, 127.f )
UPSCALE_FLOAT_CASE( kUChar, uchar, 255.f )
UPSCALE_FLOAT_CASE( kShort, short, 32767.f )
UPSCALE_FLOAT_CASE( kUShort, ushort, 65535.f )
UPSCALE_FLOAT_CASE( kInt, int, 2147483647.f )
UPSCALE_FLOAT_CASE( kUInt, uint, 4294967295.f )
default:
log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
return NULL;
}
}
return NULL;
}
int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t typeSize )
{
return validate_integer_results( expectedResults, actualResults, width, height, 0, typeSize );
}
int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t typeSize )
{
char *expected = (char *)expectedResults;
char *actual = (char *)actualResults;
for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
{
for( size_t y = 0; y < height; y++ )
{
for( size_t x = 0; x < width; x++ )
{
if( memcmp( expected, actual, typeSize * 4 ) != 0 )
{
char scratch[ 1024 ];
if( depth == 0 )
log_error( "ERROR: Data sample %d,%d did not validate!\n", (int)x, (int)y );
else
log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)z );
log_error( "\tExpected: %s\n", GetDataVectorString( expected, typeSize, 4, scratch ) );
log_error( "\t Actual: %s\n", GetDataVectorString( actual, typeSize, 4, scratch ) );
return -1;
}
expected += typeSize * 4;
actual += typeSize * 4;
}
}
}
return 0;
}
int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height )
{
return validate_float_results( expectedResults, actualResults, width, height, 0 );
}
int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth )
{
cl_float *expected = (cl_float *)expectedResults;
cl_float *actual = (cl_float *)actualResults;
for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
{
for( size_t y = 0; y < height; y++ )
{
for( size_t x = 0; x < width; x++ )
{
float err = 0.f;
for( size_t i = 0; i < 4; i++ )
{
float error = fabsf( expected[ i ] - actual[ i ] );
if( error > err )
err = error;
}
if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float
{
if( depth == 0 )
log_error( "ERROR: Data sample %d,%d did not validate!\n", (int)x, (int)y );
else
log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)z );
log_error( "\tExpected: %f %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( "\t : %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( "\t Actual: %f %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
log_error( "\t : %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
return -1;
}
expected += 4;
actual += 4;
}
}
}
return 0;
}
int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name,
GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level)
{
cl_gl_object_type object_type;
GLuint object_name;
GLenum texture_target;
GLint mipmap_level;
int error;
error = (*clGetGLObjectInfo_ptr)(mem, &object_type, &object_name);
test_error( error, "clGetGLObjectInfo failed");
if (object_type != expected_cl_gl_type) {
log_error("clGetGLObjectInfo did not return expected object type: expected %d, got %d.\n", expected_cl_gl_type, object_type);
return -1;
}
if (object_name != expected_gl_name) {
log_error("clGetGLObjectInfo did not return expected object name: expected %d, got %d.\n", expected_gl_name, object_name);
return -1;
}
if (object_type == CL_GL_OBJECT_TEXTURE2D || object_type == CL_GL_OBJECT_TEXTURE3D) {
error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_TEXTURE_TARGET, sizeof(texture_target), &texture_target, NULL);
test_error( error, "clGetGLTextureInfo for CL_GL_TEXTURE_TARGET failed");
if (texture_target != expected_cl_gl_texture_target) {
log_error("clGetGLTextureInfo did not return expected texture target: expected %d, got %d.\n", expected_cl_gl_texture_target, texture_target);
return -1;
}
error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_MIPMAP_LEVEL, sizeof(mipmap_level), &mipmap_level, NULL);
test_error( error, "clGetGLTextureInfo for CL_GL_MIPMAP_LEVEL failed");
if (mipmap_level != expected_cl_gl_mipmap_level) {
log_error("clGetGLTextureInfo did not return expected mipmap level: expected %d, got %d.\n", expected_cl_gl_mipmap_level, mipmap_level);
return -1;
}
}
return 0;
}
bool CheckGLIntegerExtensionSupport()
{
// Get the OpenGL version and supported extensions
const GLubyte *glVersion = glGetString(GL_VERSION);
const GLubyte *glExtensionList = glGetString(GL_EXTENSIONS);
// Check if the OpenGL vrsion is 3.0 or grater or GL_EXT_texture_integer is supported
return (((glVersion[0] - '0') >= 3) || (strstr((const char*)glExtensionList, "GL_EXT_texture_integer")));
}

View File

@@ -0,0 +1,402 @@
//
// 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 <stdio.h>
#include <stdlib.h>
#if !defined(_WIN32)
#include <stdbool.h>
#endif
#include <math.h>
#include <string.h>
#if !defined (__APPLE__)
#include <CL/cl.h>
#endif
#include "procs.h"
#include "../../test_common/gles/setup.h"
#include "../../test_common/harness/testHarness.h"
#if !defined(_WIN32)
#include <unistd.h>
#endif
static cl_context sCurrentContext = NULL;
#define TEST_FN_REDIRECT( fn ) redirect_##fn
#define TEST_FN_REDIRECTOR( fn ) \
int redirect_##fn(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) \
{ \
int error; \
clCommandQueueWrapper realQueue = clCreateCommandQueue( sCurrentContext, device, 0, &error ); \
test_error( error, "Unable to create command queue" ); \
return fn( device, sCurrentContext, realQueue, numElements ); \
}
TEST_FN_REDIRECTOR( test_buffers )
TEST_FN_REDIRECTOR( test_buffers_getinfo )
TEST_FN_REDIRECTOR( test_images_read )
TEST_FN_REDIRECTOR( test_images_2D_getinfo )
TEST_FN_REDIRECTOR( test_images_read_cube )
TEST_FN_REDIRECTOR( test_images_cube_getinfo )
TEST_FN_REDIRECTOR( test_images_read_3D )
TEST_FN_REDIRECTOR( test_images_3D_getinfo )
TEST_FN_REDIRECTOR( test_images_write )
TEST_FN_REDIRECTOR( test_images_write_cube )
TEST_FN_REDIRECTOR( test_renderbuffer_read )
TEST_FN_REDIRECTOR( test_renderbuffer_write )
TEST_FN_REDIRECTOR( test_renderbuffer_getinfo )
#ifndef GL_ES_VERSION_2_0
TEST_FN_REDIRECTOR( test_fence_sync )
#endif
basefn basefn_list[] = {
TEST_FN_REDIRECT( test_buffers ),
TEST_FN_REDIRECT( test_buffers_getinfo ),
TEST_FN_REDIRECT( test_images_read ),
TEST_FN_REDIRECT( test_images_2D_getinfo ),
TEST_FN_REDIRECT( test_images_read_cube ),
TEST_FN_REDIRECT( test_images_cube_getinfo ),
TEST_FN_REDIRECT( test_images_read_3D ),
TEST_FN_REDIRECT( test_images_3D_getinfo ),
TEST_FN_REDIRECT( test_images_write ),
TEST_FN_REDIRECT( test_images_write_cube ),
TEST_FN_REDIRECT( test_renderbuffer_read ),
TEST_FN_REDIRECT( test_renderbuffer_write ),
TEST_FN_REDIRECT( test_renderbuffer_getinfo )
};
#ifndef GL_ES_VERSION_2_0
basefn basefn_list32[] = {
TEST_FN_REDIRECT( test_fence_sync )
};
#endif
const char *basefn_names[] = {
"buffers",
"buffers_getinfo",
"images_read",
"images_2D_getinfo",
"images_read_cube",
"images_cube_getinfo",
"images_read_3D",
"images_3D_getinfo",
"images_write",
"images_write_cube",
"renderbuffer_read",
"renderbuffer_write",
"renderbuffer_getinfo",
"all"
};
const char *basefn_names32[] = {
"fence_sync",
"all"
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0]) - 1) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int num_fns32 = sizeof(basefn_names32) / sizeof(char *);
int main(int argc, const char *argv[])
{
int error = 0;
cl_platform_id platform_id = NULL;
/* To keep it simple, use a static allocation of 32 argv pointers.
argc is not expected to go beyond 32 */
const char* argv_tmp[32] = {0};
int argc_tmp = 0;
test_start();
cl_device_type requestedDeviceType = CL_DEVICE_TYPE_DEFAULT;
for(int z = 1; z < argc; ++z)
{//for
if(strcmp( argv[ z ], "-list" ) == 0 )
{
log_info( "Available 2.x tests:\n" );
for( int i = 0; i < num_fns - 1; i++ )
log_info( "\t%s\n", basefn_names[ i ] );
log_info( "Available 3.2 tests:\n" );
for( int i = 0; i < num_fns32 - 1; i++ )
log_info( "\t%s\n", basefn_names32[ i ] );
log_info( "Note: Any 3.2 test names must follow 2.1 test names on the command line." );
log_info( "Use environment variables to specify desired device." );
test_finish();
return 0;
}
/* support requested device type */
if(!strcmp(argv[z], "CL_DEVICE_TYPE_GPU"))
{
printf("Requested device type is CL_DEVICE_TYPE_GPU\n");
requestedDeviceType = CL_DEVICE_TYPE_GPU;
}
else
if(!strcmp(argv[z], "CL_DEVICE_TYPE_CPU"))
{
printf("Requested device type is CL_DEVICE_TYPE_CPU\n");
log_info("Invalid CL device type. GL tests can only run on a GPU device.\n");
test_finish();
return 0;
}
}//for
// Check to see if any 2.x or 3.2 test names were specified on the command line.
unsigned first_32_testname = 0;
for (int j=1; (j<argc) && (!first_32_testname); ++j)
for (int i=0;i<num_fns32-1;++i)
if (strcmp(basefn_names32[i],argv[j])==0) {
first_32_testname = j;
break;
}
// Create the environment for the test.
GLEnvironment *glEnv = GLEnvironment::Instance();
// Check if any devices of the requested type support CL/GL interop.
int supported = glEnv->SupportsCLGLInterop( requestedDeviceType );
if( supported == 0 ) {
log_info("Test not run because GL-CL interop is not supported for any devices of the requested type.\n");
test_finish();
error = 0;
goto cleanup;
} else if ( supported == -1 ) {
log_error("Failed to determine if CL-GL interop is supported.\n");
test_finish();
error = -1;
goto cleanup;
}
// OpenGL tests for non-3.2 ////////////////////////////////////////////////////////
if ((argc == 1) || (first_32_testname != 1)) {
// At least one device supports CL-GL interop, so init the test.
if( glEnv->Init( &argc, (char **)argv, CL_FALSE ) ) {
log_error("Failed to initialize the GL environment for this test.\n");
test_finish();
error = -1;
goto cleanup;
}
// Create a context to use and then grab a device (or devices) from it
sCurrentContext = glEnv->CreateCLContext();
if( sCurrentContext == NULL )
{
log_error( "ERROR: Unable to obtain CL context from GL\n" );
test_finish();
error = -1;
goto cleanup;
}
size_t numDevices = 0;
cl_device_id deviceIDs[ 16 ];
error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices);
if( error != CL_SUCCESS )
{
print_error( error, "Unable to get device count from context" );
test_finish();
error = -1;
goto cleanup;
}
numDevices /= sizeof(cl_device_id);
if (numDevices < 1) {
log_error("No devices found.\n");
test_finish();
error = -1;
goto cleanup;
}
error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, sizeof( deviceIDs ), deviceIDs, NULL);
if( error != CL_SUCCESS ) {
print_error( error, "Unable to get device list from context" );
test_finish();
error = -1;
goto cleanup;
}
// Execute tests.
int argc_ = (first_32_testname) ? first_32_testname : argc;
for( size_t i = 0; i < numDevices; i++ ) {
log_info( "\nTesting OpenGL 2.x\n" );
if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) {
test_finish();
error = -1;
goto cleanup;
}
error = clGetDeviceInfo(deviceIDs[ i ],
CL_DEVICE_PLATFORM,
sizeof(platform_id),
&platform_id,
NULL);
if(error)
{
goto cleanup;
}
error = init_clgl_ext(platform_id);
if (error < 0)
{
goto cleanup;
}
/* parseAndCallCommandLineTests considers every command line argument
as a test name. This results in the test failing because of considering
args such as 'CL_DEVICE_TYPE_GPU' as test names unless
the actual test name happens to be the first argument.
Instead of changing the behaviour of parseAndCallCommandLineTests
modify the arguments passed to it so as to not affect other tests.
*/
int w = 1;
argc_tmp= argc_;
for(int k = 1; k < argc; k++)
{
if( (strcmp(argv[k], "full") == 0) ||
(strcmp(argv[k], "CL_DEVICE_TYPE_CPU") == 0) ||
(strcmp(argv[k], "CL_DEVICE_TYPE_GPU") == 0))
{
argc_tmp--;
continue;
}
else
{
argv_tmp[w++] = argv[k];
}
}
// Note: don't use the entire harness, because we have a different way of obtaining the device (via the context)
error = parseAndCallCommandLineTests( argc_tmp, argv_tmp, deviceIDs[ i ], num_fns, basefn_list, basefn_names, true, 0, 1024 );
if( error != 0 )
break;
}
// Clean-up.
// We move this to a common cleanup step to make sure that things will be released properly before the test exit
goto cleanup;
// clReleaseContext( sCurrentContext );
// delete glEnv;
}
// OpenGL 3.2 tests. ////////////////////////////////////////////////////////
if ((argc==1) || first_32_testname) {
// At least one device supports CL-GL interop, so init the test.
if( glEnv->Init( &argc, (char **)argv, CL_TRUE ) ) {
log_error("Failed to initialize the GL environment for this test.\n");
test_finish();
error = -1;
goto cleanup;
}
// Create a context to use and then grab a device (or devices) from it
sCurrentContext = glEnv->CreateCLContext();
if( sCurrentContext == NULL ) {
log_error( "ERROR: Unable to obtain CL context from GL\n" );
test_finish();
error = -1;
goto cleanup;
}
size_t numDevices = 0;
cl_device_id deviceIDs[ 16 ];
error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices);
if( error != CL_SUCCESS ) {
print_error( error, "Unable to get device count from context" );
test_finish();
error = -1;
goto cleanup;
}
numDevices /= sizeof(cl_device_id);
if (numDevices < 1) {
log_error("No devices found.\n");
test_finish();
error = -1;
goto cleanup;
}
error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, sizeof( deviceIDs ), deviceIDs, NULL);
if( error != CL_SUCCESS ) {
print_error( error, "Unable to get device list from context" );
test_finish();
error = -1;
goto cleanup;
}
int argc_ = (first_32_testname) ? 1 + (argc - first_32_testname) : argc;
const char** argv_ = (first_32_testname) ? &argv[first_32_testname-1] : argv;
// Execute the tests.
for( size_t i = 0; i < numDevices; i++ ) {
log_info( "\nTesting OpenGL 3.2\n" );
if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) {
test_finish();
error = -1;
goto cleanup;
}
#ifdef GL_ES_VERSION_2_0
log_info("Cannot test OpenGL 3.2! This test was built for OpenGL ES 2.0\n");
test_finish();
error = -1;
goto cleanup;
#else
// Note: don't use the entire harness, because we have a different way of obtaining the device (via the context)
error = parseAndCallCommandLineTests( argc_, argv_, deviceIDs[ i ], num_fns32, basefn_list32, basefn_names32, true, 0, 1024 );
if( error != 0 )
break;
#endif
}
// Converge on a common cleanup to make sure that things will be released properly before the test exit
goto cleanup;
}
// cleanup CL/GL/EGL environment properly when the test exit.
// This change does not affect any functionality of the test
// Intentional falling through
cleanup:
// Cleanup EGL
glEnv->terminate_egl_display();
// Always make sure that OpenCL context is released properly when the test exit
if(sCurrentContext)
{
clReleaseContext( sCurrentContext );
sCurrentContext = NULL;
}
delete glEnv;
return error;
}

View File

@@ -0,0 +1,35 @@
//
// 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 "../../test_common/harness/mt19937.h"
extern int test_buffers( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_buffers_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements );
extern int test_images_create( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_images_read( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_images_2D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements );
extern int test_images_read_cube( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_images_cube_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements );
extern int test_images_read_3D( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_images_3D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements );
extern int test_images_write( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_images_write_cube( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_renderbuffer_read( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_renderbuffer_write( cl_device_id device, cl_context context, cl_command_queue queue, int num_elements );
extern int test_renderbuffer_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements );
extern int test_fence_sync( cl_device_id device, cl_context context, cl_command_queue queue, int numElements );

View File

@@ -0,0 +1,215 @@
//
// 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 "setup.h"
#include "testBase.h"
#include "../../test_common/harness/errorHelpers.h"
#include <assert.h>
#include <CL/cl.h>
#include <CL/cl_ext.h>
#define EGLERR() \
assert(eglGetError() == EGL_SUCCESS); \
#define MAX_DEVICES 10
class EGLGLEnvironment : public GLEnvironment
{
private:
cl_platform_id _platform;
EGLDisplay _display;
EGLContext _context;
EGLSurface _surface;
public:
EGLGLEnvironment()
:_platform(NULL)
,_display(EGL_NO_DISPLAY)
,_context(NULL)
,_surface(EGL_NO_SURFACE)
{
}
virtual int Init( int *argc, char **argv, int use_opengl_32 )
{
EGLint ConfigAttribs[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
// EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
EGL_NONE
};
static const EGLint ContextAttribs[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLint conf_list[] = {
EGL_WIDTH, 512,
EGL_HEIGHT, 512,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
EGL_NONE};
EGLint majorVersion;
EGLint minorVersion;
EGLConfig config;
EGLint numConfigs;
EGLERR();
_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLERR();
eglInitialize(_display, &majorVersion, &minorVersion);
EGLERR();
eglBindAPI(EGL_OPENGL_ES_API);
EGLERR();
eglChooseConfig(_display, ConfigAttribs, &config, 1, &numConfigs);
EGLERR();
_context = eglCreateContext(_display, config, NULL, ContextAttribs);
EGLERR();
_surface = eglCreatePbufferSurface(_display, config, conf_list);
EGLERR();
eglMakeCurrent(_display, _surface, _surface, _context);
EGLERR();
return 0;
}
virtual cl_context CreateCLContext( void )
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, (cl_context_properties) _platform,
CL_GL_CONTEXT_KHR, (cl_context_properties) _context,
CL_EGL_DISPLAY_KHR, (cl_context_properties) _display,
0
};
cl_device_id devices[MAX_DEVICES];
size_t dev_size;
cl_int status;
status = clGetGLContextInfoKHR(properties,
CL_DEVICES_FOR_GL_CONTEXT_KHR,
sizeof(devices),
devices,
&dev_size);
if (status != CL_SUCCESS) {
print_error(status, "clGetGLContextInfoKHR failed");
return NULL;
}
dev_size /= sizeof(cl_device_id);
log_info("GL _context supports %d compute devices\n", dev_size);
status = clGetGLContextInfoKHR(properties,
CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
sizeof(devices),
devices,
&dev_size);
if (status != CL_SUCCESS) {
print_error(status, "clGetGLContextInfoKHR failed");
return NULL;
}
if (!dev_size)
{
log_info("GL _context current device is not a CL device.\n");
return NULL;
}
return clCreateContext(properties, 1, &devices[0], NULL, NULL, &status);
}
virtual int SupportsCLGLInterop( cl_device_type device_type )
{
cl_device_id devices[MAX_DEVICES];
cl_uint num_of_devices;
int interop_devices = 0;
int error;
error = clGetPlatformIDs(1, &_platform, NULL);
if (error) {
print_error(error, "clGetPlatformIDs failed");
return -1;
}
error = clGetDeviceIDs(_platform, device_type, MAX_DEVICES, devices, &num_of_devices);
if (error) {
print_error(error, "clGetDeviceIDs failed");
return -1;
}
// Check all devices, search for one that supports cl_khr_gl_sharing
char extensions[8192];
for (int i=0; i<(int)num_of_devices; i++) {
error = clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS, sizeof(extensions), extensions, NULL);
if (error) {
print_error(error, "clGetDeviceInfo failed");
return -1;
}
if (strstr(extensions, "cl_khr_gl_sharing ") == NULL) {
log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
} else {
log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
interop_devices++;
}
}
return interop_devices > 0;
}
// Change to cleanup egl environment properly when the test exit.
// This change does not affect any functionality of the test it self
virtual void terminate_egl_display()
{
if(_display != EGL_NO_DISPLAY)
{
eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
EGLERR();
eglDestroyContext(_display, _context);
EGLERR();
_context = EGL_NO_CONTEXT;
eglDestroySurface(_display, _surface);
EGLERR();
_surface = EGL_NO_SURFACE;
eglTerminate(_display);
EGLERR();
_display = EGL_NO_DISPLAY;
}
}
virtual ~EGLGLEnvironment()
{
}
};
GLEnvironment * GLEnvironment::Instance( void )
{
return new EGLGLEnvironment();
}

View File

@@ -0,0 +1,71 @@
//
// 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.
//
#ifndef _testBase_h
#define _testBase_h
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#if !defined(_WIN32)
#include <stdbool.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#if !defined (__APPLE__)
#include <CL/cl.h>
#include "../../test_common/gles/gl_headers.h"
#include <CL/cl_gl.h>
#else
#include "../../test_common/gl/gl_headers.h"
#endif
#include "../../test_common/harness/errorHelpers.h"
#include "../../test_common/harness/kernelHelpers.h"
#include "../../test_common/harness/threadTesting.h"
#include "../../test_common/harness/typeWrappers.h"
#include "../../test_common/harness/conversions.h"
#include "../../test_common/harness/mt19937.h"
#ifdef GL_ES_VERSION_2_0
#include "../../test_common/gles/helpers.h"
#else
#include "../../test_common/gl/helpers.h"
#endif
extern const char *get_kernel_suffix( cl_image_format *format );
extern const char *get_write_conversion( cl_image_format *format, ExplicitType type);
extern ExplicitType get_read_kernel_type( cl_image_format *format );
extern ExplicitType get_write_kernel_type( cl_image_format *format );
extern char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType );
extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t typeSize );
extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t typeSize );
extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height );
extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth );
extern int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name,
GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level);
extern bool CheckGLIntegerExtensionSupport();
#endif // _testBase_h

View File

@@ -0,0 +1,402 @@
//
// 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 "testHarness.h"
#include "../../test_common/harness/conversions.h"
#include "../../test_common/harness/typeWrappers.h"
#include <math.h>
#include <float.h>
#if !defined (__APPLE__)
#include <CL/cl_gl.h>
#endif
extern "C" { extern cl_uint gRandomSeed; };
static const char *bufferKernelPattern =
"__kernel void sample_test( __global %s%s *source, __global %s%s *clDest, __global %s%s *glDest )\n"
"{\n"
" int tid = get_global_id(0);\n"
" clDest[ tid ] = source[ tid ] + (%s%s)(1);\n"
" glDest[ tid ] = source[ tid ] + (%s%s)(2);\n"
"}\n";
#define TYPE_CASE( enum, type, range, offset ) \
case enum: \
{ \
cl_##type *ptr = (cl_##type *)outData; \
for( i = 0; i < count; i++ ) \
ptr[ i ] = (cl_##type)( ( genrand_int32(d) & range ) - offset ); \
break; \
}
void gen_input_data( ExplicitType type, size_t count, MTdata d, void *outData )
{
size_t i;
switch( type )
{
case kBool:
{
bool *boolPtr = (bool *)outData;
for( i = 0; i < count; i++ )
{
boolPtr[i] = ( genrand_int32(d) & 1 ) ? true : false;
}
break;
}
TYPE_CASE( kChar, char, 250, 127 )
TYPE_CASE( kUChar, uchar, 250, 0 )
TYPE_CASE( kShort, short, 65530, 32767 )
TYPE_CASE( kUShort, ushort, 65530, 0 )
TYPE_CASE( kInt, int, 0x0fffffff, 0x70000000 )
TYPE_CASE( kUInt, uint, 0x0fffffff, 0 )
case kLong:
{
cl_long *longPtr = (cl_long *)outData;
for( i = 0; i < count; i++ )
{
longPtr[i] = (cl_long)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 );
}
break;
}
case kULong:
{
cl_ulong *ulongPtr = (cl_ulong *)outData;
for( i = 0; i < count; i++ )
{
ulongPtr[i] = (cl_ulong)genrand_int32(d) | ( (cl_ulong)genrand_int32(d) << 32 );
}
break;
}
case kFloat:
{
cl_float *floatPtr = (float *)outData;
for( i = 0; i < count; i++ )
floatPtr[i] = get_random_float( -100000.f, 100000.f, d );
break;
}
default:
log_error( "ERROR: Invalid type passed in to generate_random_data!\n" );
break;
}
}
#define INC_CASE( enum, type ) \
case enum: \
{ \
cl_##type *src = (cl_##type *)inData; \
cl_##type *dst = (cl_##type *)outData; \
*dst = *src + 1; \
break; \
}
void get_incremented_value( void *inData, void *outData, ExplicitType type )
{
switch( type )
{
INC_CASE( kChar, char )
INC_CASE( kUChar, uchar )
INC_CASE( kShort, short )
INC_CASE( kUShort, ushort )
INC_CASE( kInt, int )
INC_CASE( kUInt, uint )
INC_CASE( kLong, long )
INC_CASE( kULong, ulong )
INC_CASE( kFloat, float )
default:
break;
}
}
int test_buffer_kernel(cl_context context, cl_command_queue queue, ExplicitType vecType, size_t vecSize, int numElements, int validate_only, MTdata d)
{
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper streams[ 3 ];
size_t dataSize = numElements * 16 * sizeof(cl_long);
#if !(defined(_WIN32) && defined(_MSC_VER))
cl_long inData[numElements * 16], outDataCL[numElements * 16], outDataGL[ numElements * 16 ];
#else
cl_long* inData = (cl_long*)_malloca(dataSize);
cl_long* outDataCL = (cl_long*)_malloca(dataSize);
cl_long* outDataGL = (cl_long*)_malloca(dataSize);
#endif
glBufferWrapper inGLBuffer, outGLBuffer;
int i;
size_t bufferSize;
int error;
size_t threads[1], localThreads[1];
char kernelSource[10240];
char *programPtr;
char sizeName[4];
/* Create the source */
if( vecSize == 1 )
sizeName[ 0 ] = 0;
else
sprintf( sizeName, "%d", (int)vecSize );
sprintf( kernelSource, bufferKernelPattern, get_explicit_type_name( vecType ), sizeName,
get_explicit_type_name( vecType ), sizeName,
get_explicit_type_name( vecType ), sizeName,
get_explicit_type_name( vecType ), sizeName,
get_explicit_type_name( vecType ), sizeName );
/* Create kernels */
programPtr = kernelSource;
if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) )
{
return -1;
}
bufferSize = numElements * vecSize * get_explicit_type_size( vecType );
/* Generate some almost-random input data */
gen_input_data( vecType, vecSize * numElements, d, inData );
memset( outDataCL, 0, dataSize );
memset( outDataGL, 0, dataSize );
/* Generate some GL buffers to go against */
glGenBuffers( 1, &inGLBuffer );
glGenBuffers( 1, &outGLBuffer );
glBindBuffer( GL_ARRAY_BUFFER, inGLBuffer );
glBufferData( GL_ARRAY_BUFFER, bufferSize, inData, GL_STATIC_DRAW );
// Note: we need to bind the output buffer, even though we don't care about its values yet,
// because CL needs it to get the buffer size
glBindBuffer( GL_ARRAY_BUFFER, outGLBuffer );
glBufferData( GL_ARRAY_BUFFER, bufferSize, outDataGL, GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glFlush();
/* Generate some streams. The first and last ones are GL, middle one just vanilla CL */
streams[ 0 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_ONLY, inGLBuffer, &error );
test_error( error, "Unable to create input GL buffer" );
streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, bufferSize, NULL, &error );
test_error( error, "Unable to create output CL buffer" );
streams[ 2 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_WRITE_ONLY, outGLBuffer, &error );
test_error( error, "Unable to create output GL buffer" );
/* Validate the info */
if (validate_only) {
int result = (CheckGLObjectInfo(streams[0], CL_GL_OBJECT_BUFFER, (GLuint)inGLBuffer, (GLenum)0, 0) |
CheckGLObjectInfo(streams[2], CL_GL_OBJECT_BUFFER, (GLuint)outGLBuffer, (GLenum)0, 0) );
for(i=0;i<3;i++)
{
clReleaseMemObject(streams[i]);
streams[i] = NULL;
}
glDeleteBuffers(1, &inGLBuffer); inGLBuffer = 0;
glDeleteBuffers(1, &outGLBuffer); outGLBuffer = 0;
return result;
}
/* Assign streams and execute */
for( int i = 0; i < 3; i++ )
{
error = clSetKernelArg( kernel, i, sizeof( streams[ i ] ), &streams[ i ] );
test_error( error, "Unable to set kernel arguments" );
}
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 2 ], 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
/* Run the kernel */
threads[0] = numElements;
error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] );
test_error( error, "Unable to get work group size to use" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL );
test_error( error, "Unable to execute test kernel" );
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL );
test_error(error, "clEnqueueReleaseGLObjects failed");
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 2 ], 0, NULL, NULL );
test_error(error, "clEnqueueReleaseGLObjects failed");
// Get the results from both CL and GL and make sure everything looks correct
error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, bufferSize, outDataCL, 0, NULL, NULL );
test_error( error, "Unable to read output CL array!" );
glBindBuffer( GL_ARRAY_BUFFER, outGLBuffer );
void *glMem = glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize, GL_MAP_READ_BIT );
memcpy( outDataGL, glMem, bufferSize );
glUnmapBuffer( GL_ARRAY_BUFFER );
char *inP = (char *)inData, *glP = (char *)outDataGL, *clP = (char *)outDataCL;
error = 0;
for( size_t i = 0; i < numElements * vecSize; i++ )
{
cl_long expectedCLValue, expectedGLValue;
get_incremented_value( inP, &expectedCLValue, vecType );
get_incremented_value( &expectedCLValue, &expectedGLValue, vecType );
if( memcmp( clP, &expectedCLValue, get_explicit_type_size( vecType ) ) != 0 )
{
char scratch[ 64 ];
log_error( "ERROR: Data sample %d from the CL output did not validate!\n", (int)i );
log_error( "\t Input: %s\n", GetDataVectorString( inP, get_explicit_type_size( vecType ), 1, scratch ) );
log_error( "\tExpected: %s\n", GetDataVectorString( &expectedCLValue, get_explicit_type_size( vecType ), 1, scratch ) );
log_error( "\t Actual: %s\n", GetDataVectorString( clP, get_explicit_type_size( vecType ), 1, scratch ) );
error = -1;
}
if( memcmp( glP, &expectedGLValue, get_explicit_type_size( vecType ) ) != 0 )
{
char scratch[ 64 ];
log_error( "ERROR: Data sample %d from the GL output did not validate!\n", (int)i );
log_error( "\t Input: %s\n", GetDataVectorString( inP, get_explicit_type_size( vecType ), 1, scratch ) );
log_error( "\tExpected: %s\n", GetDataVectorString( &expectedGLValue, get_explicit_type_size( vecType ), 1, scratch ) );
log_error( "\t Actual: %s\n", GetDataVectorString( glP, get_explicit_type_size( vecType ), 1, scratch ) );
error = -1;
}
if( error )
return error;
inP += get_explicit_type_size( vecType );
glP += get_explicit_type_size( vecType );
clP += get_explicit_type_size( vecType );
}
for(i=0;i<3;i++)
{
clReleaseMemObject(streams[i]);
streams[i] = NULL;
}
glDeleteBuffers(1, &inGLBuffer); inGLBuffer = 0;
glDeleteBuffers(1, &outGLBuffer); outGLBuffer = 0;
#if (defined(_WIN32) && defined(_MSC_VER))
_freea(inData);
_freea(outDataCL);
_freea(outDataGL);
#endif
return 0;
}
int test_buffers( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kNumExplicitTypes };
unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 };
unsigned int index, typeIndex;
int retVal = 0;
RandomSeed seed(gRandomSeed);
/* 64-bit ints optional in embedded profile */
int hasLong = 1;
int isEmbedded = 0;
char profile[1024] = "";
retVal = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL);
if (retVal)
{
print_error(retVal, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" );
return -1;
}
isEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE");
if(isEmbedded && !is_extension_available(device, "cles_khr_int64"))
{
hasLong = 0;
}
for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ )
{
for( index = 0; vecSizes[ index ] != 0; index++ )
{
/* Fix bug 7124 */
if ( (vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong) && !hasLong )
continue;
// Test!
if( test_buffer_kernel( context, queue, vecType[ typeIndex ], vecSizes[ index ], numElements, 0, seed) != 0 )
{
char sizeNames[][ 4 ] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" };
log_error( " Buffer test %s%s FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), sizeNames[ vecSizes[ index ] ] );
retVal++;
}
}
}
return retVal;
}
int test_buffers_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kNumExplicitTypes };
unsigned int vecSizes[] = { 1, 2, 4, 8, 16, 0 };
unsigned int index, typeIndex;
int retVal = 0;
RandomSeed seed( gRandomSeed );
/* 64-bit ints optional in embedded profile */
int hasLong = 1;
int isEmbedded = 0;
char profile[1024] = "";
retVal = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL);
if (retVal)
{
print_error(retVal, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" );
return -1;
}
isEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE");
if(isEmbedded && !is_extension_available(device, "cles_khr_int64"))
{
hasLong = 0;
}
for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ )
{
for( index = 0; vecSizes[ index ] != 0; index++ )
{
/* Fix bug 7124 */
if ( (vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong) && !hasLong )
continue;
// Test!
if( test_buffer_kernel( context, queue, vecType[ typeIndex ], vecSizes[ index ], numElements, 1, seed ) != 0 )
{
char sizeNames[][ 4 ] = { "", "", "2", "", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" };
log_error( " Buffer test %s%s FAILED\n", get_explicit_type_name( vecType[ typeIndex ] ), sizeNames[ vecSizes[ index ] ] );
retVal++;
}
}
}
return retVal;
}

View File

@@ -0,0 +1,664 @@
//
// 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 "gl_headers.h"
#include "testBase.h"
#include "setup.h"
#include "../../test_common/harness/genericThread.h"
#ifndef GLsync
// For OpenGL before 3.2, we look for the ARB_sync extension and try to use that
#if !defined(_WIN32)
#include <inttypes.h>
#endif // !_WIN32
typedef int64_t GLint64;
typedef uint64_t GLuint64;
typedef struct __GLsync *GLsync;
typedef GLsync (*glFenceSyncPtr)(GLenum condition,GLbitfield flags);
glFenceSyncPtr glFenceSyncFunc;
typedef bool (*glIsSyncPtr)(GLsync sync);
glIsSyncPtr glIsSyncFunc;
typedef void (*glDeleteSyncPtr)(GLsync sync);
glDeleteSyncPtr glDeleteSyncFunc;
typedef GLenum (*glClientWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout);
glClientWaitSyncPtr glClientWaitSyncFunc;
typedef void (*glWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout);
glWaitSyncPtr glWaitSyncFunc;
typedef void (*glGetInteger64vPtr)(GLenum pname, GLint64 *params);
glGetInteger64vPtr glGetInteger64vFunc;
typedef void (*glGetSyncivPtr)(GLsync sync,GLenum pname,GLsizei bufSize,GLsizei *length,
GLint *values);
glGetSyncivPtr glGetSyncivFunc;
#define CHK_GL_ERR() printf("%s\n", gluErrorString(glGetError()))
static void InitSyncFns( void )
{
glFenceSyncFunc = (glFenceSyncPtr)glutGetProcAddress( "glFenceSync" );
glIsSyncFunc = (glIsSyncPtr)glutGetProcAddress( "glIsSync" );
glDeleteSyncFunc = (glDeleteSyncPtr)glutGetProcAddress( "glDeleteSync" );
glClientWaitSyncFunc = (glClientWaitSyncPtr)glutGetProcAddress( "glClientWaitSync" );
glWaitSyncFunc = (glWaitSyncPtr)glutGetProcAddress( "glWaitSync" );
glGetInteger64vFunc = (glGetInteger64vPtr)glutGetProcAddress( "glGetInteger64v" );
glGetSyncivFunc = (glGetSyncivPtr)glutGetProcAddress( "glGetSynciv" );
}
#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
#define GL_OBJECT_TYPE 0x9112
#define GL_SYNC_CONDITION 0x9113
#define GL_SYNC_STATUS 0x9114
#define GL_SYNC_FLAGS 0x9115
#define GL_SYNC_FENCE 0x9116
#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
#define GL_UNSIGNALED 0x9118
#define GL_SIGNALED 0x9119
#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
#define GL_ALREADY_SIGNALED 0x911A
#define GL_TIMEOUT_EXPIRED 0x911B
#define GL_CONDITION_SATISFIED 0x911C
#define GL_WAIT_FAILED 0x911D
#define USING_ARB_sync 1
#endif
typedef cl_event (CL_API_CALL *clCreateEventFromGLsyncKHR_fn)( cl_context context, GLsync sync, cl_int *errCode_ret) ;
clCreateEventFromGLsyncKHR_fn clCreateEventFromGLsyncKHR_ptr;
static const char *updateBuffersKernel[] = {
"__kernel void update( __global float4 * vertices, __global float4 *colors, int horizWrap, int rowIdx )\n"
"{\n"
" size_t tid = get_global_id(0);\n"
"\n"
" size_t xVal = ( tid & ( horizWrap - 1 ) );\n"
" vertices[ tid * 2 + 0 ] = (float4)( xVal, rowIdx*16.f, 0.0f, 1.f );\n"
" vertices[ tid * 2 + 1 ] = (float4)( xVal, rowIdx*16.f + 4.0f, 0.0f, 1.f );\n"
"\n"
" int rowV = rowIdx + 1;\n"
" colors[ tid * 2 + 0 ] = (float4)( ( rowV & 1 ) / 255.f, ( ( rowV & 2 ) >> 1 ) / 255.f, ( ( rowV & 4 ) >> 2 ) / 255.f, 1.f );\n"
" //colors[ tid * 2 + 0 ] = (float4)( (float)xVal/(float)horizWrap, 1.0f, 1.0f, 1.0f );\n"
" colors[ tid * 2 + 1 ] = colors[ tid * 2 + 0 ];\n"
"}\n" };
//Passthrough VertexShader
static const char vertexshader[] =
"uniform mat4 projMatrix;\n"
"attribute vec4 inPosition;\n"
"attribute vec4 inColor;\n"
"varying vec4 outColor;\n"
"void main (void) {\n"
" gl_Position = projMatrix*inPosition;\n"
" outColor = inColor;\n"
"}\n";
//Passthrough FragmentShader
static const char fragmentshader[] =
"varying vec4 outColor;\n"
"void main (void) {\n"
" gl_FragColor = outColor;\n"
"}\n";
GLuint createShaderProgram(GLint *posLoc, GLint *colLoc)
{
GLint logLength, status;
GLuint program = glCreateProgram();
GLuint vpShader;
char* vpstr = (char*)malloc(sizeof(vertexshader));
strcpy(vpstr, vertexshader);
vpShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vpShader, 1, (const GLchar **)&vpstr, NULL);
glCompileShader(vpShader);
glGetShaderiv(vpShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*) malloc(logLength);
glGetShaderInfoLog(vpShader, logLength, &logLength, log);
log_info("Vtx Shader compile log:\n%s", log);
free(log);
}
free(vpstr);
vpstr = NULL;
glGetShaderiv(vpShader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
log_error("Failed to compile vtx shader:\n");
return 0;
}
glAttachShader(program, vpShader);
GLuint fpShader;
char* fpstr = (char*)malloc(strlen(fragmentshader));
strcpy(fpstr, fragmentshader);
fpShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fpShader, 1, (const GLchar **)&fpstr, NULL);
glCompileShader(fpShader);
free(fpstr);
fpstr = NULL;
glGetShaderiv(fpShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetShaderInfoLog(fpShader, logLength, &logLength, log);
log_info("Frag Shader compile log:\n%s", log);
free(log);
}
glAttachShader(program, fpShader);
glGetShaderiv(fpShader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
log_error("Failed to compile frag shader:\n\n");
return 0;
}
glLinkProgram(program);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(program, logLength, &logLength, log);
log_info("Program link log:\n%s", log);
free(log);
}
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == 0)
{
log_error("Failed to link program\n");
return 0;
}
glValidateProgram(program);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(program, logLength, &logLength, log);
log_info("Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
if (status == 0)
{
log_error("Failed to validate program\n");
return 0;
}
*posLoc = glGetAttribLocation(program, "inPosition");
*colLoc = glGetAttribLocation(program, "inColor");
return program;
}
void destroyShaderProgram(GLuint program)
{
GLuint shaders[2];
GLsizei count;
glUseProgram(0);
glGetAttachedShaders(program, 2, &count, shaders);
int i;
for(i = 0; i < count; i++)
{
glDetachShader(program, shaders[i]);
glDeleteShader(shaders[i]);
}
glDeleteProgram(program);
}
// This function queues up and runs the above CL kernel that writes the vertex data
cl_int run_cl_kernel( cl_kernel kernel, cl_command_queue queue, cl_mem stream0, cl_mem stream1,
cl_int rowIdx, cl_event fenceEvent, size_t numThreads )
{
cl_int error = clSetKernelArg( kernel, 3, sizeof( rowIdx ), &rowIdx );
test_error( error, "Unable to set kernel arguments" );
clEventWrapper acqEvent1, acqEvent2, kernEvent, relEvent1, relEvent2;
int numEvents = ( fenceEvent != NULL ) ? 1 : 0;
cl_event *fence_evt = ( fenceEvent != NULL ) ? &fenceEvent : NULL;
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &stream0, numEvents, fence_evt, &acqEvent1 );
test_error( error, "Unable to acquire GL obejcts");
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &stream1, numEvents, fence_evt, &acqEvent2 );
test_error( error, "Unable to acquire GL obejcts");
cl_event evts[ 2 ] = { acqEvent1, acqEvent2 };
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &numThreads, NULL, 2, evts, &kernEvent );
test_error( error, "Unable to execute test kernel" );
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &stream0, 1, &kernEvent, &relEvent1 );
test_error(error, "clEnqueueReleaseGLObjects failed");
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &stream1, 1, &kernEvent, &relEvent2 );
test_error(error, "clEnqueueReleaseGLObjects failed");
evts[ 0 ] = relEvent1;
evts[ 1 ] = relEvent2;
error = clWaitForEvents( 2, evts );
test_error( error, "Unable to wait for release events" );
return 0;
}
class RunThread : public genericThread
{
public:
cl_kernel mKernel;
cl_command_queue mQueue;
cl_mem mStream0, mStream1;
cl_int mRowIdx;
cl_event mFenceEvent;
size_t mNumThreads;
RunThread( cl_kernel kernel, cl_command_queue queue, cl_mem stream0, cl_mem stream1, size_t numThreads )
: mKernel( kernel ), mQueue( queue ), mStream0( stream0 ), mStream1( stream1 ), mNumThreads( numThreads )
{
}
void SetRunData( cl_int rowIdx, cl_event fenceEvent )
{
mRowIdx = rowIdx;
mFenceEvent = fenceEvent;
}
virtual void * IRun( void )
{
cl_int error = run_cl_kernel( mKernel, mQueue, mStream0, mStream1, mRowIdx, mFenceEvent, mNumThreads );
return (void *)error;
}
};
int test_fence_sync_single( cl_device_id device, cl_context context, cl_command_queue queue, bool separateThreads, GLint rend_vs, GLint read_vs, cl_device_id rend_device )
{
int error;
const int framebufferSize = 512;
cl_platform_id platform_id = NULL;
if( !is_extension_available( device, "cl_khr_gl_event" ) )
{
log_info( "NOTE: cl_khr_gl_event extension not present on this device; skipping fence sync test\n" );
return 0;
}
error = clGetDeviceInfo(device,
CL_DEVICE_PLATFORM,
sizeof(platform_id),
&platform_id,
NULL);
if(error)
{
return error;
}
clCreateEventFromGLsyncKHR_ptr = \
(clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform_id,"clCreateEventFromGLsyncKHR");
if( clCreateEventFromGLsyncKHR_ptr == NULL )
{
log_error( "ERROR: Unable to run fence_sync test (clCreateEventFromGLsyncKHR function not discovered!)\n" );
clCreateEventFromGLsyncKHR_ptr = \
(clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform_id, "clCreateEventFromGLsyncAPPLE");
return -1;
}
#ifdef USING_ARB_sync
char *gl_version_str = (char*)glGetString( GL_VERSION );
float glCoreVersion;
sscanf(gl_version_str, "%f", &glCoreVersion);
if( glCoreVersion < 3.0f )
{
log_info( "OpenGL version %f does not support fence/sync! Skipping test.\n", glCoreVersion );
return 0;
}
#ifdef __APPLE__
CGLContextObj currCtx = CGLGetCurrentContext();
CGLPixelFormatObj pixFmt = CGLGetPixelFormat(currCtx);
GLint val, screen;
CGLGetVirtualScreen(currCtx, &screen);
CGLDescribePixelFormat(pixFmt, screen, kCGLPFAOpenGLProfile, &val);
if(val != kCGLOGLPVersion_3_2_Core)
{
log_error( "OpenGL context was not created with OpenGL version >= 3.0 profile even though platform supports it"
"OpenGL profile %f does not support fence/sync! Skipping test.\n", glCoreVersion );
return -1;
}
#else
// Need platform specific way to query if current GL context was created with 3.x profile
log_error( "ERROR: not implemented\n\n" );
return -1;
#endif
InitSyncFns();
#endif
#ifdef __APPLE__
CGLSetVirtualScreen(CGLGetCurrentContext(), rend_vs);
#else
// Need platform specific way to set device with id rend_vs the current
// rendering target
log_error( "ERROR: not implemented\n\n" );
return -1;
#endif
GLint posLoc, colLoc;
GLuint shaderprogram = createShaderProgram(&posLoc, &colLoc);
if(!shaderprogram)
{
log_error("Failed to create shader program\n");
return -1;
}
float l = 0.0f; float r = framebufferSize;
float b = 0.0f; float t = framebufferSize;
float projMatrix[16] = { 2.0f/(r-l), 0.0f, 0.0f, 0.0f,
0.0f, 2.0f/(t-b), 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f,
-(r+l)/(r-l), -(t+b)/(t-b), 0.0f, 1.0f
};
glUseProgram(shaderprogram);
GLuint projMatLoc = glGetUniformLocation(shaderprogram, "projMatrix");
glUniformMatrix4fv(projMatLoc, 1, 0, projMatrix);
glUseProgram(0);
// Note: the framebuffer is just the target to verify our results against, so we don't
// really care to go through all the possible formats in this case
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
error = CreateGLRenderbufferRaw( framebufferSize, 128, GL_COLOR_ATTACHMENT0_EXT,
GL_RGBA, GL_UNSIGNED_BYTE,
&glFramebuffer, &glRenderbuffer );
if( error != 0 )
return error;
// GLuint vao;
// glGenVertexArrays(1, &vao);
// glBindVertexArray(vao);
glBufferWrapper vtxBuffer, colorBuffer;
glGenBuffers( 1, &vtxBuffer );
glGenBuffers( 1, &colorBuffer );
const int numHorizVertices = ( framebufferSize * 64 ) + 1;
glBindBuffer( GL_ARRAY_BUFFER, vtxBuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * numHorizVertices * 2 * 4, NULL, GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, colorBuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * numHorizVertices * 2 * 4, NULL, GL_STATIC_DRAW );
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper streams[ 2 ];
if( create_single_kernel_helper( context, &program, &kernel, 1, updateBuffersKernel, "update" ) )
return -1;
streams[ 0 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_WRITE, vtxBuffer, &error );
test_error( error, "Unable to create CL buffer from GL vertex buffer" );
streams[ 1 ] = (*clCreateFromGLBuffer_ptr)( context, CL_MEM_READ_WRITE, colorBuffer, &error );
test_error( error, "Unable to create CL buffer from GL color buffer" );
error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( streams[ 1 ] ), &streams[ 1 ] );
test_error( error, "Unable to set kernel arguments" );
cl_int horizWrap = (cl_int)framebufferSize;
error = clSetKernelArg( kernel, 2, sizeof( horizWrap ), &horizWrap );
test_error( error, "Unable to set kernel arguments" );
glViewport( 0, 0, framebufferSize, framebufferSize );
glClearColor( 0, 0, 0, 0 );
glClear( GL_COLOR_BUFFER_BIT );
glClear( GL_DEPTH_BUFFER_BIT );
glDisable( GL_DEPTH_TEST );
glEnable( GL_BLEND );
glBlendFunc( GL_ONE, GL_ONE );
clEventWrapper fenceEvent;
GLsync glFence = 0;
// Do a loop through 8 different horizontal stripes against the framebuffer
RunThread thread( kernel, queue, streams[ 0 ], streams[ 1 ], (size_t)numHorizVertices );
for( int i = 0; i < 8; i++ )
{
// if current rendering device is not the compute device and
// separateThreads == false which means compute is going on same
// thread and we are using implicit synchronization (no GLSync obj used)
// then glFlush by clEnqueueAcquireGLObject is not sufficient ... we need
// to wait for rendering to finish on other device before CL can start
// writing to CL/GL shared mem objects. When separateThreads is true i.e.
// we are using GLSync obj to synchronize then we dont need to call glFinish
// here since CL should wait for rendering on other device before this
// GLSync object to finish before it starts writing to shared mem object.
// Also rend_device == compute_device no need to call glFinish
if(rend_device != device && !separateThreads)
glFinish();
if( separateThreads )
{
thread.SetRunData( (cl_int)i, fenceEvent );
thread.Start();
error = (cl_int)(size_t)thread.Join();
}
else
{
error = run_cl_kernel( kernel, queue, streams[ 0 ], streams[ 1 ], (cl_int)i, fenceEvent, (size_t)numHorizVertices );
}
test_error( error, "Unable to run CL kernel" );
glUseProgram(shaderprogram);
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(colLoc);
glBindBuffer( GL_ARRAY_BUFFER, vtxBuffer );
glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
glBindBuffer( GL_ARRAY_BUFFER, colorBuffer );
glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDrawArrays( GL_TRIANGLE_STRIP, 0, numHorizVertices * 2 );
glDisableVertexAttribArray(posLoc);
glDisableVertexAttribArray(colLoc);
glUseProgram(0);
if( separateThreads )
{
// If we're on the same thread, then we're testing implicit syncing, so we
// don't need the actual fence code
if( fenceEvent != NULL )
{
clReleaseEvent( fenceEvent );
glDeleteSyncFunc( glFence );
}
glFence = glFenceSyncFunc( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
fenceEvent = clCreateEventFromGLsyncKHR_ptr( context, glFence, &error );
test_error( error, "Unable to create CL event from GL fence" );
// in case of explicit synchronization, we just wait for the sync object to complete
// in clEnqueueAcquireGLObject but we dont flush. Its application's responsibility
// to flush on the context on which glSync is created
glFlush();
}
}
if( glFence != 0 )
// Don't need the final release for fenceEvent, because the wrapper will take care of that
glDeleteSyncFunc( glFence );
#ifdef __APPLE__
CGLSetVirtualScreen(CGLGetCurrentContext(), read_vs);
#else
// Need platform specific code to set the current rendering device (OpenGL target)
// to device with id read_vs so that next glReadPixels get submitted to that device
log_error( "ERROR: not implemented\n\n" );
return -1;
#endif
// Grab the contents of the final framebuffer
BufferOwningPtr<char> resultData( ReadGLRenderbuffer( glFramebuffer, glRenderbuffer,
GL_COLOR_ATTACHMENT0_EXT,
GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar,
framebufferSize, 128 ) );
// Check the contents now. We should end up with solid color bands 32 pixels high and the
// full width of the framebuffer, at values (128,128,128) due to the additive blending
for( int i = 0; i < 8; i++ )
{
for( int y = 0; y < 4; y++ )
{
// Note: coverage will be double because the 63-0 triangle overwrites again at the end of the pass
cl_uchar valA = ( ( ( i + 1 ) & 1 ) ) * numHorizVertices * 2 / framebufferSize;
cl_uchar valB = ( ( ( i + 1 ) & 2 ) >> 1 ) * numHorizVertices * 2 / framebufferSize;
cl_uchar valC = ( ( ( i + 1 ) & 4 ) >> 2 ) * numHorizVertices * 2 / framebufferSize;
cl_uchar *row = (cl_uchar *)&resultData[ ( i * 16 + y ) * framebufferSize * 4 ];
for( int x = 0; x < ( framebufferSize - 1 ) - 1; x++ )
{
if( ( row[ x * 4 ] != valA ) || ( row[ x * 4 + 1 ] != valB ) ||
( row[ x * 4 + 2 ] != valC ) )
{
log_error( "ERROR: Output framebuffer did not validate!\n" );
DumpGLBuffer( GL_UNSIGNED_BYTE, framebufferSize, 128, resultData );
log_error( "RUNS:\n" );
uint32_t *p = (uint32_t *)(char *)resultData;
size_t a = 0;
for( size_t t = 1; t < framebufferSize * framebufferSize; t++ )
{
if( p[ a ] != 0 )
{
if( p[ t ] == 0 )
{
log_error( "RUN: %ld to %ld (%d,%d to %d,%d) 0x%08x\n", a, t - 1,
(int)( a % framebufferSize ), (int)( a / framebufferSize ),
(int)( ( t - 1 ) % framebufferSize ), (int)( ( t - 1 ) / framebufferSize ),
p[ a ] );
a = t;
}
}
else
{
if( p[ t ] != 0 )
{
a = t;
}
}
}
return -1;
}
}
}
}
glDeleteBuffers( 1, &vtxBuffer );
glDeleteBuffers( 1, &colorBuffer );
destroyShaderProgram(shaderprogram);
// glDeleteVertexArrays(1, &vao);
return 0;
}
int test_fence_sync( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLint vs_count = 0;
cl_device_id *device_list = NULL;
if( !is_extension_available( device, "cl_khr_gl_event" ) )
{
log_info( "NOTE: cl_khr_gl_event extension not present on this device; skipping fence sync test\n" );
return 0;
}
#ifdef __APPLE__
CGLContextObj ctx = CGLGetCurrentContext();
CGLPixelFormatObj pix = CGLGetPixelFormat(ctx);
CGLError err = CGLDescribePixelFormat(pix, 0, kCGLPFAVirtualScreenCount, &vs_count);
device_list = (cl_device_id *) malloc(sizeof(cl_device_id)*vs_count);
clGetGLContextInfoAPPLE(context, ctx, CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE, sizeof(cl_device_id)*vs_count, device_list, NULL);
#else
// Need platform specific way of getting devices from CL context to which OpenGL can render
// If not available it can be replaced with clGetContextInfo with CL_CONTEXT_DEVICES
log_error( "ERROR: not implemented\n\n" );
return -1;
#endif
GLint rend_vs, read_vs;
int error = 0;
int any_failed = 0;
// Loop through all the devices capable to OpenGL rendering
// and set them as current rendering target
for(rend_vs = 0; rend_vs < vs_count; rend_vs++)
{
// Loop through all the devices and set them as current
// compute target
for(read_vs = 0; read_vs < vs_count; read_vs++)
{
cl_device_id rend_device = device_list[rend_vs], read_device = device_list[read_vs];
char rend_name[200], read_name[200];
clGetDeviceInfo(rend_device, CL_DEVICE_NAME, sizeof(rend_name), rend_name, NULL);
clGetDeviceInfo(read_device, CL_DEVICE_NAME, sizeof(read_name), read_name, NULL);
log_info("Rendering on: %s, read back on: %s\n", rend_name, read_name);
error = test_fence_sync_single( device, context, queue, false, rend_vs, read_vs, rend_device );
any_failed |= error;
if( error != 0 )
log_error( "ERROR: Implicit syncing with GL sync events failed!\n\n" );
else
log_info("Implicit syncing Passed\n");
error = test_fence_sync_single( device, context, queue, true, rend_vs, read_vs, rend_device );
any_failed |= error;
if( error != 0 )
log_error( "ERROR: Explicit syncing with GL sync events failed!\n\n" );
else
log_info("Explicit syncing Passed\n");
}
}
free(device_list);
return any_failed;
}

View File

@@ -0,0 +1,749 @@
//
// 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 "gl_headers.h"
extern "C" { extern cl_uint gRandomSeed; }
static const char *imageReadKernelPattern =
"#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n" /* added support for half floats */
"__kernel void sample_test( read_only image2d_t source, sampler_t sampler, __global %s4 *results )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int tidY = get_global_id(1);\n"
" results[ tidY * get_image_width( source ) + tidX ] = read_image%s( source, sampler, (int2)( tidX, tidY ) );\n"
"}\n";
static const char *imageWriteKernelPattern =
"#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n" /* added support for half floats */
"__kernel void sample_test( __global %s4 *source, write_only image2d_t dest )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int tidY = get_global_id(1);\n"
" uint index = tidY * get_image_width( dest ) + tidX;\n"
" %s4 value = source[index];\n"
" write_image%s( dest, (int2)( tidX, tidY ), %s(value));\n"
"}\n";
int test_cl_image_read( cl_context context, cl_command_queue queue, cl_mem clImage,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer )
{
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper outStream;
int error;
size_t threads[ 2 ], localThreads[ 2 ];
char kernelSource[10240];
char *programPtr;
// Determine data type and format that CL came up with
error = clGetImageInfo( clImage, CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL );
test_error( error, "Unable to get CL image format" );
/* Create the source */
*outType = get_read_kernel_type( outFormat );
size_t channelSize = get_explicit_type_size( *outType );
sprintf( kernelSource, imageReadKernelPattern, get_explicit_type_name( *outType ), get_kernel_suffix( outFormat ) );
#ifdef GLES_DEBUG
log_info("-- start cl image read kernel --\n");
log_info("%s", kernelSource);
log_info("-- end cl image read kernel --\n");
#endif
/* Create kernel */
programPtr = kernelSource;
if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) )
{
return -1;
}
// Create a vanilla output buffer
outStream = clCreateBuffer( context, CL_MEM_READ_WRITE, channelSize * 4 * imageWidth * imageHeight, NULL, &error );
test_error( error, "Unable to create output buffer" );
/* Assign streams and execute */
clSamplerWrapper sampler = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error );
test_error( error, "Unable to create sampler" );
error = clSetKernelArg( kernel, 0, sizeof( clImage ), &clImage );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, 2, sizeof( outStream ), &outStream );
test_error( error, "Unable to set kernel arguments" );
glFlush();
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
/* Run the kernel */
threads[ 0 ] = imageWidth;
threads[ 1 ] = imageHeight;
error = get_max_common_2D_work_group_size( context, kernel, threads, localThreads );
test_error( error, "Unable to get work group size to use" );
error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, localThreads, 0, NULL, NULL );
test_error( error, "Unable to execute test kernel" );
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL );
test_error(error, "clEnqueueReleaseGLObjects failed");
// Read results from the CL buffer
*outResultBuffer = malloc(channelSize * 4 * imageWidth * imageHeight);
error = clEnqueueReadBuffer( queue, outStream, CL_TRUE, 0, channelSize * 4 * imageWidth * imageHeight,
*outResultBuffer, 0, NULL, NULL );
test_error( error, "Unable to read output CL buffer!" );
return 0;
}
static int test_image_read( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer )
{
// Create a CL image from the supplied GL texture
int error;
clMemWrapper image = (*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" );
#ifndef GL_ES_VERSION_2_0
GLint fmt;
glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was baseformat %s and internalformat %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) );
#endif
return error;
}
return test_cl_image_read( context, queue, image, imageWidth, imageHeight, outFormat, outType, outResultBuffer );
}
int test_image_format_read( cl_context context, cl_command_queue queue,
size_t width, size_t height, GLenum target,
GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
// Create the GL texture
glTextureWrapper glTexture;
void *tmp = CreateGLTexture2D( width, height, target, format, internalFormat, glType, type, &glTexture, &error, true, d );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
return error;
}
/* skip formats not supported by OpenGL */
if(!tmp)
{
return 0;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType actualType;
char *outBuffer;
error = test_image_read( context, queue, target, glTexture, width, height, &clFormat, &actualType, (void **)&outBuffer );
if( error != 0 )
return error;
BufferOwningPtr<char> actualResults(outBuffer);
log_info( "- Read [%4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n", (int)width, (int)height,
GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType),
GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type ));
// We have to convert our input buffer to the returned type, so we can validate.
BufferOwningPtr<char> convertedInputs(convert_to_expected( inputBuffer, width * height, type, actualType ));
// Now we validate
int valid = 0;
if(convertedInputs) {
if( actualType == kFloat )
valid = validate_float_results( convertedInputs, actualResults, width, height );
else
valid = validate_integer_results( convertedInputs, actualResults, width, height, get_explicit_type_size( actualType ) );
}
return valid;
}
int test_images_read( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] =
#ifdef GL_ES_VERSION_2_0
{ GL_TEXTURE_2D };
#else // GL_ES_VERSION_2_0
{ GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
#endif // GL_ES_VERSION_2_0
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA, GL_RGBA, GL_FLOAT, kFloat },
};
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed(gRandomSeed );
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing image read for GL format %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
size_t width = random_in_range( 16, 512, seed );
size_t height = random_in_range( 16, 512, seed );
if( test_image_format_read( context, queue, width, height,
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image read test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Image read for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
}
}
return error;
}
int test_images_read_cube( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
#ifdef GL_ES_VERSION_2_0
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
// XXX add others
#else // GL_ES_VERSION_2_0
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#endif
};
size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed(gRandomSeed);
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing image read cubemap for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
if( test_image_format_read( context, queue, sizes[i], sizes[i],
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image read cubemap test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Image read cubemap for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
else
break; // Skip other cube map targets; they're unlikely to pass either
}
}
return error;
}
#pragma mark -------------------- Write tests -------------------------
int test_cl_image_write( cl_context context, cl_command_queue queue, cl_mem clImage,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, MTdata d )
{
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper inStream;
int error;
size_t threads[ 2 ], localThreads[ 2 ];
char kernelSource[10240];
char *programPtr;
// Determine data type and format that CL came up with
error = clGetImageInfo( clImage, CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL );
test_error( error, "Unable to get CL image format" );
/* Create the source */
*outType = get_write_kernel_type( outFormat );
size_t channelSize = get_explicit_type_size( *outType );
const char* suffix = get_kernel_suffix( outFormat );
const char* convert = get_write_conversion( outFormat, *outType );
sprintf( kernelSource, imageWriteKernelPattern, get_explicit_type_name( *outType ), get_explicit_type_name( *outType ), suffix, convert);
#ifdef GLES_DEBUG
log_info("-- start cl image write kernel --\n");
log_info("%s", kernelSource);
log_info("-- end cl image write kernel --\n");
#endif
/* Create kernel */
programPtr = kernelSource;
if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) )
{
return -1;
}
// Generate some source data based on the input type we need
*outSourceBuffer = CreateRandomData(*outType, imageWidth * imageHeight * 4, d);
// Create a vanilla input buffer
inStream = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, channelSize * 4 * imageWidth * imageHeight, *outSourceBuffer, &error );
test_error( error, "Unable to create output buffer" );
/* Assign streams and execute */
clSamplerWrapper sampler = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error );
test_error( error, "Unable to create sampler" );
error = clSetKernelArg( kernel, 0, sizeof( inStream ), &inStream );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( clImage ), &clImage );
test_error( error, "Unable to set kernel arguments" );
glFlush();
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
/* Run the kernel */
threads[ 0 ] = imageWidth;
threads[ 1 ] = imageHeight;
error = get_max_common_2D_work_group_size( context, kernel, threads, localThreads );
test_error( error, "Unable to get work group size to use" );
error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, localThreads, 0, NULL, NULL );
test_error( error, "Unable to execute test kernel" );
clEventWrapper event;
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &clImage, 0, NULL, &event );
test_error(error, "clEnqueueReleaseGLObjects failed");
error = clWaitForEvents( 1, &event );
test_error(error, "clWaitForEvents failed");
#ifdef GLES_DEBUG
int i;
size_t origin[] = {0, 0, 0,};
size_t region[] = {imageWidth, imageHeight, 1 };
void* cldata = malloc( channelSize * 4 * imageWidth * imageHeight );
clEnqueueReadImage( queue, clImage, 1, origin, region, 0, 0, cldata, 0, 0, 0);
log_info("- start CL Image Data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(*outType), imageWidth, imageHeight, cldata);
log_info("- end CL Image Data -- \n");
free(cldata);
#endif
// All done!
return 0;
}
int test_image_write( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer, MTdata d )
{
int error;
// Create a CL image from the supplied GL texture
clMemWrapper image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_WRITE_ONLY, glTarget, 0, glTexture, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create CL image from GL texture" );
#ifndef GL_ES_VERSION_2_0
GLint fmt;
glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was baseformat %s and internalformat %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) );
#endif
return error;
}
return test_cl_image_write( context, queue, image, imageWidth, imageHeight, outFormat, outType, outSourceBuffer, d );
}
int test_image_format_write( cl_context context, cl_command_queue queue,
size_t width, size_t height, GLenum target,
GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
// Create the GL texture
glTextureWrapper glTexture;
void *tmp = CreateGLTexture2D( width, height, target, format, internalFormat, glType, type, &glTexture, &error, true, d );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
return error;
}
/* skip formats not supported by OpenGL */
if(!tmp)
{
return 0;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType sourceType;
void *outSourceBuffer;
error = test_image_write( context, queue, target, glTexture, width, height, &clFormat, &sourceType, (void **)&outSourceBuffer, d );
if( error != 0 )
return error;
BufferOwningPtr<char> actualSource(outSourceBuffer);
log_info( "- Write [%4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n", (int)width, (int)height,
GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType),
GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type ));
// Now read the results from the GL texture
ExplicitType readType = type;
BufferOwningPtr<char> glResults( ReadGLTexture( target, glTexture, format, internalFormat, glType, readType, width, height ) );
// We have to convert our input buffer to the returned type, so we can validate.
BufferOwningPtr<char> convertedGLResults( convert_to_expected( glResults, width * height, readType, sourceType ) );
#ifdef GLES_DEBUG
log_info("- start read GL data -- \n");
DumpGLBuffer(glType, width, height, glResults);
log_info("- end read GL data -- \n");
log_info("- start converted data -- \n");
DumpGLBuffer(glType, width, height, convertedGLResults);
log_info("- end converted data -- \n");
#endif
// Now we validate
int valid = 0;
if(convertedGLResults) {
if( sourceType == kFloat )
valid = validate_float_results( actualSource, convertedGLResults, width, height );
else
valid = validate_integer_results( actualSource, convertedGLResults, width, height, get_explicit_type_size( readType ) );
}
return valid;
}
int test_images_write( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] =
#ifdef GL_ES_VERSION_2_0
{ GL_TEXTURE_2D };
#else // GL_ES_VERSION_2_0
{ GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
#endif
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
#ifdef GL_ES_VERSION_2_0
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
// XXX add others
#else // GL_ES_VERSION_2_0
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#endif
};
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed(gRandomSeed);
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
log_info( "Testing image write test for %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
size_t i;
for( i = 0; i < iter; i++ )
{
size_t width = random_in_range( 16, 512, seed );
size_t height = random_in_range( 16, 512, seed );
if( targets[ tgtIdx ] == GL_TEXTURE_2D )
width = height;
if( test_image_format_write( context, queue, width, height,
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image write test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == 6 )
{
log_info( "passed: Image write for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
}
}
return error;
}
int test_images_write_cube( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
#ifdef GL_ES_VERSION_2_0
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
// XXX add others
#else // GL_ES_VERSION_2_0
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#endif
};
size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed( gRandomSeed );
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing image write cubemap test for %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
if( test_image_format_write( context, queue, sizes[i], sizes[i],
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image write cubemap test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Image write cubemap for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
else
break; // Skip other cube map targets; they're unlikely to pass either
}
}
return error;
}

View File

@@ -0,0 +1,256 @@
//
// 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 "gl_headers.h"
extern "C" {extern cl_uint gRandomSeed;};
static int test_image_read( cl_context context, cl_command_queue queue, GLenum glTarget, GLuint glTexture,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat,
ExplicitType *outType, void **outResultBuffer )
{
// Create a CL image from the supplied GL texture
int error;
clMemWrapper image = (*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" );
#ifndef GL_ES_VERSION_2_0
GLint fmt;
glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was baseformat %s and internalformat %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) );
#endif
return error;
}
// Determine data type and format that CL came up with
error = clGetImageInfo( image, CL_IMAGE_FORMAT, sizeof( cl_image_format ), outFormat, NULL );
test_error( error, "Unable to get CL image format" );
return CheckGLObjectInfo(image, CL_GL_OBJECT_TEXTURE2D, glTexture, glTarget, 0);
}
static int test_image_object_info( cl_context context, cl_command_queue queue,
size_t width, size_t height, GLenum target,
GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
// Create the GL texture
glTextureWrapper glTexture;
void *tmp = CreateGLTexture2D( width, height, target, format, internalFormat, glType, type, &glTexture, &error, true, d );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
// GL_RGBA_INTEGER_EXT doesn't exist in GLES2. No need to check for it.
return error;
}
/* skip formats not supported by OpenGL */
if(!tmp)
{
return 0;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType actualType;
char *outBuffer;
error = test_image_read( context, queue, target, glTexture, width, height, &clFormat, &actualType, (void **)&outBuffer );
return error;
}
int test_images_2D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] =
#ifdef GL_ES_VERSION_2_0
{ GL_TEXTURE_2D };
#else // GL_ES_VERSION_2_0
{ GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
#endif // GL_ES_VERSION_2_0
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, kHalf },
{ GL_RGBA, GL_RGBA, GL_FLOAT, kFloat },
};
size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed( gRandomSeed );
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing image texture object info test for %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
if( test_image_object_info( context, queue, sizes[i], sizes[i],
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image texture object info test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Image texture object info test passed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
else
break; // Skip other cube map targets; they're unlikely to pass either
}
}
return error;
}
int test_images_cube_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
#ifdef GL_ES_VERSION_2_0
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
// XXX add others
#else // GL_ES_VERSION_2_0
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#endif
};
size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed( gRandomSeed );
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing cube map object info test for %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
if( test_image_object_info( context, queue, sizes[i], sizes[i],
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Cube map object info test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Cube map object info test passed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
else
break; // Skip other cube map targets; they're unlikely to pass either
}
}
return error;
}

View File

@@ -0,0 +1,268 @@
//
// 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 "gl_headers.h"
extern "C" { extern cl_uint gRandomSeed; };
static const char *imageReadKernelPattern =
"__kernel void sample_test( read_only image3d_t source, sampler_t sampler, __global %s4 *results )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int tidY = get_global_id(1);\n"
" int tidZ = get_global_id(2);\n"
" int width = get_image_width( source );\n"
" int height = get_image_height( source );\n"
" int offset = tidZ * width * height + tidY * width + tidX;\n"
"\n"
" results[ offset ] = read_image%s( source, sampler, (int4)( tidX, tidY, tidZ, 0 ) );\n"
"}\n";
static int test_image_read( 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 )
{
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper streams[ 2 ];
int error;
size_t threads[ 3 ], localThreads[ 3 ];
char kernelSource[1024];
char *programPtr;
// 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" );
#ifndef GL_ES_VERSION_2_0
GLint fmt;
glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was format %s\n", GetGLFormatName( fmt ) );
#endif
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" );
/* Create the source */
*outType = get_read_kernel_type( outFormat );
size_t channelSize = get_explicit_type_size( *outType );
sprintf( kernelSource, imageReadKernelPattern, get_explicit_type_name( *outType ), get_kernel_suffix( outFormat ) );
/* Create kernel */
programPtr = kernelSource;
if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) )
{
return -1;
}
// Create a vanilla output buffer
streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, channelSize * 4 * imageWidth * imageHeight * imageDepth, NULL, &error );
test_error( error, "Unable to create output buffer" );
/* Assign streams and execute */
clSamplerWrapper sampler = clCreateSampler( context, CL_FALSE, CL_ADDRESS_NONE, CL_FILTER_NEAREST, &error );
test_error( error, "Unable to create sampler" );
error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( sampler ), &sampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, 2, sizeof( streams[ 1 ] ), &streams[ 1 ] );
test_error( error, "Unable to set kernel arguments" );
glFlush();
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
/* Run the kernel */
threads[ 0 ] = imageWidth;
threads[ 1 ] = imageHeight;
threads[ 2 ] = imageDepth;
error = get_max_common_3D_work_group_size( context, kernel, threads, localThreads );
test_error( error, "Unable to get work group size to use" );
error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, localThreads, 0, NULL, NULL );
test_error( error, "Unable to execute test kernel" );
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL );
test_error(error, "clEnqueueReleaseGLObjects failed");
// Read results from the CL buffer
*outResultBuffer = (void *)( new char[ channelSize * 4 * imageWidth * imageHeight * imageDepth ] );
error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, channelSize * 4 * imageWidth * imageHeight * imageDepth,
*outResultBuffer, 0, NULL, NULL );
test_error( error, "Unable to read output CL buffer!" );
return 0;
}
int test_image_format_read( cl_context context, cl_command_queue queue,
size_t width, size_t height, size_t depth,
GLenum target, GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
// Create the GL texture
glTextureWrapper glTexture;
void* tmp = CreateGLTexture3D( width, height, depth, target, format, internalFormat, glType, type, &glTexture, &error, d );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
return error;
}
/* skip formats not supported by OpenGL */
if(!tmp)
{
return 0;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType actualType;
char *outBuffer;
error = test_image_read( context, queue, target, glTexture, width, height, depth, &clFormat, &actualType, (void **)&outBuffer );
if( error != 0 )
return error;
BufferOwningPtr<char> actualResults(outBuffer);
log_info( "- Read [%4d x %4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n",
(int)width, (int)height, (int)depth,
GetGLFormatName( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType),
GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type ));
// We have to convert our input buffer to the returned type, so we can validate.
// This is necessary because OpenCL might not actually pick an internal format that actually matches our
// input format (for example, if it picks a normalized format, the results will come out as floats instead of
// going in as ints).
BufferOwningPtr<char> convertedInputs(convert_to_expected( inputBuffer, width * height * depth, type, actualType ));
if( convertedInputs == NULL )
return -1;
// Now we validate
if( actualType == kFloat )
return validate_float_results( convertedInputs, actualResults, width, height, depth );
else
return validate_integer_results( convertedInputs, actualResults, width, height, depth, get_explicit_type_size( actualType ) );
}
int test_images_read_3D( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_3D };
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
#ifdef GL_ES_VERSION_2_0
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
// XXX add others
#else // GL_ES_VERSION_2_0
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#endif
};
size_t sizes[] = { 2, 4, 8, 16, 32, 64, 128 };
size_t fmtIdx, tgtIdx;
int error = 0;
RandomSeed seed(gRandomSeed);
size_t iter = sizeof(sizes)/sizeof(sizes[0]);
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing image read for GL format %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
if( test_image_format_read( context, queue, sizes[i], sizes[i], sizes[i],
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image read test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == sizeof (sizes) / sizeof( sizes[0] ) )
{
log_info( "passed: Image read test for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
}
}
return error;
}

View File

@@ -0,0 +1,166 @@
//
// 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 "gl_headers.h"
#include "testBase.h"
extern "C" {extern cl_uint gRandomSeed;};
static int test_image_read( 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" );
#ifndef GL_ES_VERSION_2_0
GLint fmt;
glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was format %s\n", GetGLFormatName( fmt ) );
#endif
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" );
return CheckGLObjectInfo(streams[0], CL_GL_OBJECT_TEXTURE3D, glTexture, glTarget, 0);
}
static int test_image_format_read( cl_context context, cl_command_queue queue,
size_t width, size_t height, size_t depth,
GLenum target, GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
// Create the GL texture
glTextureWrapper glTexture;
void* tmp = CreateGLTexture3D( width, height, depth, target, format, internalFormat, glType, type, &glTexture, &error, d, true );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
return error;
}
/* skip formats not supported by OpenGL */
if(!tmp)
{
return 0;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType actualType;
char *outBuffer;
return test_image_read( context, queue, target, glTexture, width, height, depth, &clFormat, &actualType, (void **)&outBuffer );
}
int test_images_3D_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_3D };
struct {
GLenum internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
#ifdef GL_ES_VERSION_2_0
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
// { GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
// { GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
// { GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
// { GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
// { GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
// { GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
// { GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#else // GL_ES_VERSION_2_0
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat }
#endif
};
size_t sizes[] = { 2, 4, 8, 16, 32, 64, 128 };
size_t fmtIdx, tgtIdx;
int error = 0;
RandomSeed seed(gRandomSeed);
size_t iter = sizeof(sizes)/sizeof(sizes[0]);
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( targets ) / sizeof( targets[ 0 ] ); tgtIdx++ )
{
size_t i;
log_info( "Testing image info for GL format %s : %s : %s : %s\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
if( test_image_format_read( context, queue, sizes[i], sizes[i], sizes[i],
targets[ tgtIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Image info test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tgtIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
error++;
break; // Skip other sizes for this combination
}
}
}
}
return error;
}

View File

@@ -0,0 +1,373 @@
//
// 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 "helpers.h"
#include "gl_headers.h"
extern "C" { extern cl_uint gRandomSeed; };
extern int test_cl_image_write( cl_context context, cl_command_queue queue, cl_mem clImage,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat,
ExplicitType *outType, void **outSourceBuffer, MTdata d );
extern int test_cl_image_read( cl_context context, cl_command_queue queue, cl_mem clImage,
size_t imageWidth, size_t imageHeight, cl_image_format *outFormat,
ExplicitType *outType, void **outResultBuffer );
static int 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 )
{
int error;
// Create a CL image from the supplied GL renderbuffer
clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_READ_ONLY, glRenderbuffer, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create CL image from GL renderbuffer" );
return error;
}
return test_cl_image_read( context, queue, image, imageWidth, imageHeight, outFormat, outType, outResultBuffer );
}
int test_renderbuffer_read_image( cl_context context, cl_command_queue queue,
GLsizei width, GLsizei height, GLenum attachment,
GLenum rbFormat, GLenum rbType,
GLenum texFormat, GLenum texType,
ExplicitType type, MTdata d )
{
int error;
// Create the GL renderbuffer
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
void *tmp = CreateGLRenderbuffer( width, height, attachment, rbFormat, rbType, texFormat, texType,
type, &glFramebuffer, &glRenderbuffer, &error, d, true );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
// GL_RGBA_INTEGER_EXT doesn't exist in GLES2. No need to check for it.
return error;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType actualType;
char *outBuffer;
error = test_attach_renderbuffer_read_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &actualType, (void **)&outBuffer );
if( error != 0 )
return error;
BufferOwningPtr<char> actualResults(outBuffer);
log_info( "- Read [%4d x %4d] : GL renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, height,
GetGLFormatName( rbFormat ), GetGLFormatName( rbFormat ), GetGLTypeName( rbType ),
GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type ));
#ifdef GLES_DEBUG
log_info("- start read GL data -- \n");
DumpGLBuffer(glType, width, height, actualResults);
log_info("- end read GL data -- \n");
#endif
// We have to convert our input buffer to the returned type, so we can validate.
BufferOwningPtr<char> convertedInput(convert_to_expected( inputBuffer, width * height, type, actualType ));
#ifdef GLES_DEBUG
log_info("- start input data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, convertedInput);
log_info("- end input data -- \n");
#endif
#ifdef GLES_DEBUG
log_info("- start converted data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, actualResults);
log_info("- end converted data -- \n");
#endif
// Now we validate
int valid = 0;
if(convertedInput) {
if( actualType == kFloat )
valid = validate_float_results( convertedInput, actualResults, width, height );
else
valid = validate_integer_results( convertedInput, actualResults, width, height, get_explicit_type_size( actualType ) );
}
return valid;
}
int test_renderbuffer_read( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
struct {
GLenum rbFormat;
GLenum rbType;
GLenum texFormat;
GLenum texType;
ExplicitType type;
} formats[] = {
{ GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
//{ GL_RGBA16F_QCOM, GL_HALF_FLOAT_OES, GL_RGBA, GL_HALF_FLOAT_OES, kHalf }, // Half-float not supported by ReadPixels
{ GL_RGBA32F, GL_FLOAT, GL_RGBA, GL_FLOAT, kFloat},
// XXX add others
};
size_t fmtIdx, attIdx;
int error = 0;
#ifdef GLES_DEBUG
size_t iter = 1;
#else
size_t iter = 6;
#endif
RandomSeed seed( gRandomSeed );
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( attIdx = 0; attIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); attIdx++ )
{
size_t i;
log_info( "Testing renderbuffer read for %s : %s : %s : %s\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
for( i = 0; i < iter; i++ )
{
GLsizei width = random_in_range( 16, 512, seed );
GLsizei height = random_in_range( 16, 512, seed );
#ifdef GLES_DEBUG
width = height = 4;
#endif
if( test_renderbuffer_read_image( context, queue, width, height,
attachments[ attIdx ],
formats[ fmtIdx ].rbFormat,
formats[ fmtIdx ].rbType,
formats[ fmtIdx ].texFormat,
formats[ fmtIdx ].texType,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Renderbuffer read test failed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Renderbuffer read test passed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
}
}
}
return error;
}
#pragma mark -------------------- Write tests -------------------------
int 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 )
{
int error;
// Create a CL image from the supplied GL renderbuffer
clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_WRITE_ONLY, glRenderbuffer, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create CL image from GL renderbuffer" );
return error;
}
return test_cl_image_write( context, queue, image, imageWidth, imageHeight, outFormat, outType, outSourceBuffer, d );
}
int test_renderbuffer_image_write( cl_context context, cl_command_queue queue,
GLsizei width, GLsizei height, GLenum attachment,
GLenum rbFormat, GLenum rbType,
GLenum texFormat, GLenum texType,
ExplicitType type, MTdata d)
{
int error;
// Create the GL renderbuffer
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
CreateGLRenderbuffer( width, height, attachment, rbFormat, rbType, texFormat, texType,
type, &glFramebuffer, &glRenderbuffer, &error, d, false );
if( error != 0 )
{
// GL_RGBA_INTEGER_EXT doesn't exist in GLES2. No need to check for it.
return error;
}
// Run and get the results
cl_image_format clFormat;
ExplicitType sourceType;
void *outSourceBuffer;
error = test_attach_renderbuffer_write_to_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &sourceType, d, (void **)&outSourceBuffer );
if( error != 0 )
return error;
BufferOwningPtr<char> sourceData(outSourceBuffer);
log_info( "- Write [%4d x %4d] : GL Renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, height,
GetGLFormatName( rbFormat ), GetGLFormatName( rbFormat ), GetGLTypeName( rbType),
GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type ));
// Now read the results from the GL renderbuffer
void* tmp = ReadGLRenderbuffer( glFramebuffer, glRenderbuffer, attachment, rbFormat, rbType,
texFormat, texType, type, width, height );
BufferOwningPtr<char> resultData( tmp );
#ifdef GLES_DEBUG
log_info("- start result data -- \n");
DumpGLBuffer(glType, width, height, resultData);
log_info("- end result data -- \n");
#endif
// We have to convert our input buffer to the returned type, so we can validate.
BufferOwningPtr<char> convertedData( convert_to_expected( resultData, width * height, type, sourceType ) );
#ifdef GLES_DEBUG
log_info("- start input data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(sourceType), width, height, sourceData);
log_info("- end input data -- \n");
#endif
#ifdef GLES_DEBUG
log_info("- start converted data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(sourceType), width, height, convertedData);
log_info("- end converted data -- \n");
#endif
// Now we validate
int valid = 0;
if(convertedData) {
if( sourceType == kFloat )
valid = validate_float_results( sourceData, convertedData, width, height );
else
valid = validate_integer_results( sourceData, convertedData, width, height, get_explicit_type_size( type ) );
}
return valid;
}
int test_renderbuffer_write( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
struct {
GLenum rbFormat;
GLenum rbType;
GLenum texFormat;
GLenum texType;
ExplicitType type;
} formats[] = {
{ GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
//{ GL_RGBA16F_QCOM, GL_UNSIGNED_SHORT, GL_RGBA, GL_UNSIGNED_SHORT, kHalf }, // Half float not supported by ReadPixels
{ GL_RGBA32F, GL_FLOAT, GL_RGBA, GL_FLOAT, kFloat},
// XXX add others
};
size_t fmtIdx, attIdx;
int error = 0;
size_t iter = 6;
#ifdef GLES_DEBUG
iter = 1;
#endif
RandomSeed seed( gRandomSeed );
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( attIdx = 0; attIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); attIdx++ )
{
log_info( "Testing Renderbuffer write test for %s : %s : %s : %s\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType) );
size_t i;
for( i = 0; i < iter; i++ )
{
GLsizei width = random_in_range( 16, 512, seed );
GLsizei height = random_in_range( 16, 512, seed );
#ifdef GLES_DEBUG
width = height = 4;
#endif
if( test_renderbuffer_image_write( context, queue, width, height,
attachments[ attIdx ],
formats[ fmtIdx ].rbFormat,
formats[ fmtIdx ].rbType,
formats[ fmtIdx ].texFormat,
formats[ fmtIdx ].texType,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Renderbuffer write test failed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Renderbuffer write test passed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
}
}
}
return error;
}

View File

@@ -0,0 +1,119 @@
//
// 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 "gl_headers.h"
#include "testBase.h"
extern "C" {extern cl_uint gRandomSeed;};
static int test_renderbuffer_object_info( cl_context context, cl_command_queue queue,
GLsizei width, GLsizei height, GLenum attachment,
GLenum rbFormat, GLenum rbType,
GLenum texFormat, GLenum texType,
ExplicitType type, MTdata d )
{
int error;
// Create the GL render buffer
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
void* tmp = CreateGLRenderbuffer( width, height, attachment, rbFormat, rbType, texFormat, texType,
type, &glFramebuffer, &glRenderbuffer, &error, d, true );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
return error;
clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)(context, CL_MEM_READ_ONLY, glRenderbuffer, &error);
test_error(error, "clCreateFromGLRenderbuffer failed");
log_info( "- Given a GL format of %s, input type was %s, size was %d x %d\n",
GetGLFormatName( rbFormat ),
get_explicit_type_name( type ), (int)width, (int)height );
// Verify the expected information here.
return CheckGLObjectInfo(image, CL_GL_OBJECT_RENDERBUFFER, (GLuint)glRenderbuffer, rbFormat, 0);
}
int test_renderbuffer_getinfo( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
struct {
GLenum rbFormat;
GLenum rbType;
GLenum texFormat;
GLenum texType;
ExplicitType type;
} formats[] = {
{ GL_RGBA8_OES, GL_UNSIGNED_BYTE, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA32F, GL_FLOAT, GL_RGBA, GL_FLOAT, kFloat }
};
size_t fmtIdx, tgtIdx;
int error = 0;
size_t iter = 6;
RandomSeed seed(gRandomSeed);
// Check if images are supported
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Loop through a set of GL formats, testing a set of sizes against each one
for( fmtIdx = 0; fmtIdx < sizeof( formats ) / sizeof( formats[ 0 ] ); fmtIdx++ )
{
for( tgtIdx = 0; tgtIdx < sizeof( attachments ) / sizeof( attachments[ 0 ] ); tgtIdx++ )
{
log_info( "Testing Renderbuffer object info for %s : %s : %s\n",
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLBaseFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].type ) );
size_t i;
for( i = 0; i < iter; i++ )
{
GLsizei width = random_in_range( 16, 512, seed );
GLsizei height = random_in_range( 16, 512, seed );
if( test_renderbuffer_object_info( context, queue, (int)width, (int)height,
attachments[ tgtIdx ],
formats[ fmtIdx ].rbFormat,
formats[ fmtIdx ].rbType,
formats[ fmtIdx ].texFormat,
formats[ fmtIdx ].texType,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Renderbuffer write test failed for GL format %s : %s\n\n",
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
error++;
break; // Skip other sizes for this combination
}
}
if( i == iter )
{
log_info( "passed: Renderbuffer write test passed for GL format %s : %s\n\n",
GetGLFormatName( formats[ fmtIdx ].rbFormat ),
GetGLTypeName( formats[ fmtIdx ].rbType ) );
}
}
}
return error;
}