Initial open source release of OpenCL 2.0 CTS.

This commit is contained in:
Kedar Patil
2017-05-16 18:50:35 +05:30
parent 6911ba5116
commit 3a440d17c8
883 changed files with 318212 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
if(WIN32)
list(APPEND CLConform_LIBRARIES glut32 opengl32 glu32 )
else(WIN32)
list(APPEND CLConform_LIBRARIES GL glut GLEW GLU)
endif(WIN32)
set (GL_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
../../test_common/gl/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
)
if (WIN32)
list (APPEND GL_SOURCES ../../test_common/gl/setup_win32.cpp)
else(WIN32)
list (APPEND GL_SOURCES ../../test_common/gl/setup_x11.cpp)
endif(WIN32)
# Compiling GLEW along with the project if the compiler is MINGW.
# The mingw linker was giving weird errors while linking to glew32.lib generated by
# MSVC.
if(MINGW)
list (APPEND GL_SOURCES GLEW/glew.c)
set_source_files_properties(
${GL_SOURCES}
COMPILE_FLAGS -DGLEW_STATIC)
include_directories("./GLEW/")
endif(MINGW)
if (MSVC)
if(CMAKE_CL_64)
list(APPEND CLConform_LIBRARIES glew64)
else(CMAKE_CL_64)
list(APPEND CLConform_LIBRARIES glew32)
endif(CMAKE_CL_64)
endif(MSVC)
add_executable(conformance_test_gl
${GL_SOURCES} ${GLUT_SOURCES})
set_source_files_properties(
${GL_SOURCES}
PROPERTIES LANGUAGE CXX)
TARGET_LINK_LIBRARIES(conformance_test_gl
${CLConform_LIBRARIES})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_gl
: helpers.cpp
main.cpp
test_buffers.cpp
test_images_2D.cpp
test_images_2D_info.cpp
test_images_3D.cpp
test_images_3D_info.cpp
test_renderbuffer.cpp
test_renderbuffer_info.cpp
: <target-os>darwin:<source>setup_osx.cpp
<target-os>linux:<source>setup_x11.cpp
<target-os>windows:<source>setup_win32.cpp
<library>../..//glut
<library>../..//glew
;
install dist
: test_gl
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/gl
<variant>release:<location>$(DIST)/release/tests/test_conformance/gl
;

View File

@@ -0,0 +1,62 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
helpers.cpp \
test_buffers.cpp \
test_fence_sync.cpp \
test_images_1D.cpp \
test_images_1Darray.cpp \
test_images_2Darray.cpp \
test_images_2D.cpp \
test_images_3D.cpp \
test_images_getinfo_common.cpp \
test_images_read_common.cpp \
test_images_write_common.cpp \
test_renderbuffer.cpp \
test_renderbuffer_info.cpp \
test_images_depth.cpp \
test_images_multisample.cpp \
test_image_methods.cpp \
../../test_common/gl/helpers.cpp \
../../test_common/gl/setup_osx.cpp \
../../test_common/harness/conversions.c \
../../test_common/harness/errorHelpers.c \
../../test_common/harness/genericThread.cpp \
../../test_common/harness/imageHelpers.c \
../../test_common/harness/kernelHelpers.c \
../../test_common/harness/mt19937.c \
../../test_common/harness/testHarness.c \
../../test_common/harness/threadTesting.c
DEFINES =
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK = $(SOURCES)
HEADERS =
TARGET = test_gl
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32
CC = c++
CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF}
OBJECTS := ${SOURCES:.c=.o}
OBJECTS := ${OBJECTS:.cpp=.o}
TARGETOBJECT =
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES)
clean:
rm -f $(TARGET) $(OBJECTS)
.DEFAULT:
@echo The target \"$@\" does not exist in Makefile.

View File

@@ -0,0 +1,78 @@
//
// 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 __COMMON_H__
#define __COMMON_H__
#include "testBase.h"
typedef struct {
size_t width;
size_t height;
size_t depth;
} sizevec_t;
struct format {
GLenum internal;
GLenum formattype;
GLenum datatype;
ExplicitType type;
};
// These are the typically tested formats.
static struct format common_formats[] = {
#ifdef __APPLE__
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, kUChar },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
// { GL_RGB10, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, kFloat },
#endif
{ 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 },
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
};
#ifdef GL_VERSION_3_2
static struct format depth_formats[] = {
{ GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, kUShort },
{ GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, kFloat },
{ GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, kUInt },
{ GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, kFloat },
};
#endif
int test_images_write_common(cl_device_id device, cl_context context,
cl_command_queue queue, struct format* formats, size_t nformats,
GLenum *targets, size_t ntargets, sizevec_t* sizes, size_t nsizes );
int test_images_read_common( cl_device_id device, cl_context context,
cl_command_queue queue, struct format* formats, size_t nformats,
GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes );
int test_images_get_info_common( cl_device_id device, cl_context context,
cl_command_queue queue, struct format* formats, size_t nformats,
GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes );
int is_rgb_101010_supported( cl_context context, GLenum gl_target );
#endif // __COMMON_H__

View File

@@ -0,0 +1,657 @@
//
// 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"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif
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_UNORM_INT24:
case CL_SNORM_INT8:
case CL_SNORM_INT16:
case CL_HALF_FLOAT:
case CL_FLOAT:
case CL_UNORM_INT_101010:
return "f";
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:
log_error("Test error: unsupported kernel suffix for image_channel_data_type 0x%X\n",format->image_channel_data_type);
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_UNORM_INT24:
case CL_SNORM_INT8:
case CL_SNORM_INT16:
case CL_HALF_FLOAT:
case CL_FLOAT:
case CL_UNORM_INT_101010:
#ifdef GL_VERSION_3_2
case CL_DEPTH:
#endif
return kFloat;
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:
log_error("Test error: unsupported kernel suffix for image_channel_data_type 0x%X\n",format->image_channel_data_type);
return kNumExplicitTypes;
}
}
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_UNORM_INT24:
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;
case CL_UNORM_INT_101010:
return kFloat;
#ifdef GL_VERSION_3_2
case CL_DEPTH:
return kFloat;
#endif
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_HALF_FLOAT:
case CL_FLOAT:
case CL_UNORM_INT_101010:
case CL_UNORM_INT24:
if(type != kFloat) return "convert_float4";
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, size_t channelNum, GLenum glDataType )
{
#ifdef 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 * channelNum * get_explicit_type_size(outType) ] ; // sizeof( cl_int ) ];
if (glDataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) {
for (size_t i = 0; i < numPixels; ++i) {
((cl_float*)outData)[i] = ((cl_float*)inputBuffer)[2 * i];
}
}
else {
memcpy( outData, inputBuffer, numPixels * channelNum * 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; 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 * channelNum ];
const cl_float MaxValue = (glDataType == GL_UNSIGNED_INT_24_8) ? 16777215.f : 4294967295.f;
const cl_uint ShiftBits = (glDataType == GL_UNSIGNED_INT_24_8) ? 8 : 0;
for( size_t i = 0; i < numPixels * channelNum; i++ )
{
outData[ i ] = (cl_float)(src[ i ] >> ShiftBits) / MaxValue;
}
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 == kHalf )
{
cl_half *src = (cl_half *)inputBuffer;
switch( outType )
{
case kFloat:
{
cl_float *outData = new cl_float[ numPixels * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; i++ )
{
outData[ i ] = convert_half_to_float(src[ i ]);
}
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 sampleNum, size_t typeSize )
{
return validate_integer_results( expectedResults, actualResults, width, height, sampleNum, 0, typeSize );
}
int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t typeSize )
{
char *expected = (char *)expectedResults;
char *actual = (char *)actualResults;
for ( size_t s = 0; s < sampleNum; s++ )
{
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,%d did not validate!\n", (int)x, (int)y, (int)s );
else
log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s );
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, size_t sampleNum, size_t channelNum )
{
return validate_float_results( expectedResults, actualResults, width, height, sampleNum, 0, channelNum );
}
int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t channelNum )
{
cl_float *expected = (cl_float *)expectedResults;
cl_float *actual = (cl_float *)actualResults;
for ( size_t s = 0; s < sampleNum; s++ )
{
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 < channelNum; 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,%d did not validate!\n", (int)x, (int)y, (int)s );
else
log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s );
if (channelNum == 4)
{
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 ] );
}
else if(channelNum == 1)
{
log_error( "\tExpected: %f\n", expected[ 0 ] );
log_error( "\t : %a\n", expected[ 0 ] );
log_error( "\t Actual: %f\n", actual[ 0 ] );
log_error( "\t : %a\n", actual[ 0 ] );
}
return -1;
}
expected += channelNum;
actual += channelNum;
}
}
}
}
return 0;
}
int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum )
{
return validate_float_results_rgb_101010( expectedResults, actualResults, width, height, sampleNum, 0 );
}
int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum )
{
cl_float *expected = (cl_float *)expectedResults;
cl_float *actual = (cl_float *)actualResults;
for ( size_t s = 0; s < sampleNum; s++ )
{
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 < 3; i++ ) // skip the fourth channel
{
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,%d did not validate!\n", (int)x, (int)y, (int)s );
else
log_error( "ERROR: Data sample %d,%d,%d,%d did not validate!\n", (int)x, (int)y, (int)z, (int)s );
log_error( "\tExpected: %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ] );
log_error( "\t : %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ] );
log_error( "\t Actual: %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ] );
log_error( "\t : %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ] );
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 we're dealing with a buffer or render buffer, we are done.
if (object_type == CL_GL_OBJECT_BUFFER || object_type == CL_GL_OBJECT_RENDERBUFFER) {
return 0;
}
// Otherwise, it's a texture-based object and requires a bit more checking.
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")));
}
int is_rgb_101010_supported( cl_context context, GLenum gl_target )
{
cl_image_format formatList[ 128 ];
cl_uint formatCount = 0;
unsigned int i;
int error;
cl_mem_object_type image_type;
switch (get_base_gl_target(gl_target)) {
case GL_TEXTURE_1D:
image_type = CL_MEM_OBJECT_IMAGE1D;
case GL_TEXTURE_BUFFER:
image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER;
break;
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_2D:
case GL_COLOR_ATTACHMENT0:
case GL_RENDERBUFFER:
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
image_type = CL_MEM_OBJECT_IMAGE2D;
break;
case GL_TEXTURE_3D:
image_type = CL_MEM_OBJECT_IMAGE3D;
case GL_TEXTURE_1D_ARRAY:
image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
case GL_TEXTURE_2D_ARRAY:
image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
break;
default:
image_type = CL_MEM_OBJECT_IMAGE2D;
}
if ((error = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE,
image_type, 128, formatList,
&formatCount ))) {
return error;
}
// Check if the RGB 101010 format is supported
for( i = 0; i < formatCount; i++ )
{
if( formatList[ i ].image_channel_data_type == CL_UNORM_INT_101010 )
{
return 1;
}
}
return 0;
}

View File

@@ -0,0 +1,446 @@
//
// 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 "../../test_common/harness/compat.h"
#include <stdio.h>
#include <string.h>
#if !defined (__APPLE__)
#include <CL/cl.h>
#endif
#include "procs.h"
#include "../../test_common/gl/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 = clCreateCommandQueueWithProperties( sCurrentContext, device, 0, &error ); \
test_error( error, "Unable to create command queue" ); \
return fn( device, sCurrentContext, realQueue, numElements ); \
}
// buffers:
TEST_FN_REDIRECTOR( test_buffers )
TEST_FN_REDIRECTOR( test_buffers_getinfo )
// 1D images:
TEST_FN_REDIRECTOR( test_images_read_1D )
TEST_FN_REDIRECTOR( test_images_write_1D )
TEST_FN_REDIRECTOR( test_images_1D_getinfo )
// 1D image arrays:
TEST_FN_REDIRECTOR( test_images_read_1Darray )
TEST_FN_REDIRECTOR( test_images_write_1Darray )
TEST_FN_REDIRECTOR( test_images_1Darray_getinfo )
// 2D images:
TEST_FN_REDIRECTOR( test_images_read_2D )
TEST_FN_REDIRECTOR( test_images_read_cube )
TEST_FN_REDIRECTOR( test_images_write )
TEST_FN_REDIRECTOR( test_images_write_cube )
TEST_FN_REDIRECTOR( test_images_2D_getinfo )
TEST_FN_REDIRECTOR( test_images_cube_getinfo )
// 2D image arrays:
TEST_FN_REDIRECTOR( test_images_read_2Darray )
TEST_FN_REDIRECTOR( test_images_write_2Darray )
TEST_FN_REDIRECTOR( test_images_2Darray_getinfo )
// 3D images:
TEST_FN_REDIRECTOR( test_images_read_3D )
TEST_FN_REDIRECTOR( test_images_write_3D )
TEST_FN_REDIRECTOR( test_images_3D_getinfo )
#ifdef GL_VERSION_3_2
TEST_FN_REDIRECTOR( test_images_read_texturebuffer )
TEST_FN_REDIRECTOR( test_images_write_texturebuffer )
TEST_FN_REDIRECTOR( test_images_texturebuffer_getinfo )
// depth textures
TEST_FN_REDIRECTOR( test_images_read_2D_depth )
TEST_FN_REDIRECTOR( test_images_write_2D_depth )
TEST_FN_REDIRECTOR( test_images_read_2Darray_depth )
TEST_FN_REDIRECTOR( test_images_write_2Darray_depth )
TEST_FN_REDIRECTOR( test_images_read_2D_multisample )
TEST_FN_REDIRECTOR( test_images_read_2Darray_multisample )
TEST_FN_REDIRECTOR( test_image_methods_depth );
TEST_FN_REDIRECTOR( test_image_methods_multisample );
#endif
// Renderbuffer-backed images:
TEST_FN_REDIRECTOR( test_renderbuffer_read )
TEST_FN_REDIRECTOR( test_renderbuffer_write )
TEST_FN_REDIRECTOR( test_renderbuffer_getinfo )
TEST_FN_REDIRECTOR( test_fence_sync )
basefn basefn_list[] = {
TEST_FN_REDIRECT( test_buffers ),
TEST_FN_REDIRECT( test_buffers_getinfo ),
TEST_FN_REDIRECT( test_images_read_1D ),
TEST_FN_REDIRECT( test_images_write_1D ),
TEST_FN_REDIRECT( test_images_1D_getinfo ),
TEST_FN_REDIRECT( test_images_read_1Darray ),
TEST_FN_REDIRECT( test_images_write_1Darray ),
TEST_FN_REDIRECT( test_images_1Darray_getinfo ),
TEST_FN_REDIRECT( test_images_read_2D ),
TEST_FN_REDIRECT( test_images_write ),
TEST_FN_REDIRECT( test_images_2D_getinfo ),
TEST_FN_REDIRECT( test_images_read_cube ),
TEST_FN_REDIRECT( test_images_write_cube ),
TEST_FN_REDIRECT( test_images_cube_getinfo ),
TEST_FN_REDIRECT( test_images_read_2Darray ),
TEST_FN_REDIRECT( test_images_write_2Darray),
TEST_FN_REDIRECT( test_images_2Darray_getinfo ),
TEST_FN_REDIRECT( test_images_read_3D ),
TEST_FN_REDIRECT( test_images_write_3D ),
TEST_FN_REDIRECT( test_images_3D_getinfo ),
TEST_FN_REDIRECT( test_renderbuffer_read ),
TEST_FN_REDIRECT( test_renderbuffer_write ),
TEST_FN_REDIRECT( test_renderbuffer_getinfo )
};
basefn basefn_list32[] = {
TEST_FN_REDIRECT( test_images_read_texturebuffer ),
TEST_FN_REDIRECT( test_images_write_texturebuffer ),
TEST_FN_REDIRECT( test_images_texturebuffer_getinfo ),
TEST_FN_REDIRECT( test_fence_sync ),
TEST_FN_REDIRECT( test_images_read_2D_depth ),
TEST_FN_REDIRECT( test_images_write_2D_depth ),
TEST_FN_REDIRECT( test_images_read_2Darray_depth ),
TEST_FN_REDIRECT( test_images_write_2Darray_depth ),
TEST_FN_REDIRECT( test_images_read_2D_multisample ),
TEST_FN_REDIRECT( test_images_read_2Darray_multisample ),
TEST_FN_REDIRECT( test_image_methods_depth ),
TEST_FN_REDIRECT( test_image_methods_multisample)
};
const char *basefn_names[] = {
"buffers",
"buffers_getinfo",
"images_read_1D",
"images_write_1D",
"images_1D_getinfo",
"images_read_1Darray",
"images_write_1Darray",
"images_1Darray_getinfo",
"images_read", /* 2D */
"images_write",
"images_2D_getinfo",
"images_read_cube",
"images_write_cube",
"images_cube_getinfo",
"images_read_2Darray",
"images_write_2Darray",
"images_2Darray_getinfo",
"images_read_3D",
"images_write_3D",
"images_3D_getinfo",
"renderbuffer_read",
"renderbuffer_write",
"renderbuffer_getinfo",
};
const char *basefn_names32[] = {
"images_read_texturebuffer",
"images_write_texturebuffer",
"images_texturebuffer_getinfo",
"fence_sync",
"images_read_2D_depth",
"images_write_2D_depth",
"images_read_2D_array_depth",
"images_write_2D_array_depth",
"images_read_2D_multisample",
"images_read_2D_array_multisample",
"image_methods_depth",
"image_methods_multisample",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
ct_assert((sizeof(basefn_names32) / sizeof(basefn_names32[0])) == (sizeof(basefn_list32) / sizeof(basefn_list32[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int num_fns32 = sizeof(basefn_names32) / sizeof(char *);
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
bool gTestRounding = true;
int main(int argc, const char *argv[])
{
int error = 0;
int numErrors = 0;
test_start();
cl_device_type requestedDeviceType = CL_DEVICE_TYPE_DEFAULT;
checkDeviceTypeOverride(&requestedDeviceType);
/* Do we have a CPU/GPU specification? */
if( argc > 1 )
{
if( strcmp( argv[ argc - 1 ], "gpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_GPU" ) == 0 )
{
requestedDeviceType = CL_DEVICE_TYPE_GPU;
argc--;
}
else if( strcmp( argv[ argc - 1 ], "cpu" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_CPU" ) == 0 )
{
requestedDeviceType = CL_DEVICE_TYPE_CPU;
argc--;
}
else if( strcmp( argv[ argc - 1 ], "accelerator" ) == 0 || strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
{
requestedDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
argc--;
}
else if( strcmp( argv[ argc - 1 ], "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
{
requestedDeviceType = CL_DEVICE_TYPE_DEFAULT;
argc--;
}
}
if( argc > 1 && strcmp( argv[ 1 ], "-list" ) == 0 )
{
log_info( "Available 2.x tests:\n" );
for( int i = 0; i < num_fns; i++ )
log_info( "\t%s\n", basefn_names[ i ] );
log_info( "Available 3.2 tests:\n" );
for( int i = 0; i < num_fns32; 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.\n" );
log_info( "Use environment variables to specify desired device.\n" );
test_finish();
return 0;
}
// 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;++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();
return 0;
} else if ( supported == -1 ) {
log_error("Unable to setup the test or failed to determine if CL-GL interop is supported.\n");
test_finish();
return -1;
}
// Initialize function pointers.
error = init_clgl_ext();
if (error < 0) {
return error;
}
// 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();
return -1;
}
// 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();
return -1;
}
size_t numDevices = 0;
cl_device_id *deviceIDs;
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();
return -1;
}
deviceIDs = (cl_device_id *)malloc(numDevices);
if (deviceIDs == NULL) {
print_error( error, "malloc failed" );
test_finish();
return -1;
}
error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, numDevices, deviceIDs, NULL);
if( error != CL_SUCCESS ) {
print_error( error, "Unable to get device list from context" );
test_finish();
return -1;
}
numDevices /= sizeof(cl_device_id);
if (numDevices < 1) {
log_error("No devices found.\n");
test_finish();
return -1;
}
// 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();
return -1;
}
// 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_fns, basefn_list, basefn_names, true, 0, 1024 );
if( error != 0 )
break;
}
numErrors += error;
// Clean-up.
free(deviceIDs);
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();
return -1;
}
// 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();
return -1;
}
size_t numDevices = 0;
cl_device_id *deviceIDs;
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();
return -1;
}
deviceIDs = (cl_device_id *)malloc(numDevices);
if (deviceIDs == NULL) {
print_error( error, "malloc failed" );
test_finish();
return -1;
}
error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, numDevices, deviceIDs, NULL);
if( error != CL_SUCCESS ) {
print_error( error, "Unable to get device list from context" );
test_finish();
return -1;
}
numDevices /= sizeof(cl_device_id);
if (numDevices < 1) {
log_error("No devices found.\n");
test_finish();
return -1;
}
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();
return -1;
}
// 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;
}
numErrors += error;
// Clean-up.
free(deviceIDs);
clReleaseContext( sCurrentContext );
delete glEnv;
}
//All done.
return numErrors;
}

140
test_conformance/gl/procs.h Normal file
View File

@@ -0,0 +1,140 @@
//
// 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"
#pragma mark -
#pragma Misc tests
extern int test_buffers( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_fence_sync( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
#pragma mark -
#pragma mark Tead tests
extern int test_images_read_2D( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_read_1D( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_read_texturebuffer( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_read_1Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_read_2Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_read_cube( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_read_3D( 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 );
#pragma mark -
#pragma mark Write tests
// 2D tests are the ones with no suffix:
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_write( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
// Here are the rest:
extern int test_images_write_1D( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_write_texturebuffer( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_write_1Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_write_2Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
extern int test_images_write_3D( cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements );
#pragma mark -
#pragma mark Get info test entry points
extern int test_buffers_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_1D_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_texturebuffer_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_1Darray_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_2D_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_2Darray_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_cube_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_3D_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_read_2D_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_write_2D_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_read_2Darray_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int );
extern int test_images_write_2Darray_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_read_2D_multisample( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );
extern int test_images_read_2Darray_multisample( cl_device_id device, cl_context context,
cl_command_queue queue, int );
extern int test_image_methods_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int );
extern int test_image_methods_multisample( cl_device_id device, cl_context context,
cl_command_queue queue, int );
extern int test_renderbuffer_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements );

View File

@@ -0,0 +1,65 @@
//
// 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 "../../test_common/harness/compat.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined (__APPLE__)
#include <CL/cl.h>
#include "../../test_common/gl/gl_headers.h"
#include <CL/cl_gl.h>
#else
#include "../../test_common/gl/gl_headers.h"
#endif
#include "../../test_common/harness/imageHelpers.h"
#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"
#include "../../test_common/gl/helpers.h"
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, size_t channelNum, GLenum glDataType = 0);
extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t typeSize );
extern int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t typeSize );
extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum, size_t channelNum );
extern int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum, size_t channelNum );
extern int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t sampleNum );
extern int validate_float_results_rgb_101010( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t sampleNum );
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,357 @@
//
// 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/conversions.h"
#include "../../test_common/harness/typeWrappers.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 = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_ONLY );
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;
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);
for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ )
{
for( index = 0; vecSizes[ index ] != 0; index++ )
{
// 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 );
for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ )
{
for( index = 0; vecSizes[ index ] != 0; index++ )
{
// 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,730 @@
//
// 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/gl/setup.h"
#include "../../test_common/harness/genericThread.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#if !defined(_WIN32) && !defined(__ANDROID__)
#include <GL/glx.h>
#endif
#endif
#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;
#ifndef APIENTRY
#define APIENTRY
#endif
typedef GLsync (APIENTRY *glFenceSyncPtr)(GLenum condition,GLbitfield flags);
glFenceSyncPtr glFenceSyncFunc;
typedef bool (APIENTRY *glIsSyncPtr)(GLsync sync);
glIsSyncPtr glIsSyncFunc;
typedef void (APIENTRY *glDeleteSyncPtr)(GLsync sync);
glDeleteSyncPtr glDeleteSyncFunc;
typedef GLenum (APIENTRY *glClientWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout);
glClientWaitSyncPtr glClientWaitSyncFunc;
typedef void (APIENTRY *glWaitSyncPtr)(GLsync sync,GLbitfield flags,GLuint64 timeout);
glWaitSyncPtr glWaitSyncFunc;
typedef void (APIENTRY *glGetInteger64vPtr)(GLenum pname, GLint64 *params);
glGetInteger64vPtr glGetInteger64vFunc;
typedef void (APIENTRY *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 =
"#version 150\n"
"uniform mat4 projMatrix;\n"
"in vec4 inPosition;\n"
"in vec4 inColor;\n"
"out vec4 vertColor;\n"
"void main (void) {\n"
" gl_Position = projMatrix*inPosition;\n"
" vertColor = inColor;\n"
"}\n";
//Passthrough FragmentShader
static const char *fragmentshader =
"#version 150\n"
"in vec4 vertColor;\n"
"out vec4 outColor;\n"
"void main (void) {\n"
" outColor = vertColor;\n"
"}\n";
GLuint createShaderProgram(GLint *posLoc, GLint *colLoc)
{
GLint logLength, status;
GLuint program = glCreateProgram();
GLuint vpShader;
vpShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vpShader, 1, (const GLchar **)&vertexshader, 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);
}
glGetShaderiv(vpShader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
log_error("Failed to compile vtx shader:\n");
return 0;
}
glAttachShader(program, vpShader);
GLuint fpShader;
fpShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fpShader, 1, (const GLchar **)&fragmentshader, NULL);
glCompileShader(fpShader);
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;
}
*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;
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;
}
// Ask OpenCL for the platforms. Warn if more than one platform found,
// since this might not be the platform we want. By default, we simply
// use the first returned platform.
cl_uint nplatforms;
cl_platform_id platform;
clGetPlatformIDs(0, NULL, &nplatforms);
clGetPlatformIDs(1, &platform, NULL);
if (nplatforms > 1) {
log_info("clGetPlatformIDs returned multiple values. This is not "
"an error, but might result in obtaining incorrect function "
"pointers if you do not want the first returned platform.\n");
// Show them the platform name, in case it is a problem.
size_t size;
char *name;
clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size);
name = (char*)malloc(size);
clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL);
log_info("Using platform with name: %s \n", name);
free(name);
}
clCreateEventFromGLsyncKHR_ptr = (clCreateEventFromGLsyncKHR_fn)clGetExtensionFunctionAddressForPlatform(platform, "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, "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
#ifdef _WIN32
HDC hdc = wglGetCurrentDC();
HGLRC hglrc = wglGetCurrentContext();
#else
Display* dpy = glXGetCurrentDisplay();
GLXDrawable drawable = glXGetCurrentDrawable();
GLXContext ctx = glXGetCurrentContext();
#endif
#endif
InitSyncFns();
#endif
#ifdef __APPLE__
CGLSetVirtualScreen(CGLGetCurrentContext(), rend_vs);
#else
#ifdef _WIN32
wglMakeCurrent(hdc, hglrc);
#else
glXMakeCurrent(dpy, drawable, ctx);
#endif
#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_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
&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 );
// Now that the requisite objects are bound, we can attempt program
// validation:
glValidateProgram(shaderprogram);
GLint logLength, status;
glGetProgramiv(shaderprogram, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(shaderprogram, logLength, &logLength, log);
log_info("Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(shaderprogram, GL_VALIDATE_STATUS, &status);
if (status == 0)
{
log_error("Failed to validate program\n");
return 0;
}
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 )
{
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();
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();
}
else
glFinish();
}
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
#ifdef _WIN32
wglMakeCurrent(hdc, hglrc);
#else
glXMakeCurrent(dpy, drawable, ctx);
#endif
#endif
// Grab the contents of the final framebuffer
BufferOwningPtr<char> resultData( ReadGLRenderbuffer( glFramebuffer, glRenderbuffer,
GL_COLOR_ATTACHMENT0_EXT,
GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 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;
}
}
}
}
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
size_t device_cb;
cl_int err = clGetContextInfo( context, CL_CONTEXT_DEVICES, 0, NULL, &device_cb);
if( err != CL_SUCCESS )
{
print_error( err, "Unable to get device count from context" );
test_finish();
return -1;
}
vs_count = (GLint)device_cb / sizeof(cl_device_id);
if (vs_count < 1) {
log_error("No devices found.\n");
return -1;
}
device_list = (cl_device_id *) malloc(device_cb);
err = clGetContextInfo( context, CL_CONTEXT_DEVICES, device_cb, device_list, NULL);
if( err != CL_SUCCESS ) {
free(device_list);
print_error( err, "Unable to get device list from context" );
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,405 @@
//
// 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 "common.h"
#include <algorithm>
using namespace std;
typedef struct image_kernel_data
{
cl_int width;
cl_int height;
cl_int depth;
cl_int arraySize;
cl_int widthDim;
cl_int heightDim;
cl_int channelType;
cl_int channelOrder;
cl_int expectedChannelType;
cl_int expectedChannelOrder;
cl_int numSamples;
};
static const char *methodTestKernelPattern =
"typedef struct {\n"
" int width;\n"
" int height;\n"
" int depth;\n"
" int arraySize;\n"
" int widthDim;\n"
" int heightDim;\n"
" int channelType;\n"
" int channelOrder;\n"
" int expectedChannelType;\n"
" int expectedChannelOrder;\n"
" int numSamples;\n"
" } image_kernel_data;\n"
"__kernel void sample_kernel( read_only %s input, __global image_kernel_data *outData )\n"
"{\n"
"%s%s%s%s%s%s%s%s%s%s%s"
"}\n";
static const char *arraySizeKernelLine =
" outData->arraySize = get_image_array_size( input );\n";
static const char *imageWidthKernelLine =
" outData->width = get_image_width( input );\n";
static const char *imageHeightKernelLine =
" outData->height = get_image_height( input );\n";
static const char *imageDimKernelLine =
" int2 dim = get_image_dim( input );\n";
static const char *imageWidthDimKernelLine =
" outData->widthDim = dim.x;\n";
static const char *imageHeightDimKernelLine =
" outData->heightDim = dim.y;\n";
static const char *channelTypeKernelLine =
" outData->channelType = get_image_channel_data_type( input );\n";
static const char *channelTypeConstLine =
" outData->expectedChannelType = CLK_%s;\n";
static const char *channelOrderKernelLine =
" outData->channelOrder = get_image_channel_order( input );\n";
static const char *channelOrderConstLine =
" outData->expectedChannelOrder = CLK_%s;\n";
static const char *numSamplesKernelLine =
" outData->numSamples = get_image_num_samples( input );\n";
static int verify(cl_int input, cl_int kernelOutput, const char * description)
{
if( kernelOutput != input )
{
log_error( "ERROR: %s did not validate (expected %d, got %d)\n", description, input, kernelOutput);
return -1;
}
return 0;
}
extern int supportsMsaa(cl_context context, bool* supports_msaa);
extern int supportsDepth(cl_context context, bool* supports_depth);
int test_image_format_methods( cl_device_id device, cl_context context, cl_command_queue queue,
size_t width, size_t height, size_t arraySize, size_t samples,
GLenum target, format format, MTdata d )
{
int error, result=0;
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper image, outDataBuffer;
char programSrc[ 10240 ];
image_kernel_data outKernelData;
#ifdef GL_VERSION_3_2
if (get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE ||
get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
{
bool supports_msaa;
error = supportsMsaa(context, &supports_msaa);
if( error != 0 ) return error;
if (!supports_msaa) return 0;
}
if (format.formattype == GL_DEPTH_COMPONENT ||
format.formattype == GL_DEPTH_STENCIL)
{
bool supports_depth;
error = supportsDepth(context, &supports_depth);
if( error != 0 ) return error;
if (!supports_depth) return 0;
}
#endif
DetectFloatToHalfRoundingMode(queue);
glTextureWrapper glTexture;
switch (get_base_gl_target(target)) {
case GL_TEXTURE_2D:
CreateGLTexture2D( width, height, target,
format.formattype, format.internal, format.datatype,
format.type, &glTexture, &error, false, d );
break;
case GL_TEXTURE_2D_ARRAY:
CreateGLTexture2DArray( width, height, arraySize, target,
format.formattype, format.internal, format.datatype,
format.type, &glTexture, &error, false, d );
break;
case GL_TEXTURE_2D_MULTISAMPLE:
CreateGLTexture2DMultisample( width, height, samples, target,
format.formattype, format.internal, format.datatype,
format.type, &glTexture, &error, false, d, false);
break;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
CreateGLTexture2DArrayMultisample( width, height, arraySize, samples, target,
format.formattype, format.internal, format.datatype,
format.type, &glTexture, &error, false, d, false);
break;
default:
log_error("Unsupported GL tex target (%s) passed to write test: "
"%s (%s):%d", GetGLTargetName(target), __FUNCTION__,
__FILE__, __LINE__);
}
// Check to see if the texture could not be created for some other reason like
// GL_FRAMEBUFFER_UNSUPPORTED
if (error == GL_FRAMEBUFFER_UNSUPPORTED) {
return 0;
}
// Construct testing source
log_info( " - Creating image %d by %d...\n", width, height );
// Create a CL image from the supplied GL texture
image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY,
target, 0, glTexture, &error );
if ( error != CL_SUCCESS ) {
print_error( error, "Unable to create CL image from GL texture" );
GLint fmt;
glGetTexLevelParameteriv( target, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was base format %s and internal "
"format %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) );
return error;
}
cl_image_format imageFormat;
error = clGetImageInfo (image, CL_IMAGE_FORMAT,
sizeof(imageFormat), &imageFormat, NULL);
test_error(error, "Failed to get image format");
const char * imageType = 0;
bool doArraySize = false;
bool doImageWidth = false;
bool doImageHeight = false;
bool doImageChannelDataType = false;
bool doImageChannelOrder = false;
bool doImageDim = false;
bool doNumSamples = false;
switch(target) {
case GL_TEXTURE_2D:
imageType = "image2d_depth_t";
doImageWidth = true;
doImageHeight = true;
doImageChannelDataType = true;
doImageChannelOrder = true;
doImageDim = true;
break;
case GL_TEXTURE_2D_ARRAY:
imageType = "image2d_array_depth_t";
doImageWidth = true;
doImageHeight = true;
doArraySize = true;
doImageChannelDataType = true;
doImageChannelOrder = true;
doImageDim = true;
doArraySize = true;
break;
case GL_TEXTURE_2D_MULTISAMPLE:
doNumSamples = true;
if(format.formattype == GL_DEPTH_COMPONENT) {
doImageWidth = true;
imageType = "image2d_msaa_depth_t";
} else {
imageType = "image2d_msaa_t";
}
break;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
if(format.formattype == GL_DEPTH_COMPONENT) {
doImageWidth = true;
imageType = "image2d_msaa_array_depth_t";
} else {
imageType = "image2d_array_msaa_t";
}
break;
}
char channelTypeConstKernelLine[512] = {0};
char channelOrderConstKernelLine[512] = {0};
const char* channelTypeName=0;
const char* channelOrderName=0;
if(doImageChannelDataType) {
channelTypeName = GetChannelTypeName( imageFormat.image_channel_data_type );
if(channelTypeName && strlen(channelTypeName)) {
// replace CL_* with CLK_*
sprintf(channelTypeConstKernelLine, channelTypeConstLine, &channelTypeName[3]);
}
}
if(doImageChannelOrder) {
channelOrderName = GetChannelOrderName( imageFormat.image_channel_order );
if(channelOrderName && strlen(channelOrderName)) {
// replace CL_* with CLK_*
sprintf(channelOrderConstKernelLine, channelOrderConstLine, &channelOrderName[3]);
}
}
// Create a program to run against
sprintf( programSrc, methodTestKernelPattern,
imageType,
( doArraySize ) ? arraySizeKernelLine : "",
( doImageWidth ) ? imageWidthKernelLine : "",
( doImageHeight ) ? imageHeightKernelLine : "",
( doImageChannelDataType ) ? channelTypeKernelLine : "",
( doImageChannelDataType ) ? channelTypeConstKernelLine : "",
( doImageChannelOrder ) ? channelOrderKernelLine : "",
( doImageChannelOrder ) ? channelOrderConstKernelLine : "",
( doImageDim ) ? imageDimKernelLine : "",
( doImageDim && doImageWidth ) ? imageWidthDimKernelLine : "",
( doImageDim && doImageHeight ) ? imageHeightDimKernelLine : "",
( doNumSamples ) ? numSamplesKernelLine : "");
//log_info("-----------------------------------\n%s\n", programSrc);
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.\n");
const char *ptr = programSrc;
error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "sample_kernel" );
test_error( error, "Unable to create kernel to test against" );
// Create an output buffer
outDataBuffer = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof( outKernelData ), NULL, &error );
test_error( error, "Unable to create output buffer" );
// Set up arguments and run
error = clSetKernelArg( kernel, 0, sizeof( image ), &image );
test_error( error, "Unable to set kernel argument" );
error = clSetKernelArg( kernel, 1, sizeof( outDataBuffer ), &outDataBuffer );
test_error( error, "Unable to set kernel argument" );
// Flush and Acquire.
glFlush();
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &image, 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
size_t threads[1] = { 1 }, localThreads[1] = { 1 };
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
error = clEnqueueReadBuffer( queue, outDataBuffer, CL_TRUE, 0, sizeof( outKernelData ), &outKernelData, 0, NULL, NULL );
test_error( error, "Unable to read data buffer" );
// Verify the results now
if( doImageWidth )
result |= verify(width, outKernelData.width, "width");
if( doImageHeight)
result |= verify(height, outKernelData.height, "height");
if( doImageDim && doImageWidth )
result |= verify(width, outKernelData.widthDim, "width from get_image_dim");
if( doImageDim && doImageHeight )
result |= verify(height, outKernelData.heightDim, "height from get_image_dim");
if( doImageChannelDataType )
result |= verify(outKernelData.channelType, outKernelData.expectedChannelType, channelTypeName);
if( doImageChannelOrder )
result |= verify(outKernelData.channelOrder, outKernelData.expectedChannelOrder, channelOrderName);
if( doArraySize )
result |= verify(arraySize, outKernelData.arraySize, "array size");
if( doNumSamples )
result |= verify(samples, outKernelData.numSamples, "samples");
if(result) {
log_error("Test image methods failed");
}
clEventWrapper event;
error = (*clEnqueueReleaseGLObjects_ptr)( queue, 1, &image, 0, NULL, &event );
test_error(error, "clEnqueueReleaseGLObjects failed");
error = clWaitForEvents( 1, &event );
test_error(error, "clWaitForEvents failed");
return result;
}
int test_image_methods_depth( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ){
if (!is_extension_available(device, "cl_khr_gl_depth_images")) {
log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n");
return 0;
}
size_t pixelSize;
int result = 0;
GLenum depth_targets[] = {GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY};
size_t ntargets = sizeof(depth_targets) / sizeof(depth_targets[0]);
size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
const size_t nsizes = 5;
sizevec_t sizes[nsizes];
// Need to limit texture size according to GL device properties
GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, maxTextureLayers = 16, size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize);
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
size = min(maxTextureSize, maxTextureRectangleSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed );
}
for (size_t i = 0; i < nsizes; i++) {
for(size_t itarget = 0; itarget < ntargets; ++itarget) {
for(size_t iformat = 0; iformat < nformats; ++iformat)
result |= test_image_format_methods(device, context, queue, sizes[i].width, sizes[i].height, (depth_targets[itarget] == GL_TEXTURE_2D_ARRAY) ? sizes[i].depth: 1, 0,
depth_targets[itarget], depth_formats[iformat], seed );
}
}
return result;
}
int test_image_methods_multisample( cl_device_id device, cl_context context, cl_command_queue queue, int numElements ){
if (!is_extension_available(device, "cl_khr_gl_msaa_sharing")) {
log_info("Test not run because 'cl_khr_gl_msaa_sharing' extension is not supported by the tested device\n");
return 0;
}
size_t pixelSize;
int result = 0;
GLenum targets[] = {GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY};
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 5;
sizevec_t sizes[nsizes];
GLint maxTextureLayers = 16, maxTextureSize = 4096;
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed );
}
glEnable(GL_MULTISAMPLE);
for (size_t i = 0; i < nsizes; i++) {
for(size_t itarget = 0; itarget < ntargets; ++itarget) {
for(size_t iformat = 0; iformat < nformats; ++iformat) {
GLint samples = get_gl_max_samples(targets[itarget], common_formats[iformat].internal);
result |= test_image_format_methods(device, context, queue, sizes[i].width, sizes[i].height, (targets[ntargets] == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? sizes[i].depth: 1,
samples, targets[itarget], common_formats[iformat], seed );
}
}
}
return result;
}

View File

@@ -0,0 +1,141 @@
//
// 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 "common.h"
#include "testBase.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
void calc_test_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
GLint maxTextureSize = 4096, maxTextureBufferSize = 4096, size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize);
size = min(maxTextureSize, maxTextureBufferSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].height = 1;
sizes[i].depth = 1;
}
}
int test_images_read_1D( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_1D };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_test_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
int test_images_write_1D( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_1D };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_test_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
int test_images_1D_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_1D };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_test_size_descriptors(sizes, nsizes);
return test_images_get_info_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
int test_images_read_texturebuffer( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_BUFFER };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_test_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
int test_images_write_texturebuffer( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_BUFFER };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_test_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
int test_images_texturebuffer_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_BUFFER };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_test_size_descriptors(sizes, nsizes);
return test_images_get_info_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}

View File

@@ -0,0 +1,90 @@
//
// 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 "common.h"
#include "testBase.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
void calc_1D_array_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
GLint maxTextureLayers = 16, maxTextureSize = 4096;
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed );
sizes[i].depth = 1;
}
}
int test_images_read_1Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_1D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_1D_array_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
int test_images_write_1Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_1D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_1D_array_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
int test_images_1Darray_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_1D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_1D_array_size_descriptors(sizes, nsizes);
return test_images_get_info_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}

View File

@@ -0,0 +1,190 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "common.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
extern "C" { extern cl_uint gRandomSeed; }
#pragma mark -
#pragma mark _2D read tests
void calc_2D_test_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
// Need to limit texture size according to GL device properties
GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize);
size = min(maxTextureSize, maxTextureRectangleSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].depth = 1;
}
}
void calc_cube_test_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
// Need to limit texture size according to GL device properties
GLint maxQubeMapSize = 4096;
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxQubeMapSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = sizes[i].height = random_in_range( 2, min(maxQubeMapSize, 1<<(i+4)), seed );
sizes[i].depth = 1;
}
}
int test_images_read_2D( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_2D_test_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
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 };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_cube_test_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
#pragma mark -
#pragma mark _2D write tests
#include "common.h"
int test_images_write( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_2D_test_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
int test_images_write_cube( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
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
};
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_cube_test_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
#pragma mark -
#pragma mark _2D get info tests
int test_images_2D_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_2D_test_size_descriptors(sizes, nsizes);
return test_images_get_info_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
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
};
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_cube_test_size_descriptors(sizes, nsizes);
return test_images_get_info_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}

View File

@@ -0,0 +1,93 @@
//
// 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 "common.h"
#include "testBase.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
void calc_2D_array_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
GLint maxTextureLayers = 16, maxTextureSize = 4096;
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed );
}
}
int test_images_read_2Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_2D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_2D_array_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
int test_images_write_2Darray( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
// FIXME: Query for 2D image array write support.
GLenum targets[] = { GL_TEXTURE_2D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_2D_array_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
int test_images_2Darray_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int )
{
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
GLenum targets[] = { GL_TEXTURE_2D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_2D_array_size_descriptors(sizes, nsizes);
return test_images_get_info_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}

View File

@@ -0,0 +1,109 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "common.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
extern "C" { extern cl_uint gRandomSeed; };
#pragma mark -
#pragma mark _3D read test
void calc_3D_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
GLint maxTextureSize = 2048;
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxTextureSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].depth = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
}
}
int test_images_read_3D( cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_3D };
size_t ntargets = 1;
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_3D_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}
#pragma mark -
#pragma marm _3D write test
int test_images_write_3D( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
// TODO: Perhaps the expected behavior is to FAIL if 3D images are
// unsupported?
if (!is_extension_available(device, "cl_khr_3d_image_writes")) {
log_info("This device does not support 3D image writes. Skipping test.\n");
return 0;
}
GLenum targets[] = { GL_TEXTURE_3D };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_3D_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes );
}
#pragma mark -
#pragma mark _3D get info test
int test_images_3D_getinfo( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
GLenum targets[] = { GL_TEXTURE_3D };
size_t ntargets = 1;
size_t nformats = sizeof(common_formats) / sizeof(common_formats[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_3D_size_descriptors(sizes, nsizes);
return test_images_get_info_common(device, context, queue, common_formats,
nformats, targets, ntargets, sizes, nsizes);
}

View File

@@ -0,0 +1,162 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "common.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
extern "C" { extern cl_uint gRandomSeed; }
#pragma mark -
#pragma mark _2D depth read tests
void calc_depth_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit texture size according to GL device properties
GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize);
size = min(maxTextureSize, maxTextureRectangleSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].depth = 1;
}
}
void calc_depth_array_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit texture size according to GL device properties
GLint maxTextureSize = 4096, maxTextureRectangleSize = 4096, maxTextureLayers = 16, size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &maxTextureRectangleSize);
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
size = min(maxTextureSize, maxTextureRectangleSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(size, 1<<(i+4)), seed );
sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed );
}
}
int test_images_read_2D_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
if (!is_extension_available(device, "cl_khr_gl_depth_images")) {
log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n");
return 0;
}
RandomSeed seed( gRandomSeed );
GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_depth_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, depth_formats,
nformats, targets, ntargets, sizes, nsizes);
}
#pragma mark -
#pragma mark _2D depth write tests
int test_images_write_2D_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
if (!is_extension_available(device, "cl_khr_gl_depth_images")) {
log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n");
return 0;
}
GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_EXT };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_depth_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, depth_formats,
nformats, targets, ntargets, sizes, nsizes );
}
int test_images_read_2Darray_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int )
{
if (!is_extension_available(device, "cl_khr_gl_depth_images")) {
log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n");
return 0;
}
size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
GLenum targets[] = { GL_TEXTURE_2D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_depth_array_size_descriptors(sizes, nsizes);
return test_images_read_common(device, context, queue, depth_formats,
nformats, targets, ntargets, sizes, nsizes);
}
int test_images_write_2Darray_depth( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
if (!is_extension_available(device, "cl_khr_gl_depth_images")) {
log_info("Test not run because 'cl_khr_gl_depth_images' extension is not supported by the tested device\n");
return 0;
}
// FIXME: Query for 2D image array write support.
GLenum targets[] = { GL_TEXTURE_2D_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
size_t nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
const size_t nsizes = 6;
sizevec_t sizes[nsizes];
calc_depth_array_size_descriptors(sizes, nsizes);
return test_images_write_common( device, context, queue, depth_formats,
nformats, targets, ntargets, sizes, nsizes );
}

View File

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

View File

@@ -0,0 +1,118 @@
//
// 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 "common.h"
#include "testBase.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#include <algorithm>
using namespace std;
void calc_2D_multisample_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit texture size according to GL device properties
GLint maxTextureSize = 4096;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].depth = 1;
}
}
void calc_2D_array_multisample_size_descriptors(sizevec_t* sizes, size_t nsizes)
{
// Need to limit array size according to GL device properties
GLint maxTextureLayers = 16, maxTextureSize = 4096;
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
RandomSeed seed( gRandomSeed );
// Generate some random sizes (within reasonable ranges)
for (size_t i = 0; i < nsizes; i++) {
sizes[i].width = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].height = random_in_range( 2, min(maxTextureSize, 1<<(i+4)), seed );
sizes[i].depth = random_in_range( 2, min(maxTextureLayers, 1<<(i+4)), seed );
}
}
int test_images_read_2D_multisample( cl_device_id device, cl_context context,
cl_command_queue queue, int numElements )
{
if (!is_extension_available(device, "cl_khr_gl_msaa_sharing")) {
log_info("Test not run because 'cl_khr_gl_msaa_sharing' extension is not supported by the tested device\n");
return 0;
}
glEnable(GL_MULTISAMPLE);
const size_t nsizes = 8;
sizevec_t sizes[nsizes];
calc_2D_multisample_size_descriptors(sizes, nsizes);
size_t nformats;
GLenum targets[] = { GL_TEXTURE_2D_MULTISAMPLE };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
nformats = sizeof(common_formats) / sizeof(common_formats[0]);
int ret_common = test_images_read_common(device, context, queue, common_formats, nformats, targets, ntargets, sizes, nsizes);
nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
int ret_depth = test_images_read_common(device, context, queue, depth_formats, nformats, targets, ntargets, sizes, nsizes);
return (ret_common) ? ret_common : ret_depth;
}
int test_images_read_2Darray_multisample( cl_device_id device, cl_context context,
cl_command_queue queue, int )
{
if (!is_extension_available(device, "cl_khr_gl_msaa_sharing")) {
log_info("Test not run because 'cl_khr_gl_msaa_sharing' extension is not supported by the tested device\n");
return 0;
}
glEnable(GL_MULTISAMPLE);
const size_t nsizes = 4;
sizevec_t sizes[nsizes];
calc_2D_array_multisample_size_descriptors(sizes, nsizes);
size_t nformats;
GLenum targets[] = { GL_TEXTURE_2D_MULTISAMPLE_ARRAY };
size_t ntargets = sizeof(targets) / sizeof(targets[0]);
nformats = sizeof(common_formats) / sizeof(common_formats[0]);
int ret_common = test_images_read_common(device, context, queue, common_formats, nformats, targets, ntargets, sizes, nsizes);
nformats = sizeof(depth_formats) / sizeof(depth_formats[0]);
int ret_depth = test_images_read_common(device, context, queue, depth_formats, nformats, targets, ntargets, sizes, nsizes);
return (ret_common) ? ret_common : ret_depth;
}

View File

@@ -0,0 +1,736 @@
//
// 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 "common.h"
#include "testBase.h"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
extern "C" { extern cl_uint gRandomSeed; };
extern int supportsHalf(cl_context context, bool* supports_half);
extern int supportsMsaa(cl_context context, bool* supports_msaa);
extern int supportsDepth(cl_context context, bool* supports_depth);
static const char *kernelpattern_image_read_1d =
"__kernel void sample_test( read_only image1d_t source, sampler_t sampler, __global %s4 *results )\n"
"{\n"
" int offset = get_global_id(0);\n"
" results[ offset ] = read_image%s( source, sampler, offset );\n"
"}\n";
static const char *kernelpattern_image_read_1d_buffer =
"__kernel void sample_test( read_only image1d_buffer_t source, sampler_t sampler, __global %s4 *results )\n"
"{\n"
" int offset = get_global_id(0);\n"
" results[ offset ] = read_image%s( source, offset );\n"
"}\n";
static const char *kernelpattern_image_read_1darray =
"__kernel void sample_test( read_only image1d_array_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 *kernelpattern_image_read_2d =
"__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 *kernelpattern_image_read_2darray =
"__kernel void sample_test( read_only image2d_array_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 const char *kernelpattern_image_read_3d =
"__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 const char *kernelpattern_image_read_2d_depth =
"__kernel void sample_test( read_only image2d_depth_t source, sampler_t sampler, __global %s *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 *kernelpattern_image_read_2darray_depth =
"__kernel void sample_test( read_only image2d_array_depth_t source, sampler_t sampler, __global %s *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 const char *kernelpattern_image_multisample_read_2d =
"__kernel void sample_test( read_only image2d_msaa_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 width = get_image_width( source );\n"
" int height = get_image_height( source );\n"
" int num_samples = get_image_num_samples( source );\n"
" for(size_t sample = 0; sample < num_samples; sample++ ) {\n"
" int offset = sample * width * height + tidY * width + tidX;\n"
" results[ offset ] = read_image%s( source, (int2)( tidX, tidY ), sample );\n"
" }\n"
"}\n";
static const char *kernelpattern_image_multisample_read_2d_depth =
"__kernel void sample_test( read_only image2d_msaa_depth_t source, sampler_t sampler, __global %s *results )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int tidY = get_global_id(1);\n"
" int width = get_image_width( source );\n"
" int height = get_image_height( source );\n"
" int num_samples = get_image_num_samples( source );\n"
" for(size_t sample = 0; sample < num_samples; sample++ ) {\n"
" int offset = sample * width * height + tidY * width + tidX;\n"
" results[ offset ] = read_image%s( source, (int2)( tidX, tidY ), sample );\n"
" }\n"
"}\n";
static const char *kernelpattern_image_multisample_read_2darray =
"__kernel void sample_test( read_only image2d_array_msaa_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 num_samples = get_image_num_samples( source );\n"
" int width = get_image_width( source );\n"
" int height = get_image_height( source );\n"
" int array_size = get_image_array_size( source );\n"
" for(size_t sample = 0; sample< num_samples; ++sample) {\n"
" int offset = (array_size * width * height) * sample + (width * height) * tidZ + tidY * width + tidX;\n"
" results[ offset ] = read_image%s( source, (int4)( tidX, tidY, tidZ, 1 ), sample );\n"
" }\n"
"}\n";
static const char *kernelpattern_image_multisample_read_2darray_depth =
"__kernel void sample_test( read_only image2d_array_msaa_depth_t source, sampler_t sampler, __global %s *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 num_samples = get_image_num_samples( source );\n"
" int width = get_image_width( source );\n"
" int height = get_image_height( source );\n"
" int array_size = get_image_array_size( source );\n"
" for(size_t sample = 0; sample < num_samples; ++sample) {\n"
" int offset = (array_size * width * height) * sample + (width * height) * tidZ + tidY * width + tidX;\n"
" results[ offset ] = read_image%s( source, (int4)( tidX, tidY, tidZ, 1 ), sample );\n"
" }\n"
"}\n";
static const char* get_appropriate_kernel_for_target(GLenum target, cl_channel_order channel_order) {
switch (get_base_gl_target(target)) {
case GL_TEXTURE_1D:
return kernelpattern_image_read_1d;
case GL_TEXTURE_BUFFER:
return kernelpattern_image_read_1d_buffer;
case GL_TEXTURE_1D_ARRAY:
return kernelpattern_image_read_1darray;
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_2D:
case GL_COLOR_ATTACHMENT0:
case GL_RENDERBUFFER:
case GL_TEXTURE_CUBE_MAP:
#ifdef GL_VERSION_3_2
if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL)
return kernelpattern_image_read_2d_depth;
#endif
return kernelpattern_image_read_2d;
case GL_TEXTURE_2D_ARRAY:
#ifdef GL_VERSION_3_2
if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL)
return kernelpattern_image_read_2darray_depth;
#endif
return kernelpattern_image_read_2darray;
case GL_TEXTURE_3D:
return kernelpattern_image_read_3d;
case GL_TEXTURE_2D_MULTISAMPLE:
#ifdef GL_VERSION_3_2
if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL)
return kernelpattern_image_multisample_read_2d_depth;
#endif
return kernelpattern_image_multisample_read_2d;
break;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
#ifdef GL_VERSION_3_2
if(channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL)
return kernelpattern_image_multisample_read_2darray_depth;
#endif
return kernelpattern_image_multisample_read_2darray;
break;
default:
log_error("Unsupported texture target (%s); cannot determine "
"appropriate kernel.", GetGLTargetName(target));
return NULL;
}
}
int test_cl_image_read( cl_context context, cl_command_queue queue,
GLenum gl_target, cl_mem image, size_t width, size_t height, size_t depth, size_t sampleNum,
cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer )
{
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper streams[ 2 ];
int error;
char kernelSource[2048];
char *programPtr;
// Use the image created from the GL texture.
streams[ 0 ] = image;
// 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" );
// Determine the number of samples
cl_uint samples = 0;
error = clGetImageInfo( streams[ 0 ], CL_IMAGE_NUM_SAMPLES, sizeof( samples ), &samples, NULL );
test_error( error, "Unable to get CL_IMAGE_NUM_SAMPLES" );
// Create the source
*outType = get_read_kernel_type( outFormat );
size_t channelSize = get_explicit_type_size( *outType );
const char* source = get_appropriate_kernel_for_target(gl_target, outFormat->image_channel_order);
sprintf( kernelSource, source, get_explicit_type_name( *outType ),
get_kernel_suffix( outFormat ) );
programPtr = kernelSource;
if( create_single_kernel_helper( context, &program, &kernel, 1,
(const char **)&programPtr, "sample_test" ) )
{
return -1;
}
// Create a vanilla output buffer
cl_device_id device;
error = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE, sizeof(device), &device, NULL);
test_error( error, "Unable to get queue device" );
cl_ulong maxAllocSize = 0;
error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
test_error( error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE" );
size_t buffer_bytes = channelSize * get_channel_order_channel_count(outFormat->image_channel_order) * width * height * depth * sampleNum;
if (buffer_bytes > maxAllocSize) {
log_info("Output buffer size %d is too large for device (max alloc size %d) Skipping...\n",
(int)buffer_bytes, (int)maxAllocSize);
return 1;
}
streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, buffer_bytes, NULL, &error );
test_error( error, "Unable to create output buffer" );
/* Assign streams and execute */
cl_sampler_properties properties[] = {
CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE,
CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE,
CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST,
0 };
clSamplerWrapper sampler = clCreateSamplerWithProperties( context, properties, &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" );
glFinish();
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &streams[ 0 ], 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
// The ND range we use is a function of the dimensionality of the image.
size_t global_range[3] = { width, height, depth };
size_t *local_range = NULL;
int ndim = 1;
switch (get_base_gl_target(gl_target)) {
case GL_TEXTURE_1D:
case GL_TEXTURE_BUFFER:
ndim = 1;
break;
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_2D:
case GL_TEXTURE_1D_ARRAY:
case GL_COLOR_ATTACHMENT0:
case GL_RENDERBUFFER:
case GL_TEXTURE_CUBE_MAP:
ndim = 2;
break;
case GL_TEXTURE_3D:
case GL_TEXTURE_2D_ARRAY:
#ifdef GL_VERSION_3_2
case GL_TEXTURE_2D_MULTISAMPLE:
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
ndim = 3;
break;
#endif
default:
log_error("Test error: Unsupported texture target.\n");
return 1;
}
// 2D and 3D images have a special way to set the local size (legacy).
// Otherwise, we let CL select by leaving local_range as NULL.
if (gl_target == GL_TEXTURE_2D) {
local_range = (size_t*)malloc(sizeof(size_t) * ndim);
get_max_common_2D_work_group_size( context, kernel, global_range, local_range );
} else if (gl_target == GL_TEXTURE_3D) {
local_range = (size_t*)malloc(sizeof(size_t) * ndim);
get_max_common_3D_work_group_size( context, kernel, global_range, local_range );
}
error = clEnqueueNDRangeKernel( queue, kernel, ndim, NULL, global_range,
local_range, 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 * get_channel_order_channel_count(outFormat->image_channel_order) * width * height * depth * sampleNum] );
error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0,
channelSize * get_channel_order_channel_count(outFormat->image_channel_order) * width * height * depth * sampleNum, *outResultBuffer, 0, NULL, NULL );
test_error( error, "Unable to read output CL buffer!" );
// free the ranges
if (local_range) free(local_range);
return 0;
}
static int test_image_read( cl_context context, cl_command_queue queue,
GLenum target, GLuint globj, size_t width, size_t height, size_t depth, size_t sampleNum,
cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer )
{
int error;
// Create a CL image from the supplied GL texture or renderbuffer.
cl_mem image;
if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) {
image = (*clCreateFromGLRenderbuffer_ptr)( context, CL_MEM_READ_ONLY, globj, &error );
} else {
image = (*clCreateFromGLTexture_ptr)( context, CL_MEM_READ_ONLY,
target, 0, globj, &error );
}
if( error != CL_SUCCESS ) {
if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) {
print_error( error, "Unable to create CL image from GL renderbuffer" );
} else {
print_error( error, "Unable to create CL image from GL texture" );
GLint fmt;
glGetTexLevelParameteriv( target, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was base format %s and internal "
"format %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) );
}
return error;
}
return test_cl_image_read( context, queue, target, image,
width, height, depth, sampleNum, outFormat, outType, outResultBuffer );
}
static int test_image_format_read(
cl_context context, cl_command_queue queue,
size_t width, size_t height, size_t depth,
GLenum target, struct format* fmt, MTdata data)
{
int error = 0;
// Determine the maximum number of supported samples
GLint samples = 1;
if (target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
samples = get_gl_max_samples(target, fmt->internal);
// If we're testing a half float format, then we need to determine the
// rounding mode of this machine. Punt if we fail to do so.
if( fmt->type == kHalf )
{
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
bool supports_half = false;
error = supportsHalf(context, &supports_half);
if( error != 0 )
return error;
if (!supports_half) return 0;
}
#ifdef GL_VERSION_3_2
if (get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE ||
get_base_gl_target(target) == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
{
bool supports_msaa;
error = supportsMsaa(context, &supports_msaa);
if( error != 0 ) return error;
if (!supports_msaa) return 0;
}
if (fmt->formattype == GL_DEPTH_COMPONENT ||
fmt->formattype == GL_DEPTH_STENCIL)
{
bool supports_depth;
error = supportsDepth(context, &supports_depth);
if( error != 0 ) return error;
if (!supports_depth) return 0;
}
#endif
size_t w = width, h = height, d = depth;
// Unpack the format and use it, along with the target, to create an
// appropriate GL texture.
GLenum gl_fmt = fmt->formattype;
GLenum gl_internal_fmt = fmt->internal;
GLenum gl_type = fmt->datatype;
ExplicitType type = fmt->type;
// Required for most of the texture-backed cases:
glTextureWrapper texture;
// Required for the special case of TextureBuffer textures:
glBufferWrapper glbuf;
// And these are required for the case of Renderbuffer images:
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
void* buffer = NULL;
// Use the correct texture creation function depending on the target, and
// adjust width, height, depth as appropriate so subsequent size calculations
// succeed.
switch (get_base_gl_target(target)) {
case GL_TEXTURE_1D:
h = 1; d = 1;
buffer = CreateGLTexture1D( width, target, gl_fmt,
gl_internal_fmt, gl_type, type, &texture, &error, true, data );
break;
case GL_TEXTURE_BUFFER:
h = 1; d = 1;
buffer = CreateGLTextureBuffer(width, target, gl_fmt, gl_internal_fmt,
gl_type, type, &texture, &glbuf, &error, true, data);
break;
case GL_RENDERBUFFER:
case GL_COLOR_ATTACHMENT0:
d = 1;
buffer = CreateGLRenderbuffer(width, height, target, gl_fmt,
gl_internal_fmt, gl_type, type, &glFramebuffer, &glRenderbuffer, &error,
data, true);
break;
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_CUBE_MAP:
d = 1;
buffer = CreateGLTexture2D(width, height, target, gl_fmt, gl_internal_fmt,
gl_type, type, &texture, &error, true, data);
break;
case GL_TEXTURE_1D_ARRAY:
d = 1;
buffer = CreateGLTexture1DArray( width, height, target, gl_fmt,
gl_internal_fmt, gl_type, type, &texture, &error, true, data );
break;
case GL_TEXTURE_2D_ARRAY:
buffer = CreateGLTexture2DArray( width, height, depth, target, gl_fmt,
gl_internal_fmt, gl_type, type, &texture, &error, true, data );
break;
case GL_TEXTURE_3D:
buffer = CreateGLTexture3D( width, height, depth, target, gl_fmt,
gl_internal_fmt, gl_type, type, &texture, &error, data, true );
break;
#ifdef GL_VERSION_3_2
case GL_TEXTURE_2D_MULTISAMPLE:
d = 1;
buffer = CreateGLTexture2DMultisample( width, height, samples, target, gl_fmt,
gl_internal_fmt, gl_type, type, &texture, &error, true, data, true );
break;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
buffer = CreateGLTexture2DArrayMultisample( width, height, depth, samples, target, gl_fmt,
gl_internal_fmt, gl_type, type, &texture, &error, true, data, true );
break;
#endif
default:
log_error("Unsupported texture target.");
return 1;
}
if ( error == -2 ) {
log_info("OpenGL texture couldn't be created, because a texture is too big. Skipping test.\n");
return 0;
}
// Check to see if the texture could not be created for some other reason like
// GL_FRAMEBUFFER_UNSUPPORTED
if (error == GL_FRAMEBUFFER_UNSUPPORTED) {
log_info("Skipping...\n");
return 0;
}
if ( error != 0 ) {
if ((gl_fmt == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())){
log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. "
"Skipping test.\n");
return 0;
} else {
return error;
}
}
BufferOwningPtr<char> inputBuffer(buffer);
if( inputBuffer == NULL )
return -1;
cl_image_format clFormat;
ExplicitType actualType;
char *outBuffer;
// Perform the read:
GLuint globj = texture;
if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) {
globj = glRenderbuffer;
}
error = test_image_read( context, queue, target, globj, w, h, d, samples, &clFormat,
&actualType, (void **)&outBuffer );
if( error != 0 )
return error;
BufferOwningPtr<char> actualResults(outBuffer);
if( actualResults == NULL )
return -1;
log_info( "- Read [%4d x %4d x %4d x %4d] : GL Texture : %s : %s : %s => CL Image : %s : %s \n",
(int)w, (int)h, (int)d, (int)samples, GetGLFormatName( gl_fmt ), GetGLFormatName( gl_internal_fmt ),
GetGLTypeName( gl_type ), GetChannelOrderName( clFormat.image_channel_order ),
GetChannelTypeName( clFormat.image_channel_data_type ));
BufferOwningPtr<char> convertedInputs;
// 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).
if ( gl_type == GL_UNSIGNED_INT_2_10_10_10_REV )
{
cl_uint *p = (cl_uint *)buffer;
float *inData = (float *)malloc( w * h * d * samples * sizeof(float) );
for( size_t i = 0; i < 4 * w * h * d * samples; i += 4 )
{
inData[ i + 0 ] = (float)( ( p[ 0 ] >> 20 ) & 0x3ff ) / (float)1023;
inData[ i + 1 ] = (float)( ( p[ 0 ] >> 10 ) & 0x3ff ) / (float)1023;
inData[ i + 2 ] = (float)( p[ 0 ] & 0x3ff ) / (float)1023;
p++;
}
convertedInputs.reset( inData );
if( convertedInputs == NULL )
return -1;
}
else if ( gl_type == GL_DEPTH24_STENCIL8 )
{
// GL_DEPTH24_STENCIL8 is treated as CL_UNORM_INT24 + CL_DEPTH_STENCIL where
// the stencil is ignored.
cl_uint *p = (cl_uint *)buffer;
float *inData = (float *)malloc( w * h * d * samples * sizeof(float) );
for( size_t i = 0; i < w * h * d * samples; i++ )
{
inData[ i ] = (float)((p[i] >> 8) & 0xffffff) / (float)0xfffffe;
}
convertedInputs.reset( inData );
if( convertedInputs == NULL )
return -1;
}
else if ( gl_type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)
{
// GL_FLOAT_32_UNSIGNED_INT_24_8_REV is treated as a CL_FLOAT +
// unused 24 + CL_DEPTH_STENCIL; we check the float value and ignore the
// second word
float *p = (float *)buffer;
float *inData = (float *)malloc( w * h * d * samples * sizeof(float) );
for( size_t i = 0; i < w * h * d * samples; i++ )
{
inData[ i ] = p[i*2];
}
convertedInputs.reset( inData );
if( convertedInputs == NULL )
return -1;
}
else
{
convertedInputs.reset(convert_to_expected( inputBuffer,
w * h * d * samples, type, actualType, get_channel_order_channel_count(clFormat.image_channel_order) ));
if( convertedInputs == NULL )
return -1;
}
// Now we validate
if( actualType == kFloat )
{
if ( clFormat.image_channel_data_type == CL_UNORM_INT_101010 )
{
return validate_float_results_rgb_101010( convertedInputs, actualResults, w, h, d, samples );
}
else
{
return validate_float_results( convertedInputs, actualResults, w, h, d, samples, get_channel_order_channel_count(clFormat.image_channel_order) );
}
}
else
{
return validate_integer_results( convertedInputs, actualResults, w, h, d, samples, get_explicit_type_size( actualType ) );
}
}
int test_images_read_common( cl_device_id device, cl_context context,
cl_command_queue queue, struct format* formats, size_t nformats,
GLenum *targets, size_t ntargets, sizevec_t *sizes, size_t nsizes )
{
int error = 0;
RandomSeed seed(gRandomSeed);
// First, ensure this device supports images.
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
size_t fidx, tidx, sidx;
// Test each format on every target, every size.
for ( fidx = 0; fidx < nformats; fidx++ ) {
for ( tidx = 0; tidx < ntargets; tidx++ ) {
// Texture buffer only takes an internal format, so the level data passed
// by the test and used for verification must match the internal format
if ((targets[tidx] == GL_TEXTURE_BUFFER) && (GetGLFormat(formats[ fidx ].internal) != formats[fidx].formattype))
continue;
if ( formats[ fidx ].datatype == GL_UNSIGNED_INT_2_10_10_10_REV )
{
// Check if the RGB 101010 format is supported
if ( is_rgb_101010_supported( context, targets[ tidx ] ) == 0 )
break; // skip
}
if (targets[tidx] != GL_TEXTURE_BUFFER)
log_info( "Testing image read for GL format %s : %s : %s : %s\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ) );
else
log_info( "Testing image read for GL format %s : %s\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ));
for ( sidx = 0; sidx < nsizes; sidx++ ) {
// Test this format + size:
int err;
if ((err = test_image_format_read(context, queue,
sizes[sidx].width, sizes[sidx].height, sizes[sidx].depth,
targets[tidx], &formats[fidx], seed) ))
{
// Negative return values are errors, positive mean the test was skipped
if (err < 0) {
// We land here in the event of test failure.
log_error( "ERROR: Image read test failed for %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ) );
error++;
}
// Skip the other sizes for this format.
printf("Skipping remaining sizes for this format\n");
break;
}
}
// Note a successful format test, if we passed every size.
if( sidx == sizeof (sizes) / sizeof( sizes[0] ) ) {
log_info( "passed: Image read test for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ) );
}
}
}
return error;
}

View File

@@ -0,0 +1,868 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "common.h"
#include <limits.h>
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
extern "C" { extern cl_uint gRandomSeed; };
#pragma mark -
#pragma mark Write test kernels
static const char *kernelpattern_image_write_1D =
"__kernel void sample_test( __global %s4 *source, write_only image1d_t dest )\n"
"{\n"
" uint index = get_global_id(0);\n"
" %s4 value = source[index];\n"
" write_image%s( dest, index, %s(value));\n"
"}\n";
static const char *kernelpattern_image_write_1D_half =
"__kernel void sample_test( __global half4 *source, write_only image1d_t dest )\n"
"{\n"
" uint index = get_global_id(0);\n"
" write_imagef( dest, index, vload_half4(index, (__global half *)source));\n"
"}\n";
static const char *kernelpattern_image_write_1D_buffer =
"__kernel void sample_test( __global %s4 *source, write_only image1d_buffer_t dest )\n"
"{\n"
" uint index = get_global_id(0);\n"
" %s4 value = source[index];\n"
" write_image%s( dest, index, %s(value));\n"
"}\n";
static const char *kernelpattern_image_write_1D_buffer_half =
"__kernel void sample_test( __global half4 *source, write_only image1d_buffer_t dest )\n"
"{\n"
" uint index = get_global_id(0);\n"
" write_imagef( dest, index, vload_half4(index, (__global half *)source));\n"
"}\n";
static const char *kernelpattern_image_write_2D =
"__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";
static const char *kernelpattern_image_write_2D_half =
"__kernel void sample_test( __global half4 *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"
" write_imagef( dest, (int2)( tidX, tidY ), vload_half4(index, (__global half *)source));\n"
"}\n";
static const char *kernelpattern_image_write_1Darray =
"__kernel void sample_test( __global %s4 *source, write_only image1d_array_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";
static const char *kernelpattern_image_write_1Darray_half =
"__kernel void sample_test( __global half4 *source, write_only image1d_array_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"
" write_imagef( dest, (int2)( tidX, tidY ), vload_half4(index, (__global half *)source));\n"
"}\n";
static const char *kernelpattern_image_write_3D =
"__kernel void sample_test( __global %s4 *source, write_only image3d_t dest )\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( dest );\n"
" int height = get_image_height( dest );\n"
" int index = tidZ * width * height + tidY * width + tidX;\n"
" %s4 value = source[index];\n"
" write_image%s( dest, (int4)( tidX, tidY, tidZ, 0 ), %s(value));\n"
"}\n";
static const char *kernelpattern_image_write_3D_half =
"__kernel void sample_test( __global half4 *source, write_only image3d_t dest )\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( dest );\n"
" int height = get_image_height( dest );\n"
" int index = tidZ * width * height + tidY * width + tidX;\n"
" write_imagef( dest, (int4)( tidX, tidY, tidZ, 0 ), vload_half4(index, (__global half *)source));\n"
"}\n";
static const char *kernelpattern_image_write_2Darray =
"__kernel void sample_test( __global %s4 *source, write_only image2d_array_t dest )\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( dest );\n"
" int height = get_image_height( dest );\n"
" int index = tidZ * width * height + tidY * width + tidX;\n"
" %s4 value = source[index];\n"
" write_image%s( dest, (int4)( tidX, tidY, tidZ, 0 ), %s(value));\n"
"}\n";
static const char *kernelpattern_image_write_2Darray_half =
"__kernel void sample_test( __global half4 *source, write_only image2d_array_t dest )\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( dest );\n"
" int height = get_image_height( dest );\n"
" int index = tidZ * width * height + tidY * width + tidX;\n"
" write_imagef( dest, (int4)( tidX, tidY, tidZ, 0 ), vload_half4(index, (__global half *)source));\n"
"}\n";
#ifdef GL_VERSION_3_2
static const char * kernelpattern_image_write_2D_depth =
"__kernel void sample_test( __global %s *source, write_only image2d_depth_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"
" float value = source[index];\n"
" write_imagef( dest, (int2)( tidX, tidY ), value);\n"
"}\n";
static const char * kernelpattern_image_write_2D_array_depth =
"__kernel void sample_test( __global %s *source, write_only image2d_array_depth_t dest )\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( dest );\n"
" int height = get_image_height( dest );\n"
" int index = tidZ * width * height + tidY * width + tidX;\n"
" %s value = source[index];\n"
" write_image%s( dest, (int4)( tidX, tidY, tidZ, 0 ), %s(value));\n"
"}\n";
#endif
#pragma mark -
#pragma mark Utility functions
static const char* get_appropriate_write_kernel(GLenum target,
ExplicitType type, cl_channel_order channel_order)
{
switch (get_base_gl_target(target)) {
case GL_TEXTURE_1D:
if (type == kHalf)
return kernelpattern_image_write_1D_half;
else
return kernelpattern_image_write_1D;
break;
case GL_TEXTURE_BUFFER:
if (type == kHalf)
return kernelpattern_image_write_1D_buffer_half;
else
return kernelpattern_image_write_1D_buffer;
break;
case GL_TEXTURE_1D_ARRAY:
if (type == kHalf)
return kernelpattern_image_write_1Darray_half;
else
return kernelpattern_image_write_1Darray;
break;
case GL_COLOR_ATTACHMENT0:
case GL_RENDERBUFFER:
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_2D:
case GL_TEXTURE_CUBE_MAP:
#ifdef GL_VERSION_3_2
if (channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL)
return kernelpattern_image_write_2D_depth;
#endif
if (type == kHalf)
return kernelpattern_image_write_2D_half;
else
return kernelpattern_image_write_2D;
break;
case GL_TEXTURE_2D_ARRAY:
#ifdef GL_VERSION_3_2
if (channel_order == CL_DEPTH || channel_order == CL_DEPTH_STENCIL)
return kernelpattern_image_write_2D_array_depth;
#endif
if (type == kHalf)
return kernelpattern_image_write_2Darray_half;
else
return kernelpattern_image_write_2Darray;
break;
case GL_TEXTURE_3D:
if (type == kHalf)
return kernelpattern_image_write_3D_half;
else
return kernelpattern_image_write_3D;
break;
default:
log_error("Unsupported GL tex target (%s) passed to write test: "
"%s (%s):%d", GetGLTargetName(target), __FUNCTION__,
__FILE__, __LINE__);
return NULL;
}
}
void set_dimensions_by_target(GLenum target, size_t *dims, size_t sizes[3],
size_t width, size_t height, size_t depth)
{
switch (get_base_gl_target(target)) {
case GL_TEXTURE_1D:
sizes[0] = width;
*dims = 1;
break;
case GL_TEXTURE_BUFFER:
sizes[0] = width;
*dims = 1;
break;
case GL_TEXTURE_1D_ARRAY:
sizes[0] = width;
sizes[1] = height;
*dims = 2;
break;
case GL_COLOR_ATTACHMENT0:
case GL_RENDERBUFFER:
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_2D:
case GL_TEXTURE_CUBE_MAP:
sizes[0] = width;
sizes[1] = height;
*dims = 2;
break;
case GL_TEXTURE_2D_ARRAY:
sizes[0] = width;
sizes[1] = height;
sizes[2] = depth;
*dims = 3;
break;
case GL_TEXTURE_3D:
sizes[0] = width;
sizes[1] = height;
sizes[2] = depth;
*dims = 3;
break;
default:
log_error("Unsupported GL tex target (%s) passed to write test: "
"%s (%s):%d", GetGLTargetName(target), __FUNCTION__,
__FILE__, __LINE__);
}
}
int test_cl_image_write( cl_context context, cl_command_queue queue,
GLenum target, cl_mem clImage, size_t width, size_t height, size_t depth,
cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer,
MTdata d, bool supports_half )
{
size_t global_dims, global_sizes[3];
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper inStream;
char* programPtr;
int error;
char kernelSource[2048];
// What CL format did we get from the texture?
error = clGetImageInfo(clImage, CL_IMAGE_FORMAT, sizeof(cl_image_format),
outFormat, NULL);
test_error(error, "Unable to get the CL image format");
// Create the kernel source. The target and the data type will influence
// which particular kernel we choose.
*outType = get_write_kernel_type( outFormat );
size_t channelSize = get_explicit_type_size(*outType);
const char* appropriateKernel = get_appropriate_write_kernel(target,
*outType, outFormat->image_channel_order);
if (*outType == kHalf && !supports_half) {
log_info("cl_khr_fp16 isn't supported. Skip this test.\n");
return 0;
}
const char* suffix = get_kernel_suffix( outFormat );
const char* convert = get_write_conversion( outFormat, *outType );
sprintf(kernelSource, appropriateKernel, get_explicit_type_name( *outType ),
get_explicit_type_name( *outType ), suffix, convert);
programPtr = kernelSource;
if( create_single_kernel_helper( context, &program, &kernel, 1,
(const char **)&programPtr, "sample_test" ) )
{
return -1;
}
// Create an appropriately-sized output buffer.
// Check to see if the output buffer will fit on the device
size_t bytes = channelSize * 4 * width * height * depth;
cl_ulong alloc_size = 0;
cl_device_id device = NULL;
error = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE, sizeof(device), &device, NULL);
test_error( error, "Unable to query command queue for device" );
error = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(alloc_size), &alloc_size, NULL);
test_error( error, "Unable to device for max mem alloc size" );
if (bytes > alloc_size) {
log_info(" Skipping: Buffer size (%lu) is greater than CL_DEVICE_MAX_MEM_ALLOC_SIZE (%lu)\n", bytes, alloc_size);
*outSourceBuffer = NULL;
return 0;
}
*outSourceBuffer = CreateRandomData(*outType, width * height * depth * 4, d);
inStream = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR,
channelSize * 4 * width * height * depth, *outSourceBuffer, &error );
test_error( error, "Unable to create output buffer" );
cl_sampler_properties properties[] = {
CL_SAMPLER_NORMALIZED_COORDS, CL_FALSE,
CL_SAMPLER_ADDRESSING_MODE, CL_ADDRESS_NONE,
CL_SAMPLER_FILTER_MODE, CL_FILTER_NEAREST,
0 };
clSamplerWrapper sampler = clCreateSamplerWithProperties( context, properties, &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" );
// Flush and Acquire.
glFinish();
error = (*clEnqueueAcquireGLObjects_ptr)( queue, 1, &clImage, 0, NULL, NULL);
test_error( error, "Unable to acquire GL obejcts");
// Execute ( letting OpenCL choose the local size )
// Setup the global dimensions and sizes based on the target type.
set_dimensions_by_target(target, &global_dims, global_sizes,
width, height, depth);
error = clEnqueueNDRangeKernel( queue, kernel, global_dims, NULL,
global_sizes, NULL, 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");
return 0;
}
static int test_image_write( cl_context context, cl_command_queue queue,
GLenum glTarget, GLuint glTexture, size_t width, size_t height, size_t depth,
cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer,
MTdata d, bool supports_half )
{
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" );
GLint fmt;
glGetTexLevelParameteriv( glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt );
log_error( " Supplied GL texture was base format %s and internal "
"format %s\n", GetGLBaseFormatName( fmt ), GetGLFormatName( fmt ) );
return error;
}
return test_cl_image_write( context, queue, glTarget, image,
width, height, depth, outFormat, outType, outSourceBuffer, d, supports_half );
}
int supportsHalf(cl_context context, bool* supports_half)
{
int error;
size_t size;
cl_uint numDev;
error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDev, NULL);
test_error(error, "clGetContextInfo for CL_CONTEXT_NUM_DEVICES failed");
cl_device_id* devices = new cl_device_id[numDev];
error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDev * sizeof(cl_device_id), devices, NULL);
test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed");
// Get the extensions string for the device
error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, 0, NULL, &size);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed");
char *extensions = new char[size+1];
if (extensions == 0) {
log_error("Failed to allocate memory for extensions string.\n");
return -1;
}
memset( extensions, CHAR_MIN, sizeof(char)*(size+1) );
error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed");
*supports_half = strstr(extensions, "cl_khr_fp16");
delete [] extensions;
delete [] devices;
return error;
}
int supportsMsaa(cl_context context, bool* supports_msaa)
{
int error;
size_t size;
cl_uint numDev;
error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDev, NULL);
test_error(error, "clGetContextInfo for CL_CONTEXT_NUM_DEVICES failed");
cl_device_id* devices = new cl_device_id[numDev];
error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDev * sizeof(cl_device_id), devices, NULL);
test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed");
// Get the extensions string for the device
error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, 0, NULL, &size);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed");
char *extensions = new char[size+1];
if (extensions == 0) {
log_error("Failed to allocate memory for extensions string.\n");
return -1;
}
memset( extensions, CHAR_MIN, sizeof(char)*(size+1) );
error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed");
*supports_msaa = strstr(extensions, "cl_khr_gl_msaa_sharing");
delete [] extensions;
delete [] devices;
return error;
}
int supportsDepth(cl_context context, bool* supports_depth)
{
int error;
size_t size;
cl_uint numDev;
error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &numDev, NULL);
test_error(error, "clGetContextInfo for CL_CONTEXT_NUM_DEVICES failed");
cl_device_id* devices = new cl_device_id[numDev];
error = clGetContextInfo(context, CL_CONTEXT_DEVICES, numDev * sizeof(cl_device_id), devices, NULL);
test_error(error, "clGetContextInfo for CL_CONTEXT_DEVICES failed");
// Get the extensions string for the device
error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, 0, NULL, &size);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed");
char *extensions = new char[size+1];
if (extensions == 0) {
log_error("Failed to allocate memory for extensions string.\n");
return -1;
}
memset( extensions, CHAR_MIN, sizeof(char)*(size+1) );
error = clGetDeviceInfo(devices[0], CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed");
*supports_depth = strstr(extensions, "cl_khr_gl_depth_images");
delete [] extensions;
delete [] devices;
return error;
}
static int test_image_format_write( 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;
int samples = 8;
// If we're testing a half float format, then we need to determine the
// rounding mode of this machine. Punt if we fail to do so.
if( type == kHalf )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
// Create an appropriate GL texture or renderbuffer, given the target.
glTextureWrapper glTexture;
glBufferWrapper glBuf;
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
switch (get_base_gl_target(target)) {
case GL_TEXTURE_1D:
CreateGLTexture1D( width, target, format, internalFormat, glType,
type, &glTexture, &error, false, d );
break;
case GL_TEXTURE_BUFFER:
CreateGLTextureBuffer( width, target, format, internalFormat, glType,
type, &glTexture, &glBuf, &error, false, d );
break;
case GL_TEXTURE_1D_ARRAY:
CreateGLTexture1DArray( width, height, target, format, internalFormat,
glType, type, &glTexture, &error, false, d );
break;
case GL_TEXTURE_RECTANGLE_EXT:
case GL_TEXTURE_2D:
case GL_TEXTURE_CUBE_MAP:
CreateGLTexture2D( width, height, target, format, internalFormat, glType,
type, &glTexture, &error, false, d );
break;
case GL_COLOR_ATTACHMENT0:
case GL_RENDERBUFFER:
CreateGLRenderbuffer(width, height, target, format, internalFormat,
glType, type, &glFramebuffer, &glRenderbuffer, &error, d, false);
case GL_TEXTURE_2D_ARRAY:
CreateGLTexture2DArray( width, height, depth, target, format,
internalFormat, glType, type, &glTexture, &error, false, d );
break;
case GL_TEXTURE_3D:
CreateGLTexture3D( width, height, depth, target, format,
internalFormat, glType, type, &glTexture, &error, d, false );
break;
default:
log_error("Unsupported GL tex target (%s) passed to write test: "
"%s (%s):%d", GetGLTargetName(target), __FUNCTION__,
__FILE__, __LINE__);
}
// If there was a problem during creation, make sure it isn't a known
// cause, and then complain.
if ( error == -2 ) {
log_info("OpenGL texture couldn't be created, because a texture is too big. Skipping test.\n");
return 0;
}
if ( error != 0 ) {
if ((format == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport())){
log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. "
"Skipping test.\n");
return 0;
} else {
return error;
}
}
// Run and get the results
cl_image_format clFormat;
ExplicitType sourceType;
ExplicitType validationType;
void *outSourceBuffer = NULL;
GLenum globj = glTexture;
if (target == GL_RENDERBUFFER || target == GL_COLOR_ATTACHMENT0) {
globj = glRenderbuffer;
}
bool supports_half = false;
error = supportsHalf(context, &supports_half);
if( error != 0 )
return error;
error = test_image_write( context, queue, target, globj, width, height,
depth, &clFormat, &sourceType, (void **)&outSourceBuffer, d, supports_half );
if( error != 0 || ((sourceType == kHalf ) && !supports_half)) {
if (outSourceBuffer)
free(outSourceBuffer);
return error;
}
if (!outSourceBuffer)
return 0;
// If actual source type was half, convert to float for validation.
if ( sourceType == kHalf )
validationType = kFloat;
else
validationType = sourceType;
BufferOwningPtr<char> validationSource;
if ( clFormat.image_channel_data_type == CL_UNORM_INT_101010 )
{
validationSource.reset( outSourceBuffer );
}
else
{
validationSource.reset( convert_to_expected( outSourceBuffer,
width * height * depth, sourceType, validationType, get_channel_order_channel_count(clFormat.image_channel_order) ) );
free(outSourceBuffer);
}
log_info( "- Write for %s [%4ld x %4ld x %4ld] : GL Texture : %s : %s : %s =>"
" CL Image : %s : %s \n",
GetGLTargetName(target),
width, height, depth,
GetGLFormatName( format ),
GetGLFormatName( internalFormat ),
GetGLTypeName( glType),
GetChannelOrderName( clFormat.image_channel_order ),
GetChannelTypeName( clFormat.image_channel_data_type ));
// Read the results from the GL texture.
ExplicitType readType = type;
BufferOwningPtr<char> glResults( ReadGLTexture(
target, glTexture, glBuf, width, format,
internalFormat, glType, readType, /* unused */ 1, 1 ) );
if( glResults == NULL )
return -1;
// We have to convert our input buffer to the returned type, so we can validate.
BufferOwningPtr<char> convertedGLResults;
if ( clFormat.image_channel_data_type != CL_UNORM_INT_101010 )
{
convertedGLResults.reset( convert_to_expected(
glResults, width * height * depth, readType, validationType, get_channel_order_channel_count(clFormat.image_channel_order), glType ));
}
// Validate.
int valid = 0;
if (convertedGLResults) {
if( sourceType == kFloat || sourceType == kHalf )
{
if ( clFormat.image_channel_data_type == CL_UNORM_INT_101010 )
{
valid = validate_float_results_rgb_101010( validationSource, glResults, width, height, depth, 1 );
}
else
{
valid = validate_float_results( validationSource, convertedGLResults,
width, height, depth, 1, get_channel_order_channel_count(clFormat.image_channel_order) );
}
}
else
{
valid = validate_integer_results( validationSource, convertedGLResults,
width, height, depth, 1, get_explicit_type_size( readType ) );
}
}
return valid;
}
#pragma mark -
#pragma mark Write test common entry point
// This is the main loop for all of the write tests. It iterates over the
// given formats & targets, testing a variety of sizes against each
// combination.
int test_images_write_common(cl_device_id device, cl_context context,
cl_command_queue queue, struct format* formats, size_t nformats,
GLenum *targets, size_t ntargets, sizevec_t* sizes, size_t nsizes )
{
int err = 0;
int error = 0;
RandomSeed seed(gRandomSeed);
// First, ensure this device supports images.
if (checkForImageSupport(device)) {
log_info("Device does not support images. Skipping test.\n");
return 0;
}
// Get the value of CL_DEVICE_MAX_MEM_ALLOC_SIZE
cl_ulong max_individual_allocation_size = 0;
err = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
sizeof(max_individual_allocation_size),
&max_individual_allocation_size, NULL);
if (err) {
log_error("ERROR: clGetDeviceInfo failed for CL_DEVICE_MAX_MEM_ALLOC_SIZE.\n");
error++;
return error;
}
size_t total_allocation_size;
size_t fidx, tidx, sidx;
for ( fidx = 0; fidx < nformats; fidx++ ) {
for ( tidx = 0; tidx < ntargets; tidx++ ) {
// Texture buffer only takes an internal format, so the level data passed
// by the test and used for verification must match the internal format
if ((targets[tidx] == GL_TEXTURE_BUFFER) && (GetGLFormat(formats[ fidx ].internal) != formats[fidx].formattype))
continue;
if ( formats[ fidx ].datatype == GL_UNSIGNED_INT_2_10_10_10_REV )
{
// Check if the RGB 101010 format is supported
if ( is_rgb_101010_supported( context, targets[ tidx ] ) == 0 )
continue; // skip
}
if (formats[ fidx ].datatype == GL_UNSIGNED_INT_24_8)
{
//check if a implementation supports writing to the depth stencil formats
cl_image_format imageFormat = { CL_DEPTH_STENCIL, CL_UNORM_INT24 };
if (!is_image_format_supported(context, CL_MEM_WRITE_ONLY, (targets[tidx] == GL_TEXTURE_2D || targets[tidx] == GL_TEXTURE_RECTANGLE) ? CL_MEM_OBJECT_IMAGE2D: CL_MEM_OBJECT_IMAGE2D_ARRAY, &imageFormat))
continue;
}
if (formats[ fidx ].datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)
{
//check if a implementation supports writing to the depth stencil formats
cl_image_format imageFormat = { CL_DEPTH_STENCIL, CL_FLOAT};
if (!is_image_format_supported(context, CL_MEM_WRITE_ONLY, (targets[tidx] == GL_TEXTURE_2D || targets[tidx] == GL_TEXTURE_RECTANGLE) ? CL_MEM_OBJECT_IMAGE2D: CL_MEM_OBJECT_IMAGE2D_ARRAY, &imageFormat))
continue;
}
if (targets[tidx] != GL_TEXTURE_BUFFER)
log_info( "Testing image write for GL format %s : %s : %s : %s\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ) );
else
log_info( "Testing image write for GL format %s : %s\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ));
for (sidx = 0; sidx < nsizes; sidx++) {
// All tested formats are 4-channel formats
total_allocation_size =
sizes[sidx].width * sizes[sidx].height * sizes[sidx].depth *
4 * get_explicit_type_size( formats[ fidx ].type );
if (total_allocation_size > max_individual_allocation_size) {
log_info( "The requested allocation size (%gMB) is larger than the "
"maximum individual allocation size (%gMB)\n",
total_allocation_size/(1024.0*1024.0),
max_individual_allocation_size/(1024.0*1024.0));
log_info( "Skipping write test for %s : %s : %s : %s "
" and size (%ld, %ld, %ld)\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ),
sizes[sidx].width,
sizes[sidx].height,
sizes[sidx].depth);
continue;
}
#ifdef GL_VERSION_3_2
if (get_base_gl_target(targets[ tidx ]) == GL_TEXTURE_2D_MULTISAMPLE ||
get_base_gl_target(targets[ tidx ]) == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
{
bool supports_msaa;
error = supportsMsaa(context, &supports_msaa);
if( error != 0 ) return error;
if (!supports_msaa) return 0;
}
if (formats[ fidx ].formattype == GL_DEPTH_COMPONENT ||
formats[ fidx ].formattype == GL_DEPTH_STENCIL)
{
bool supports_depth;
error = supportsDepth(context, &supports_depth);
if( error != 0 ) return error;
if (!supports_depth) return 0;
}
#endif
if( test_image_format_write( context, queue,
sizes[sidx].width,
sizes[sidx].height,
sizes[sidx].depth,
targets[ tidx ],
formats[ fidx ].formattype,
formats[ fidx ].internal,
formats[ fidx ].datatype,
formats[ fidx ].type, seed ) )
{
log_error( "ERROR: Image write test failed for %s : %s : %s : %s "
" and size (%ld, %ld, %ld)\n\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ),
sizes[sidx].width,
sizes[sidx].height,
sizes[sidx].depth);
error++;
break; // Skip other sizes for this combination
}
}
// If we passed all sizes (check versus size loop count):
if (sidx == nsizes) {
log_info( "passed: Image write for GL format %s : %s : %s : %s\n\n",
GetGLTargetName( targets[ tidx ] ),
GetGLFormatName( formats[ fidx ].internal ),
GetGLBaseFormatName( formats[ fidx ].formattype ),
GetGLTypeName( formats[ fidx ].datatype ) );
}
}
}
return error;
}

View File

@@ -0,0 +1,479 @@
//
// 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"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
#if defined (__linux__)
GLboolean
gluCheckExtension(const GLubyte *extension, const GLubyte *extensions)
{
const GLubyte *start;
GLubyte *where, *terminator;
/* Extension names should not have spaces. */
where = (GLubyte *) strchr((const char*)extension, ' ');
if (where || *extension == '\0')
return 0;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
start = extensions;
for (;;) {
where = (GLubyte *) strstr((const char *) start, (const char*) extension);
if (!where)
break;
terminator = where + strlen((const char*) extension);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return 1;
start = terminator;
}
return 0;
}
#endif
extern "C" { extern cl_uint gRandomSeed; };
// This is defined in the write common code:
extern int test_cl_image_write( cl_context context, cl_command_queue queue,
GLenum target, cl_mem clImage, size_t width, size_t height, size_t depth,
cl_image_format *outFormat, ExplicitType *outType, void **outSourceBuffer,
MTdata d, bool supports_half );
extern int test_cl_image_read( cl_context context, cl_command_queue queue,
GLenum gl_target, cl_mem image, size_t width, size_t height, size_t depth, size_t sampleNum,
cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer );
extern int supportsHalf(cl_context context, bool* supports_half);
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
cl_mem 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, glTarget, image, imageWidth,
imageHeight, 1, 1, outFormat, outType, outResultBuffer );
}
int test_renderbuffer_read_image( cl_context context, cl_command_queue queue,
GLsizei width, GLsizei height, GLenum attachment,
GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
if( type == kHalf )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
// Create the GL renderbuffer
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
void *tmp = CreateGLRenderbuffer( width, height, attachment, format, internalFormat, glType, type, &glFramebuffer, &glRenderbuffer, &error, d, true );
BufferOwningPtr<char> inputBuffer(tmp);
if( error != 0 )
{
if ((format == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport()))
{
log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. Skipping test.\n");
return 0;
}
else
{
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( format ), GetGLFormatName( internalFormat ), GetGLTypeName( glType),
GetChannelOrderName( clFormat.image_channel_order ), GetChannelTypeName( clFormat.image_channel_data_type ));
#ifdef 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, get_channel_order_channel_count(clFormat.image_channel_order) ));
#ifdef DEBUG
log_info("- start input data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height, convertedInput);
log_info("- end input data -- \n");
#endif
#ifdef 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, 1, get_channel_order_channel_count(clFormat.image_channel_order) );
else
valid = validate_integer_results( convertedInput, actualResults, width, height, 1, 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 internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
{ 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 },
// Renderbuffers with integer formats do not seem to work reliably across
// platforms/implementations. Disabling this in version 1.0 of CL conformance tests.
#ifdef TEST_INTEGER_FORMATS
{ 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 },
#endif
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
};
size_t fmtIdx, attIdx;
int error = 0;
#ifdef 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;
}
if( !gluCheckExtension( (const GLubyte *)"GL_EXT_framebuffer_object", glGetString( GL_EXTENSIONS ) ) )
{
log_info( "Renderbuffers are not supported by this OpenGL implementation; 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 ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
for( i = 0; i < iter; i++ )
{
GLsizei width = random_in_range( 16, 512, seed );
GLsizei height = random_in_range( 16, 512, seed );
#ifdef DEBUG
width = height = 4;
#endif
if( test_renderbuffer_read_image( context, queue, width, height,
attachments[ attIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Renderbuffer read test failed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
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: Renderbuffer read test passed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
}
}
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, bool supports_half )
{
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, glTarget, image, imageWidth,
imageHeight, 1, outFormat, outType, outSourceBuffer, d, supports_half );
}
int test_renderbuffer_image_write( cl_context context, cl_command_queue queue,
GLsizei width, GLsizei height, GLenum attachment,
GLenum format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
if( type == kHalf )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
// Create the GL renderbuffer
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
CreateGLRenderbuffer( width, height, attachment, format, internalFormat, glType, type, &glFramebuffer, &glRenderbuffer, &error, d, false );
if( error != 0 )
{
if ((format == GL_RGBA_INTEGER_EXT) && (!CheckGLIntegerExtensionSupport()))
{
log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. Skipping test.\n");
return 0;
}
else
{
return error;
}
}
// Run and get the results
cl_image_format clFormat;
ExplicitType sourceType;
ExplicitType validationType;
void *outSourceBuffer;
bool supports_half = false;
error = supportsHalf(context, &supports_half);
if( error != 0 )
return error;
error = test_attach_renderbuffer_write_to_image( context, queue, attachment, glRenderbuffer, width, height, &clFormat, &sourceType, d, (void **)&outSourceBuffer, supports_half );
if( error != 0 || ((sourceType == kHalf ) && !supports_half))
return error;
// If actual source type was half, convert to float for validation.
if( sourceType == kHalf )
validationType = kFloat;
else
validationType = sourceType;
BufferOwningPtr<char> validationSource( convert_to_expected( outSourceBuffer, width * height, sourceType, validationType, get_channel_order_channel_count(clFormat.image_channel_order) ) );
log_info( "- Write [%4d x %4d] : GL Renderbuffer : %s : %s : %s => CL Image : %s : %s \n", width, 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 renderbuffer
BufferOwningPtr<char> resultData( ReadGLRenderbuffer( glFramebuffer, glRenderbuffer, attachment, format, internalFormat, glType, type, width, height ) );
#ifdef 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, validationType, get_channel_order_channel_count(clFormat.image_channel_order) ) );
#ifdef DEBUG
log_info("- start input data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height, validationSource);
log_info("- end input data -- \n");
#endif
#ifdef DEBUG
log_info("- start converted data -- \n");
DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height, convertedData);
log_info("- end converted data -- \n");
#endif
// Now we validate
int valid = 0;
if(convertedData) {
if( sourceType == kFloat || sourceType == kHalf )
valid = validate_float_results( validationSource, convertedData, width, height, 1, get_channel_order_channel_count(clFormat.image_channel_order) );
else
valid = validate_integer_results( validationSource, convertedData, width, height, 1, 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 internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
{ 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 },
// Renderbuffers with integer formats do not seem to work reliably across
// platforms/implementations. Disabling this in version 1.0 of CL conformance tests.
#ifdef TEST_INTEGER_FORMATS
{ 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 },
#endif
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
};
size_t fmtIdx, attIdx;
int error = 0;
size_t iter = 6;
#ifdef 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;
}
if( !gluCheckExtension( (const GLubyte *)"GL_EXT_framebuffer_object", glGetString( GL_EXTENSIONS ) ) )
{
log_info( "Renderbuffers are not supported by this OpenGL implementation; 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 ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
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 DEBUG
width = height = 4;
#endif
if( test_renderbuffer_image_write( context, queue, width, height,
attachments[ attIdx ],
formats[ fmtIdx ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Renderbuffer write test failed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
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: Renderbuffer write test passed for %s : %s : %s : %s\n\n",
GetGLAttachmentName( attachments[ attIdx ] ),
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
}
}
return error;
}

View File

@@ -0,0 +1,133 @@
//
// 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"
#if defined( __APPLE__ )
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#include <CL/cl_gl.h>
#endif
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 format, GLenum internalFormat,
GLenum glType, ExplicitType type, MTdata d )
{
int error;
if( type == kHalf )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
// Create the GL render buffer
glFramebufferWrapper glFramebuffer;
glRenderbufferWrapper glRenderbuffer;
BufferOwningPtr<char> inputBuffer(CreateGLRenderbuffer( width, height, attachment, format, internalFormat, glType, type, &glFramebuffer, &glRenderbuffer, &error, d, true ));
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( internalFormat ),
get_explicit_type_name( type ), (int)width, (int)height );
// Verify the expected information here.
return CheckGLObjectInfo(image, CL_GL_OBJECT_RENDERBUFFER, (GLuint)glRenderbuffer, internalFormat, 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 internal;
GLenum format;
GLenum datatype;
ExplicitType type;
} formats[] = {
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
};
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;
}
if( !gluCheckExtension( (const GLubyte *)"GL_EXT_framebuffer_object", glGetString( GL_EXTENSIONS ) ) )
{
log_info( "Renderbuffers are not supported by this OpenGL implementation; 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 ].internal ),
GetGLBaseFormatName( formats[ fmtIdx ].format ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
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 ].format,
formats[ fmtIdx ].internal,
formats[ fmtIdx ].datatype,
formats[ fmtIdx ].type, seed ) )
{
log_error( "ERROR: Renderbuffer write test failed for GL format %s : %s\n\n",
GetGLFormatName( formats[ fmtIdx ].internal ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
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 ].internal ),
GetGLTypeName( formats[ fmtIdx ].datatype ) );
}
}
}
return error;
}