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,15 @@
if(NOT MSVC)
# IGL: Force no optimizations
set(CMAKE_C_FLAGS_RELEASE "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O0")
endif(NOT MSVC)
add_subdirectory(clCopyImage)
add_subdirectory(clFillImage)
add_subdirectory(clGetInfo)
add_subdirectory(clReadWriteImage)
add_subdirectory(kernel_image_methods)
add_subdirectory(kernel_read_write)
add_subdirectory(samplerlessReads)

View File

@@ -0,0 +1,9 @@
build-project clCopyImage ;
build-project clFillImage ;
build-project clGetInfo ;
build-project clReadWriteImage ;
build-project kernel_image_methods ;
build-project kernel_read_write ;
build_project samplerlessReads ;
use-project /images : . ;

View File

@@ -0,0 +1,31 @@
PRODUCTS = \
clCopyImage/ \
clFillImage/ \
clGetInfo/ \
clReadWriteImage/ \
kernel_image_methods/ \
kernel_read_write/ \
samplerlessReads/
TOP=$(shell pwd)
all: $(PRODUCTS)
clean:
@for testdir in $(dir $(PRODUCTS)) ; \
do ( \
echo "==================================================================================" ; \
echo "Cleaning $$testdir" ; \
echo "==================================================================================" ; \
cd $$testdir && make clean \
); \
done \
$(PRODUCTS):
@echo "==================================================================================" ;
@echo "(`date "+%H:%M:%S"`) Make $@" ;
@echo "==================================================================================" ;
cd $(dir $@) && make -i
.PHONY: clean $(PRODUCTS) all

View File

@@ -0,0 +1,27 @@
set(MODULE_NAME CL_COPY_IMAGES)
set(${MODULE_NAME}_SOURCES
main.cpp
test_copy_1D.cpp
test_copy_1D_array.cpp
test_copy_2D.cpp
test_copy_2D_2D_array.cpp
test_copy_2D_3D.cpp
test_copy_2D_array.cpp
test_copy_3D.cpp
test_copy_3D_2D_array.cpp
test_copy_generic.cpp
test_loops.cpp
../../../test_common/harness/testHarness.c
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,19 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_cl_copy_images
: main.cpp
test_copy_2D_3D.cpp
test_copy_2D.cpp
test_copy_3D.cpp
test_loops.cpp
;
install dist
: test_cl_copy_images
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/clCopyImage
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/clCopyImage
;

View File

@@ -0,0 +1,56 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_copy_generic.cpp \
test_copy_1D.cpp \
test_copy_2D.cpp \
test_loops.cpp \
test_copy_3D.cpp \
test_copy_1D_array.cpp \
test_copy_2D_array.cpp \
test_copy_2D_3D.cpp \
test_copy_2D_2D_array.cpp \
test_copy_3D_2D_array.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.c \
../../../test_common/harness/typeWrappers.cpp \
../../../test_common/harness/mt19937.c
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_cl_copy_images
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = 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,265 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gUseRamp = false, gTestRounding = false, gEnablePitch = false, gTestMipmaps = false;
int gTypesToTest = 0;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
cl_channel_order gChannelOrderToUse = (cl_channel_order)-1;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
cl_context context;
cl_command_queue queue;
extern int test_image_set( cl_device_id device, MethodsToTest testMethod );
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if( p != NULL )
execName = p + 1;
log_info( "Usage: %s [debug_trace] [small_images]\n", execName );
log_info( "Where:\n" );
log_info( "\t1D - Only test 1D images\n" );
log_info( "\t2D - Only test 2D images\n" );
log_info( "\t3D - Only test 3D images\n" );
log_info( "\t1Darray - Only test 1D image arrays\n" );
log_info( "\t2Darray - Only test 2D image arrays\n" );
log_info( "\t2Dto3D - Only test 2D -> 3D images\n" );
log_info( "\t3Dto2D - Only test 3D -> 2D images\n" );
log_info( "\t2Darrayto2D - Only test 2D image arrays -> 2D images\n" );
log_info( "\t2Dto2Darray - Only test 2D images -> 2D image arrays\n" );
log_info( "\t2Darrayto3D - Only test 2D image arrays -> 3D images\n" );
log_info( "\t3Dto2Darray - Only test 3D images -> 2D image arrays\n" );
log_info( "\n" );
log_info( "\ttest_mipmaps - Test with mipmapped images\n" );
log_info( "\tdebug_trace - Enables additional debug info logging\n" );
log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
log_info( "\trounding - Runs every format through a single image filled with every possible value for that image format, to verify rounding works properly\n" );
//log_info( "\tuse_pitches - Enables row and slice pitches\n" );
log_info( "\tuse_ramp - Instead of random data, uses images filled with ramps (and 0xff on any padding pixels) to ease debugging\n" );
}
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_device_id device;
cl_channel_type chanType;
cl_channel_order chanOrder;
char str[ 128 ];
int testMethods = 0;
bool randomize = false;
test_start();
checkDeviceTypeOverride( &gDeviceType );
// Parse arguments
for( int i = 1; i < argc; i++ )
{
strncpy( str, argv[ i ], sizeof( str ) - 1 );
if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if( strcmp( str, "test_mipmaps" ) == 0 )
{
gTestMipmaps = true;
// Don't test pitches with mipmaps, at least currently.
gEnablePitch = false;
}
else if( strcmp( str, "debug_trace" ) == 0 )
gDebugTrace = true;
else if( strcmp( str, "small_images" ) == 0 )
gTestSmallImages = true;
else if( strcmp( str, "max_images" ) == 0 )
gTestMaxImages = true;
else if( strcmp( str, "use_ramps" ) == 0 )
gUseRamp = true;
else if( strcmp( str, "use_pitches" ) == 0 )
gEnablePitch = true;
else if( strcmp( str, "randomize" ) == 0 )
randomize = true;
else if( strcmp( str, "1D" ) == 0 )
testMethods |= k1D;
else if( strcmp( str, "2D" ) == 0 )
testMethods |= k2D;
else if( strcmp( str, "3D" ) == 0 )
testMethods |= k3D;
else if( strcmp( str, "1Darray" ) == 0 )
testMethods |= k1DArray;
else if( strcmp( str, "2Darray" ) == 0 )
testMethods |= k2DArray;
else if( strcmp( str, "2Dto3D" ) == 0 )
testMethods |= k2DTo3D;
else if( strcmp( str, "3Dto2D" ) == 0 )
testMethods |= k3DTo2D;
else if( strcmp( str, "2Darrayto2D" ) == 0 )
testMethods |= k2DArrayTo2D;
else if( strcmp( str, "2Dto2Darray" ) == 0 )
testMethods |= k2DTo2DArray;
else if( strcmp( str, "2Darrayto3D" ) == 0 )
testMethods |= k2DArrayTo3D;
else if( strcmp( str, "3Dto2Darray" ) == 0 )
testMethods |= k3DTo2DArray;
else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else if( ( chanOrder = get_channel_order_from_name( str ) ) != (cl_channel_order)-1 )
gChannelOrderToUse = chanOrder;
else
{
log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str );
return -1;
}
}
if( testMethods == 0 )
testMethods = k1D | k2D | k3D | k1DArray | k2DArray | k2DTo3D | k3DTo2D | k2DArrayTo2D | k2DTo2DArray | k2DArrayTo3D | k3DTo2DArray;
// Seed the random # generators
if( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
log_info( "Random seed: %u.\n", gRandomSeed );
gReSeed = 1;
}
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
error = clGetDeviceIDs(platform, gDeviceType, 1, &device, NULL );
if( error )
{
print_error( error, "Unable to get specified device" );
test_finish();
return -1;
}
char deviceName[ 128 ], deviceVendor[ 128 ], deviceVersion[ 128 ];
error = clGetDeviceInfo( device, CL_DEVICE_NAME, sizeof( deviceName ), deviceName, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_VENDOR, sizeof( deviceVendor ), deviceVendor, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof( deviceVersion ), deviceVersion, NULL );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to get device information" );
test_finish();
return -1;
}
log_info("Using compute device: Name = %s, Vendor = %s, Version = %s\n", deviceName, deviceVendor, deviceVersion );
// Check for image support
if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) {
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if( gTestSmallImages )
log_info( "Note: Using small test images\n" );
// Run the test now
int ret = 0;
for( int test = k1D; test <= k3DTo2DArray; test <<= 1 )
{
if( testMethods & test )
ret += test_image_set( device, (MethodsToTest)test );
}
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.");
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount);
else
log_info("PASSED test.\n");
} else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED test.\n");
}
// Clean up
clReleaseCommandQueue(queue);
clReleaseContext(context);
test_finish();
if (gTestFailure > 0)
return gTestFailure;
return ret;
}

View File

@@ -0,0 +1,235 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
int test_copy_image_size_1D( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ];
int ret = 0, retCode;
size_t src_lod = 0, src_width_lod = imageInfo->width, src_row_pitch_lod;
size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_row_pitch_lod;
size_t width_lod = imageInfo->width;
size_t max_mip_level;
if( gTestMipmaps )
{
max_mip_level = imageInfo->num_mip_levels;
// Work at a random mip level
src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
src_row_pitch_lod = src_width_lod * get_pixel_size( imageInfo->format );
dst_row_pitch_lod = dst_width_lod * get_pixel_size( imageInfo->format );
}
// First, try just a full covering region
sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0;
destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0;
regionSize[ 0 ] = imageInfo->width;
regionSize[ 1 ] = 1;
regionSize[ 2 ] = 1;
if(gTestMipmaps)
{
sourcePos[ 1 ] = src_lod;
destPos[ 1 ] = dst_lod;
regionSize[ 0 ] = width_lod;
}
retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for( int i = 0; i < 8; i++ )
{
if( gTestMipmaps )
{
// Work at a random mip level
src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
sourcePos[ 1 ] = src_lod;
destPos[ 1 ] = dst_lod;
}
// Pick a random size
regionSize[ 0 ] = ( width_lod > 8 ) ? (size_t)random_in_range( 8, (int)width_lod - 1, d ) : width_lod;
// Now pick positions within valid ranges
sourcePos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_copy_image_set_1D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed(gRandomSeed);
size_t pixelSize;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
size_t rowPadding = gEnablePitch ? 48 : 0;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
if( gDebugTrace )
log_info( " at size %d\n", (int)imageInfo.width );
int ret = test_copy_image_size_1D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
size_t rowPadding = gEnablePitch ? 48 : 0;
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
log_info( "Testing %d\n", (int)sizes[ idx ][ 0 ] );
if( gDebugTrace )
log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] );
if( test_copy_image_size_1D( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
size_t rowPadding = gEnablePitch ? 48 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
size = compute_mipmapped_image_size( imageInfo );
size = size*4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
size = (size_t)imageInfo.rowPitch * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
{
log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
if ( gTestMipmaps )
log_info( " and %llu mip levels\n", (size_t) imageInfo.num_mip_levels );
}
int ret = test_copy_image_size_1D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,248 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
int test_copy_image_size_1D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ];
int ret = 0, retCode;
size_t src_lod = 0, src_width_lod = imageInfo->width, src_row_pitch_lod;
size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_row_pitch_lod;
size_t width_lod = imageInfo->width;
size_t max_mip_level;
if( gTestMipmaps )
{
max_mip_level = imageInfo->num_mip_levels;
// Work at a random mip level
src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
src_row_pitch_lod = src_width_lod * get_pixel_size( imageInfo->format );
dst_row_pitch_lod = dst_width_lod * get_pixel_size( imageInfo->format );
}
// First, try just a full covering region
sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0;
destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0;
regionSize[ 0 ] = imageInfo->width;
regionSize[ 1 ] = imageInfo->arraySize;
regionSize[ 2 ] = 1;
if(gTestMipmaps)
{
sourcePos[ 2 ] = src_lod;
destPos[ 2 ] = dst_lod;
regionSize[ 0 ] = width_lod;
}
retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for( int i = 0; i < 8; i++ )
{
if( gTestMipmaps )
{
// Work at a random mip level
src_lod = (size_t) ( max_mip_level > 1 )? random_in_range( 0, max_mip_level - 1 , d ) : 0;
dst_lod = (size_t) ( max_mip_level > 1 )? random_in_range( 0, max_mip_level - 1 , d ) : 0;
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
sourcePos[ 2 ] = src_lod;
destPos[ 2 ] = dst_lod;
}
// Pick a random size
regionSize[ 0 ] = ( width_lod > 8 ) ? (size_t)random_in_range( 8, (int)width_lod - 1, d ) : (int)width_lod;
regionSize[ 1 ] = ( imageInfo->arraySize > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->arraySize - 1, d ) : imageInfo->arraySize;
// Now pick positions within valid ranges
sourcePos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( imageInfo->arraySize > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( imageInfo->arraySize > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - regionSize[ 1 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_copy_image_set_1D_array( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed(gRandomSeed);
size_t pixelSize;
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
size_t rowPadding = gEnablePitch ? 48 : 0;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize );
int ret = test_copy_image_size_1D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
size_t rowPadding = gEnablePitch ? 48 : 0;
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch;
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
if( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
if( test_copy_image_size_1D_array( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
size_t rowPadding = gEnablePitch ? 48 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.height = imageInfo.depth = 0;
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch;
size = compute_mipmapped_image_size( imageInfo );
size = size*4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch;
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
int ret = test_copy_image_size_1D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,248 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
int test_copy_image_size_2D( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ];
int ret = 0, retCode;
size_t src_lod = 0, src_width_lod = imageInfo->width, src_row_pitch_lod;
size_t src_height_lod = imageInfo->height;
size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_row_pitch_lod;
size_t dst_height_lod = imageInfo->height;
size_t width_lod = imageInfo->width, height_lod = imageInfo->height;
size_t max_mip_level;
if( gTestMipmaps )
{
max_mip_level = imageInfo->num_mip_levels;
// Work at a random mip level
src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
src_height_lod = ( imageInfo->height >> src_lod )? ( imageInfo->height >> src_lod ) : 1;
dst_height_lod = ( imageInfo->height >> dst_lod )? ( imageInfo->height >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
height_lod = ( src_height_lod > dst_height_lod ) ? dst_height_lod : src_height_lod;
src_row_pitch_lod = src_width_lod * get_pixel_size( imageInfo->format );
dst_row_pitch_lod = dst_width_lod * get_pixel_size( imageInfo->format );
}
// First, try just a full covering region
sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0;
destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0;
regionSize[ 0 ] = imageInfo->width;
regionSize[ 1 ] = imageInfo->height;
regionSize[ 2 ] = 1;
if(gTestMipmaps)
{
sourcePos[ 2 ] = src_lod;
destPos[ 2 ] = dst_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
}
retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for( int i = 0; i < 8; i++ )
{
if( gTestMipmaps )
{
// Work at a random mip level
src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
src_height_lod = ( imageInfo->height >> src_lod )? ( imageInfo->height >> src_lod ) : 1;
dst_height_lod = ( imageInfo->height >> dst_lod )? ( imageInfo->height >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
height_lod = ( src_height_lod > dst_height_lod ) ? dst_height_lod : src_height_lod;
sourcePos[ 2 ] = src_lod;
destPos[ 2 ] = dst_lod;
}
// Pick a random size
regionSize[ 0 ] = ( width_lod > 8 ) ? (size_t)random_in_range( 8, (int)width_lod - 1, d ) : width_lod;
regionSize[ 1 ] = ( height_lod > 8 ) ? (size_t)random_in_range( 8, (int)height_lod - 1, d ) : height_lod;
// Now pick positions within valid ranges
sourcePos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 0 ] = ( width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_copy_image_generic( device, imageInfo, imageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_copy_image_set_2D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed(gRandomSeed);
size_t pixelSize;
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
size_t rowPadding = gEnablePitch ? 48 : 0;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int ret = test_copy_image_size_2D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
size_t rowPadding = gEnablePitch ? 48 : 0;
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
if( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
if( test_copy_image_size_2D( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
size_t rowPadding = gEnablePitch ? 48 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
size = compute_mipmapped_image_size( imageInfo );
size = size*4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
int ret = test_copy_image_size_2D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,419 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
static size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d )
{
if( rangeB < rangeA )
rangeA = rangeB;
if( rangeA < minimum )
return rangeA;
return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d );
}
static void set_image_dimensions( image_descriptor *imageInfo, size_t width, size_t height, size_t arraySize, size_t rowPadding, size_t slicePadding )
{
size_t pixelSize = get_pixel_size( imageInfo->format );
imageInfo->width = width;
imageInfo->height = height;
imageInfo->arraySize = arraySize;
imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding;
} while ((imageInfo->rowPitch % pixelSize) != 0);
}
if (arraySize == 0)
{
imageInfo->type = CL_MEM_OBJECT_IMAGE2D;
imageInfo->slicePitch = 0;
}
else
{
imageInfo->type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
imageInfo->slicePitch = imageInfo->rowPitch * (imageInfo->height + slicePadding);
}
}
int test_copy_image_size_2D_2D_array( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d )
{
size_t sourcePos[ 4 ] = { 0 }, destPos[ 4 ] = { 0 }, regionSize[ 3 ];
int ret = 0, retCode;
image_descriptor *threeImage, *twoImage;
if( srcImageInfo->arraySize > 0 )
{
threeImage = srcImageInfo;
twoImage = dstImageInfo;
}
else
{
threeImage = dstImageInfo;
twoImage = srcImageInfo;
}
size_t twoImage_lod = 0, twoImage_width_lod = twoImage->width, twoImage_row_pitch_lod;
size_t twoImage_height_lod = twoImage->height;
size_t threeImage_lod = 0, threeImage_width_lod = threeImage->width, threeImage_row_pitch_lod, threeImage_slice_pitch_lod;
size_t threeImage_height_lod = threeImage->height;
size_t width_lod, height_lod;
size_t twoImage_max_mip_level,threeImage_max_mip_level;
if( gTestMipmaps )
{
twoImage_max_mip_level = twoImage->num_mip_levels;
threeImage_max_mip_level = threeImage->num_mip_levels;
// Work at random mip levels
twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d );
threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d );
twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1;
threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1;
twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1;
threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1;
twoImage_row_pitch_lod = twoImage_width_lod * get_pixel_size( twoImage->format );
threeImage_row_pitch_lod = threeImage_width_lod * get_pixel_size( threeImage->format );
threeImage_slice_pitch_lod = threeImage_height_lod * threeImage_row_pitch_lod;
}
width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod;
height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod;
// First, try just a full covering region
sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = sourcePos[ 3 ] = 0;
destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = destPos[ 3 ] = 0;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
regionSize[ 2 ] = 1;
if( srcImageInfo->arraySize == 0 )
{
// 2D to 2D array
destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->arraySize - 1, d );
if(gTestMipmaps)
{
sourcePos[ 2 ] = twoImage_lod;
destPos[ 3 ] = threeImage_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
}
}
else
{
// 2D array to 2D
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->arraySize - 1, d );
if(gTestMipmaps)
{
sourcePos[ 3 ] = threeImage_lod;
destPos[ 2 ] = twoImage_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
}
}
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for( int i = 0; i < 8; i++ )
{
if( gTestMipmaps )
{
// Work at a random mip level
twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d );
threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d );
twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1;
threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1;
twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1;
threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1;
width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod;
height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod;
}
// Pick a random size
regionSize[ 0 ] = random_in_ranges( 8, srcImageInfo->width, dstImageInfo->width, d );
regionSize[ 1 ] = random_in_ranges( 8, srcImageInfo->height, dstImageInfo->height, d );
if( gTestMipmaps )
{
regionSize[ 0 ] = ( width_lod > 8 ) ? random_in_range( 8, width_lod, d ) : width_lod;
regionSize[ 1 ] = ( height_lod > 8) ? random_in_range( 8, height_lod, d ): height_lod;
}
// Now pick positions within valid ranges
sourcePos[ 0 ] = ( srcImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( srcImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0;
sourcePos[ 2 ] = ( srcImageInfo->arraySize > 0 ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->arraySize - 1 ), d ) : gTestMipmaps ? twoImage_lod : 0;
if ( gTestMipmaps )
if( srcImageInfo->arraySize > 0 )
{
sourcePos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
sourcePos[ 3 ] = threeImage_lod;
}
else
{
sourcePos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
}
destPos[ 0 ] = ( dstImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( dstImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 2 ] = ( dstImageInfo->arraySize > 0 ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->arraySize - 1 ), d ) : gTestMipmaps ? twoImage_lod : 0;
if ( gTestMipmaps )
if( dstImageInfo->arraySize > 0 )
{
destPos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 3 ] = threeImage_lod;
}
else
{
destPos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
}
// Go for it!
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_copy_image_set_2D_2D_array( cl_device_id device, cl_image_format *format, bool reverse = false )
{
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor srcImageInfo = { 0 };
image_descriptor dstImageInfo = { 0 };
RandomSeed seed( gRandomSeed );
srcImageInfo.format = dstImageInfo.format = format;
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( dstImageInfo.width = 4; dstImageInfo.width < 17; dstImageInfo.width++ )
{
for( dstImageInfo.height = 4; dstImageInfo.height < 13; dstImageInfo.height++ )
{
for( dstImageInfo.arraySize = 4; dstImageInfo.arraySize < 9; dstImageInfo.arraySize++ )
{
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.arraySize, rowPadding, slicePadding );
set_image_dimensions( &srcImageInfo, dstImageInfo.width, dstImageInfo.height, 0, rowPadding, slicePadding );
if (gTestMipmaps)
{
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed);
dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = 0;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
}
if( gDebugTrace )
{
if (reverse)
log_info( " at size %d,%d,%d to %d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height );
else
log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
}
int ret;
if( reverse )
ret = test_copy_image_size_2D_2D_array( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_2D_2D_array( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numberOfSizes2DArray, numberOfSizes2D;
size_t sizes2DArray[100][3], sizes2D[100][3];
// Try to allocate a bit smaller images because we need the 2D ones as well for the copy.
get_max_sizes(&numberOfSizes2DArray, 100, sizes2DArray, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE2D_ARRAY, dstImageInfo.format);
get_max_sizes(&numberOfSizes2D, 100, sizes2D, maxWidth, maxHeight, 1, 1, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE2D, dstImageInfo.format);
for( size_t i = 0; i < numberOfSizes2D; i++ )
{
for( size_t j = 0; j < numberOfSizes2DArray; j++ )
{
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
set_image_dimensions( &dstImageInfo, sizes2DArray[ j ][ 0 ], sizes2DArray[ j ][ 1 ], sizes2DArray[ j ][ 2 ], rowPadding, slicePadding );
set_image_dimensions( &srcImageInfo, sizes2D[ i ][ 0 ], sizes2D[ i ][ 1 ], 0, rowPadding, slicePadding );
cl_ulong dstSize = get_image_size(&dstImageInfo);
cl_ulong srcSize = get_image_size(&srcImageInfo);
if (gTestMipmaps)
{
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed);
dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = 0;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
dstSize = 4 * compute_mipmapped_image_size( dstImageInfo );
srcSize = 4 * compute_mipmapped_image_size( srcImageInfo );
}
if( dstSize < maxAllocSize && dstSize < ( memSize / 3 ) && srcSize < maxAllocSize && srcSize < ( memSize / 3 ) )
{
if (reverse)
log_info( "Testing %d x %d x %d to %d x %d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height );
else
log_info( "Testing %d x %d to %d x %d x %d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
if( gDebugTrace )
{
if (reverse)
log_info( " at max size %d,%d,%d to %d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height );
else
log_info( " at max size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
}
int ret;
if( reverse )
ret = test_copy_image_size_2D_2D_array( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_2D_2D_array( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
else
{
if (reverse)
log_info("Not testing max size %d x %d x %d to %d x %d due to memory constraints.\n",
(int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height);
else
log_info("Not testing max size %d x %d to %d x %d x %d due to memory constraints.\n",
(int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize);
}
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong srcSize, dstSize;
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
dstImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
dstImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
dstImageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
srcImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
srcImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
if (gTestMipmaps)
{
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed);
dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = 0;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
srcSize = 4 * compute_mipmapped_image_size( srcImageInfo );
dstSize = 4 * compute_mipmapped_image_size( dstImageInfo );
}
else
{
set_image_dimensions( &srcImageInfo, srcImageInfo.width, srcImageInfo.height, 0, rowPadding, slicePadding );
set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.arraySize, rowPadding, slicePadding );
srcSize = (cl_ulong)srcImageInfo.rowPitch * (cl_ulong)srcImageInfo.height * 4;
dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.arraySize * 4;
}
} while( srcSize > maxAllocSize || ( srcSize * 3 ) > memSize || dstSize > maxAllocSize || ( dstSize * 3 ) > memSize);
if( gDebugTrace )
{
if (reverse)
log_info( " at size %d,%d,%d to %d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height );
else
log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
}
int ret;
if( reverse )
ret = test_copy_image_size_2D_2D_array( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_2D_2D_array( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,401 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
static size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d )
{
if( rangeB < rangeA )
rangeA = rangeB;
if( rangeA < minimum )
return rangeA;
return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d );
}
static void set_image_dimensions( image_descriptor *imageInfo, size_t width, size_t height, size_t depth, size_t rowPadding, size_t slicePadding )
{
size_t pixelSize = get_pixel_size( imageInfo->format );
imageInfo->width = width;
imageInfo->height = height;
imageInfo->depth = depth;
imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding;
} while ((imageInfo->rowPitch % pixelSize) != 0);
}
imageInfo->slicePitch = imageInfo->rowPitch * (imageInfo->height + slicePadding);
if (depth == 0)
imageInfo->type = CL_MEM_OBJECT_IMAGE2D;
else
imageInfo->type = CL_MEM_OBJECT_IMAGE3D;
}
int test_copy_image_size_2D_3D( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d )
{
size_t sourcePos[ 4 ] = { 0 }, destPos[ 4 ] = { 0 }, regionSize[ 3 ];
int ret = 0, retCode;
image_descriptor *threeImage, *twoImage;
if( srcImageInfo->depth > 0 )
{
threeImage = srcImageInfo;
twoImage = dstImageInfo;
}
else
{
threeImage = dstImageInfo;
twoImage = srcImageInfo;
}
size_t twoImage_lod = 0, twoImage_width_lod = twoImage->width, twoImage_row_pitch_lod;
size_t twoImage_height_lod = twoImage->height;
size_t threeImage_lod = 0, threeImage_width_lod = threeImage->width, threeImage_row_pitch_lod, threeImage_slice_pitch_lod;
size_t threeImage_height_lod = threeImage->height, depth_lod = threeImage->depth;
size_t width_lod, height_lod;
size_t twoImage_max_mip_level,threeImage_max_mip_level;
if( gTestMipmaps )
{
twoImage_max_mip_level = twoImage->num_mip_levels;
threeImage_max_mip_level = threeImage->num_mip_levels;
// Work at random mip levels
twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d );
threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d );
twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1;
threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1;
twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1;
threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1;
depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1;
twoImage_row_pitch_lod = twoImage_width_lod * get_pixel_size( twoImage->format );
threeImage_row_pitch_lod = threeImage_width_lod * get_pixel_size( threeImage->format );
threeImage_slice_pitch_lod = threeImage_height_lod * threeImage_row_pitch_lod;
}
width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod;
height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod;
// First, try just a full covering region
sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = sourcePos[ 3 ] = 0;
destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = destPos[ 3 ] = 0;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
regionSize[ 2 ] = 1;
if( srcImageInfo->depth == 0 )
{
// 2D to 3D
destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->depth - 1, d );
if(gTestMipmaps)
{
destPos[ 2 ] = (size_t)random_in_range( 0, (int)depth_lod - 1, d );
sourcePos[ 2 ] = twoImage_lod;
destPos[ 3 ] = threeImage_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
}
}
else
{
// 3D to 2D
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->depth - 1, d );
if(gTestMipmaps)
{
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)depth_lod - 1, d );
sourcePos[ 3 ] = threeImage_lod;
destPos[ 2 ] = twoImage_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
}
}
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for( int i = 0; i < 8; i++ )
{
if( gTestMipmaps )
{
// Work at a random mip level
twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d );
threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d );
twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1;
threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1;
twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1;
threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1;
width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod;
height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod;
depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1;
}
// Pick a random size
regionSize[ 0 ] = random_in_ranges( 8, srcImageInfo->width, dstImageInfo->width, d );
regionSize[ 1 ] = random_in_ranges( 8, srcImageInfo->height, dstImageInfo->height, d );
if( gTestMipmaps )
{
regionSize[ 0 ] = ( width_lod > 8 ) ? random_in_range( 8, width_lod, d ) : width_lod;
regionSize[ 1 ] = ( height_lod > 8) ? random_in_range( 8, height_lod, d ): height_lod;
}
// Now pick positions within valid ranges
sourcePos[ 0 ] = ( srcImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( srcImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0;
sourcePos[ 2 ] = ( srcImageInfo->depth > 0 ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->depth - 1 ), d ) : 0;
if ( gTestMipmaps )
if( srcImageInfo->depth > 0 )
{
sourcePos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)( depth_lod - 1 ), d );
sourcePos[ 3 ] = threeImage_lod;
}
else
{
sourcePos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
}
destPos[ 0 ] = ( dstImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( dstImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 2 ] = ( dstImageInfo->depth > 0 ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->depth - 1 ), d ) : 0;
if ( gTestMipmaps )
if( dstImageInfo->depth > 0 )
{
destPos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 2 ] = (size_t)random_in_range( 0, (int)( depth_lod - 1 ), d );
destPos[ 3 ] = threeImage_lod;
}
else
{
destPos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
}
// Go for it!
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_copy_image_set_2D_3D( cl_device_id device, cl_image_format *format, bool reverse = false )
{
size_t maxWidth, maxHeight, max3DWidth, max3DHeight, max3DDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor srcImageInfo = { 0 };
image_descriptor dstImageInfo = { 0 };
RandomSeed seed( gRandomSeed );
srcImageInfo.format = dstImageInfo.format = format;
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( max3DWidth ), &max3DWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( max3DHeight ), &max3DHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( max3DDepth ), &max3DDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D or 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( dstImageInfo.width = 4; dstImageInfo.width < 17; dstImageInfo.width++ )
{
for( dstImageInfo.height = 4; dstImageInfo.height < 13; dstImageInfo.height++ )
{
for( dstImageInfo.depth = 4; dstImageInfo.depth < 9; dstImageInfo.depth++ )
{
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth, rowPadding, slicePadding );
set_image_dimensions( &srcImageInfo, dstImageInfo.width, dstImageInfo.height, 0, rowPadding, slicePadding );
if (gTestMipmaps)
{
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth), seed);
dstImageInfo.type = CL_MEM_OBJECT_IMAGE3D;
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = 0;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
}
if( gDebugTrace )
log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth );
int ret;
if( reverse )
ret = test_copy_image_size_2D_3D( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_2D_3D( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numberOfSizes3D, numberOfSizes2D;
size_t sizes3D[100][3], sizes2D[100][3];
// Try to allocate a bit smaller images because we need the 2D ones as well for the copy.
get_max_sizes(&numberOfSizes3D, 100, sizes3D, max3DWidth, max3DHeight, max3DDepth, 1, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE3D, dstImageInfo.format);
get_max_sizes(&numberOfSizes2D, 100, sizes2D, maxWidth, maxHeight, 1, 1, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE2D, srcImageInfo.format);
for( size_t i = 0; i < numberOfSizes2D; i++ )
for( size_t j = 0; j < numberOfSizes3D; j++ )
{
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
set_image_dimensions( &dstImageInfo, sizes3D[ j ][ 0 ], sizes3D[ j ][ 1 ], sizes3D[ j ][ 2 ], rowPadding, slicePadding );
set_image_dimensions( &srcImageInfo, sizes2D[ i ][ 0 ], sizes2D[ i ][ 1 ], 0, rowPadding, slicePadding );
cl_ulong dstSize = get_image_size(&dstImageInfo);
cl_ulong srcSize = get_image_size(&srcImageInfo);
if (gTestMipmaps)
{
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth), seed);
dstImageInfo.type = CL_MEM_OBJECT_IMAGE3D;
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = 0;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
dstSize = 4 * compute_mipmapped_image_size( dstImageInfo );
srcSize = 4 * compute_mipmapped_image_size( srcImageInfo );
}
if( dstSize < maxAllocSize && dstSize < ( memSize / 3 ) && srcSize < maxAllocSize && srcSize < ( memSize / 3 ) )
{
log_info( "Testing %d x %d to %d x %d x %d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth );
if( gDebugTrace )
log_info( " at max size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth );
int ret;
if( reverse )
ret = test_copy_image_size_2D_3D( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_2D_3D( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
else
{
log_info("Not testing max size %d x %d to %d x %d x %d due to memory constraints.\n",
(int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth);
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong srcSize, dstSize;
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
dstImageInfo.width = (size_t)random_log_in_range( 16, (int)max3DWidth / 32, seed );
dstImageInfo.height = (size_t)random_log_in_range( 16, (int)max3DHeight / 32, seed );
dstImageInfo.depth = (size_t)random_log_in_range( 16, (int)max3DDepth / 32, seed );
srcImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
srcImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
if (gTestMipmaps)
{
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE2D;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth), seed);
dstImageInfo.type = CL_MEM_OBJECT_IMAGE3D;
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = 0;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
srcSize = 4 * compute_mipmapped_image_size( srcImageInfo );
dstSize = 4 * compute_mipmapped_image_size( dstImageInfo );
}
else
{
set_image_dimensions( &srcImageInfo, srcImageInfo.width, srcImageInfo.height, 0, rowPadding, slicePadding );
set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.depth, rowPadding, slicePadding );
srcSize = (cl_ulong)srcImageInfo.rowPitch * (cl_ulong)srcImageInfo.height * 4;
dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.depth * 4;
}
} while( srcSize > maxAllocSize || ( srcSize * 3 ) > memSize || dstSize > maxAllocSize || ( dstSize * 3 ) > memSize);
if( gDebugTrace )
log_info( " at size %d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.depth );
int ret;
if( reverse )
ret = test_copy_image_size_2D_3D( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_2D_3D( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,205 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_copy_generic.cpp
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
int test_copy_image_2D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
size_t srcPos[] = { 0, 0, 0, 0}, dstPos[] = {0, 0, 0, 0};
size_t region[] = { imageInfo->width, imageInfo->height, imageInfo->arraySize };
size_t src_lod = 0, src_width_lod = imageInfo->width, src_height_lod = imageInfo->height;
size_t dst_lod = 0, dst_width_lod = imageInfo->width, dst_height_lod = imageInfo->height;
size_t width_lod = imageInfo->width, height_lod = imageInfo->height;
size_t max_mip_level;
if( gTestMipmaps )
{
max_mip_level = imageInfo->num_mip_levels;
// Work at a random mip level
src_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
dst_lod = (size_t)random_in_range( 0, max_mip_level ? max_mip_level - 1 : 0, d );
src_width_lod = ( imageInfo->width >> src_lod )? ( imageInfo->width >> src_lod ) : 1;
dst_width_lod = ( imageInfo->width >> dst_lod )? ( imageInfo->width >> dst_lod ) : 1;
src_height_lod = ( imageInfo->height >> src_lod )? ( imageInfo->height >> src_lod ) : 1;
dst_height_lod = ( imageInfo->height >> dst_lod )? ( imageInfo->height >> dst_lod ) : 1;
width_lod = ( src_width_lod > dst_width_lod ) ? dst_width_lod : src_width_lod;
height_lod = ( src_height_lod > dst_height_lod ) ? dst_height_lod : src_height_lod;
region[ 0 ] = width_lod;
region[ 1 ] = height_lod;
srcPos[ 3 ] = src_lod;
dstPos[ 3 ] = dst_lod;
}
return test_copy_image_generic( device, imageInfo, imageInfo, srcPos, dstPos, region, d );
}
int test_copy_image_set_2D_array( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
size_t rowPadding = gEnablePitch ? 80 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize );
int ret = test_copy_image_2D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, imageInfo.type, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
size_t rowPadding = gEnablePitch ? 80 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( test_copy_image_2D_array( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
size_t rowPadding = gEnablePitch ? 80 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size = compute_mipmapped_image_size( imageInfo );
size = size*4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize );
int ret = test_copy_image_2D_array( device, &imageInfo,seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,192 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_copy_generic.cpp
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
int test_copy_image_3D( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
size_t origin[] = { 0, 0, 0, 0};
size_t region[] = { imageInfo->width, imageInfo->height, imageInfo->depth };
if( gTestMipmaps )
{
size_t lod = (imageInfo->num_mip_levels > 1 )? (size_t)random_in_range( 0, imageInfo->num_mip_levels - 1, d ) : 0 ;
origin[ 3 ] = lod;
region[ 0 ] = ( imageInfo->width >> lod ) ? ( imageInfo->width >> lod ) : 1;
region[ 1 ] = ( imageInfo->height >> lod ) ? ( imageInfo->height >> lod ) : 1;
region[ 2 ] = ( imageInfo->depth >> lod ) ? ( imageInfo->depth >> lod ) : 1;
}
return test_copy_image_generic( device, imageInfo, imageInfo, origin, origin, region, d );
}
int test_copy_image_set_3D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
size_t rowPadding = gEnablePitch ? 80 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ )
{
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth );
int ret = test_copy_image_3D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, imageInfo.type, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
size_t rowPadding = gEnablePitch ? 80 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.depth = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed);
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( test_copy_image_3D( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
size_t rowPadding = gEnablePitch ? 80 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32,seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
size = compute_mipmapped_image_size( imageInfo );
size = size*4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth );
int ret = test_copy_image_3D( device, &imageInfo,seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,442 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d );
static size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d )
{
if( rangeB < rangeA )
rangeA = rangeB;
if( rangeA < minimum )
return rangeA;
return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d );
}
static void set_image_dimensions( image_descriptor *imageInfo, size_t width, size_t height, size_t depth, size_t arraySize, size_t rowPadding, size_t slicePadding )
{
size_t pixelSize = get_pixel_size( imageInfo->format );
imageInfo->width = width;
imageInfo->height = height;
imageInfo->depth = depth;
imageInfo->arraySize = arraySize;
imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding;
if (gEnablePitch)
{
do {
rowPadding++;
imageInfo->rowPitch = imageInfo->width * pixelSize + rowPadding;
} while ((imageInfo->rowPitch % pixelSize) != 0);
}
imageInfo->slicePitch = imageInfo->rowPitch * (imageInfo->height + slicePadding);
if (arraySize == 0)
imageInfo->type = CL_MEM_OBJECT_IMAGE3D;
else
imageInfo->type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
}
int test_copy_image_size_3D_2D_array( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d )
{
size_t sourcePos[ 4 ], destPos[ 4 ], regionSize[ 3 ];
int ret = 0, retCode;
image_descriptor *threeImage, *twoImage;
if( srcImageInfo->arraySize == 0 )
{
threeImage = srcImageInfo;
twoImage = dstImageInfo;
}
else
{
threeImage = dstImageInfo;
twoImage = srcImageInfo;
}
size_t twoImage_width_lod = twoImage->width, twoImage_height_lod = twoImage->height;
size_t threeImage_width_lod = threeImage->width, threeImage_height_lod = threeImage->height;
size_t twoImage_lod = 0, threeImage_lod = 0;
size_t width_lod = 0, height_lod = 0, depth_lod = 0;
size_t twoImage_max_mip_level,threeImage_max_mip_level;
if( gTestMipmaps )
{
twoImage_max_mip_level = twoImage->num_mip_levels;
threeImage_max_mip_level = threeImage->num_mip_levels;
// Work at random mip levels
twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d );
threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d );
twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1;
threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1;
twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1;
threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1;
depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1;
}
width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod;
height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod;
depth_lod = ( depth_lod > twoImage->arraySize ) ? twoImage->arraySize : depth_lod;
// First, try just a full covering region
sourcePos[ 0 ] = sourcePos[ 1 ] = sourcePos[ 2 ] = 0;
destPos[ 0 ] = destPos[ 1 ] = destPos[ 2 ] = 0;
regionSize[ 0 ] = ( threeImage->width < twoImage->width ) ? threeImage->width : twoImage->width;
regionSize[ 1 ] = ( threeImage->height < twoImage->height ) ? threeImage->height : twoImage->height;
regionSize[ 2 ] = 1;
if( srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D )
{
// 3D to 2D array
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->depth - 1, d );
destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->arraySize - 1, d );
if(gTestMipmaps)
{
sourcePos[ 2 ] = 0/*(size_t)random_in_range( 0, (int)depth_lod - 1, d )*/;
destPos[ 2 ] = ( twoImage->arraySize > depth_lod ) ? (size_t)random_in_range( 0, twoImage->arraySize - depth_lod, d) : 0;
sourcePos[ 3 ] = threeImage_lod;
destPos[ 3 ] = twoImage_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
regionSize[ 2 ] = depth_lod;
}
}
else
{
// 2D array to 3D
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)srcImageInfo->arraySize - 1, d );
destPos[ 2 ] = (size_t)random_in_range( 0, (int)dstImageInfo->depth - 1, d );
if(gTestMipmaps)
{
destPos[ 2 ] = 0 /*(size_t)random_in_range( 0, (int)depth_lod - 1, d )*/;
sourcePos[ 2 ] = ( twoImage->arraySize > depth_lod ) ? (size_t)random_in_range( 0, twoImage->arraySize - depth_lod, d) : 0;
sourcePos[ 3 ] = twoImage_lod;
destPos[ 3 ] = threeImage_lod;
regionSize[ 0 ] = width_lod;
regionSize[ 1 ] = height_lod;
regionSize[ 2 ] = depth_lod;
}
}
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for( int i = 0; i < 8; i++ )
{
if( gTestMipmaps )
{
twoImage_max_mip_level = twoImage->num_mip_levels;
threeImage_max_mip_level = threeImage->num_mip_levels;
// Work at random mip levels
twoImage_lod = (size_t)random_in_range( 0, twoImage_max_mip_level ? twoImage_max_mip_level - 1 : 0, d );
threeImage_lod = (size_t)random_in_range( 0, threeImage_max_mip_level ? threeImage_max_mip_level - 1 : 0, d );
twoImage_width_lod = ( twoImage->width >> twoImage_lod )? ( twoImage->width >> twoImage_lod ) : 1;
threeImage_width_lod = ( threeImage->width >> threeImage_lod )? ( threeImage->width >> threeImage_lod ) : 1;
twoImage_height_lod = ( twoImage->height >> twoImage_lod )? ( twoImage->height >> twoImage_lod ) : 1;
threeImage_height_lod = ( threeImage->height >> threeImage_lod )? ( threeImage->height >> threeImage_lod ) : 1;
depth_lod = ( threeImage->depth >> threeImage_lod )? ( threeImage->depth >> threeImage_lod ) : 1;
width_lod = ( twoImage_width_lod > threeImage_width_lod ) ? threeImage_width_lod : twoImage_width_lod;
height_lod = ( twoImage_height_lod > threeImage_height_lod ) ? threeImage_height_lod : twoImage_height_lod;
depth_lod = ( twoImage->arraySize > depth_lod ) ? depth_lod : twoImage->arraySize;
}
// Pick a random size
regionSize[ 0 ] = random_in_ranges( 8, srcImageInfo->width, dstImageInfo->width, d );
regionSize[ 1 ] = random_in_ranges( 8, srcImageInfo->height, dstImageInfo->height, d );
if( gTestMipmaps )
{
regionSize[ 0 ] = random_in_range( 1, width_lod, d );
regionSize[ 1 ] = random_in_range( 1, height_lod, d );
regionSize[ 2 ] = depth_lod/*random_in_range( 0, depth_lod, d )*/;
}
// Now pick positions within valid ranges
sourcePos[ 0 ] = ( srcImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( srcImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( srcImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0;
if (srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D)
{
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)( srcImageInfo->depth - 1 ), d );
if(gTestMipmaps)
{
sourcePos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
sourcePos[ 2 ] = 0 /*( depth_lod > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( depth_lod - regionSize[ 2 ] - 1 ), d ) : 0*/;
sourcePos[ 3 ] = threeImage_lod;
}
}
else
{
sourcePos[ 2 ] = (size_t)random_in_range( 0, (int)( srcImageInfo->arraySize - 1 ), d );
if(gTestMipmaps)
{
sourcePos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
sourcePos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
sourcePos[ 2 ] = ( twoImage->arraySize > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( twoImage->arraySize - regionSize[ 2 ] - 1 ), d ) : 0;
sourcePos[ 3 ] = twoImage_lod;
}
}
destPos[ 0 ] = ( dstImageInfo->width > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->width - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( dstImageInfo->height > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( dstImageInfo->height - regionSize[ 1 ] - 1 ), d ) : 0;
if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D)
{
destPos[ 2 ] = (size_t)random_in_range( 0, (int)( dstImageInfo->depth - 1 ), d );
if(gTestMipmaps)
{
destPos[ 0 ] = ( threeImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( threeImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( threeImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 2 ] = 0/*( depth_lod > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( depth_lod - regionSize[ 2 ] - 1 ), d ) : 0*/;
destPos[ 3 ] = threeImage_lod;
}
}
else
{
destPos[ 2 ] = (size_t)random_in_range( 0, (int)( dstImageInfo->arraySize - 1 ), d );
if(gTestMipmaps)
{
destPos[ 0 ] = ( twoImage_width_lod > regionSize[ 0 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_width_lod - regionSize[ 0 ] - 1 ), d ) : 0;
destPos[ 1 ] = ( twoImage_height_lod > regionSize[ 1 ] ) ? (size_t)random_in_range( 0, (int)( twoImage_height_lod - regionSize[ 1 ] - 1 ), d ) : 0;
destPos[ 2 ] = ( twoImage->arraySize > regionSize[ 2 ] ) ? (size_t)random_in_range( 0, (int)( twoImage->arraySize - regionSize[ 2 ] - 1 ), d ) : 0;
destPos[ 3 ] = twoImage_lod;
}
}
// Go for it!
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_copy_image_set_3D_2D_array( cl_device_id device, cl_image_format *format, bool reverse = false )
{
size_t maxWidth, maxHeight, max3DWidth, max3DHeight, maxDepth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor srcImageInfo = { 0 };
image_descriptor dstImageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t rowPadding = gEnablePitch ? 256 : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
srcImageInfo.format = dstImageInfo.format = format;
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( max3DWidth ), &max3DWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( max3DHeight ), &max3DHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D image array or 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( dstImageInfo.width = 4; dstImageInfo.width < 17; dstImageInfo.width++ )
{
for( dstImageInfo.height = 4; dstImageInfo.height < 13; dstImageInfo.height++ )
{
for( dstImageInfo.arraySize = 4; dstImageInfo.arraySize < 9; dstImageInfo.arraySize++ )
{
set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, 0, dstImageInfo.arraySize, rowPadding, slicePadding );
set_image_dimensions( &srcImageInfo, dstImageInfo.width, dstImageInfo.height, dstImageInfo.arraySize, 0, rowPadding, slicePadding );
if (gTestMipmaps)
{
dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE3D;
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth), seed);
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = srcImageInfo.rowPitch * srcImageInfo.height;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
}
if( gDebugTrace )
{
if (reverse)
log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth );
else
log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
}
int ret;
if( reverse )
ret = test_copy_image_size_3D_2D_array( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_3D_2D_array( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes3D[100][3];
size_t sizes2Darray[100][3];
// Try to allocate a bit smaller images because we need the 3D ones as well for the copy.
get_max_sizes(&numbeOfSizes, 100, sizes2Darray, maxWidth, maxHeight, maxDepth, maxArraySize, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE3D, srcImageInfo.format);
get_max_sizes(&numbeOfSizes, 100, sizes3D, max3DWidth, max3DHeight, maxDepth, maxArraySize, maxAllocSize/2, memSize/2, CL_MEM_OBJECT_IMAGE3D, dstImageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
set_image_dimensions( &srcImageInfo, sizes3D[ idx ][ 0 ], sizes3D[ idx ][ 1 ], sizes3D[ idx ][ 2 ], 0, rowPadding, slicePadding );
set_image_dimensions( &dstImageInfo, sizes2Darray[ idx ][ 0 ], sizes2Darray[ idx ][ 1 ], 0, sizes2Darray[ idx ][ 2 ], rowPadding, slicePadding );
cl_ulong dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.arraySize;
cl_ulong srcSize = (cl_ulong)srcImageInfo.slicePitch * (cl_ulong)srcImageInfo.depth;
if (gTestMipmaps)
{
dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE3D;
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth), seed);
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = srcImageInfo.rowPitch * srcImageInfo.height;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
srcSize = 4 * compute_mipmapped_image_size( srcImageInfo );
dstSize = 4 * compute_mipmapped_image_size( dstImageInfo );
}
if ( ( dstSize < maxAllocSize && dstSize < ( memSize / 3 ) ) &&
( srcSize < maxAllocSize && srcSize < ( memSize / 3 ) ) )
{
if (reverse)
log_info( "Testing %d x %d x %d to %d x %d x %d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth );
else
log_info( "Testing %d x %d x %d to %d x %d x %d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
if( gDebugTrace )
{
if (reverse)
log_info( " at max size %d,%d,%d to %d,%d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth );
else
log_info( " at max size %d,%d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
}
int ret;
if( reverse )
ret = test_copy_image_size_3D_2D_array( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_3D_2D_array( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
else
{
if (reverse)
log_info("Not testing max size %d x %d x %d x %d to %d x %d due to memory constraints.\n",
(int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth);
else
log_info("Not testing max size %d x %d x %d to %d x %d x %d due to memory constraints.\n",
(int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize);
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong srcSize, dstSize;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
dstImageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
dstImageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
dstImageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
srcImageInfo.width = (size_t)random_log_in_range( 16, (int)max3DWidth / 32, seed );
srcImageInfo.height = (size_t)random_log_in_range( 16, (int)max3DHeight / 32, seed );
srcImageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed );
if (gTestMipmaps)
{
dstImageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
dstImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(dstImageInfo.width, dstImageInfo.height, 0), seed);
srcImageInfo.type = CL_MEM_OBJECT_IMAGE3D;
srcImageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth), seed);
srcImageInfo.rowPitch = srcImageInfo.width * get_pixel_size( srcImageInfo.format );
srcImageInfo.slicePitch = srcImageInfo.rowPitch * srcImageInfo.height;
dstImageInfo.rowPitch = dstImageInfo.width * get_pixel_size( dstImageInfo.format );
dstImageInfo.slicePitch = dstImageInfo.rowPitch * dstImageInfo.height;
srcSize = 4 * compute_mipmapped_image_size( srcImageInfo );
dstSize = 4 * compute_mipmapped_image_size( dstImageInfo );
}
else
{
set_image_dimensions( &srcImageInfo, srcImageInfo.width, srcImageInfo.height, srcImageInfo.depth, 0, rowPadding, slicePadding );
set_image_dimensions( &dstImageInfo, dstImageInfo.width, dstImageInfo.height, 0, dstImageInfo.arraySize, rowPadding, slicePadding );
srcSize = (cl_ulong)srcImageInfo.slicePitch * (cl_ulong)srcImageInfo.depth * 4;
dstSize = (cl_ulong)dstImageInfo.slicePitch * (cl_ulong)dstImageInfo.arraySize * 4;
}
} while( srcSize > maxAllocSize || ( srcSize * 3 ) > memSize || dstSize > maxAllocSize || ( dstSize * 3 ) > memSize);
if( gDebugTrace )
{
if (reverse)
log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize, (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth );
else
log_info( " at size %d,%d,%d to %d,%d,%d\n", (int)srcImageInfo.width, (int)srcImageInfo.height, (int)srcImageInfo.depth, (int)dstImageInfo.width, (int)dstImageInfo.height, (int)dstImageInfo.arraySize );
}
int ret;
if( reverse )
ret = test_copy_image_size_3D_2D_array( device, &dstImageInfo, &srcImageInfo, seed );
else
ret = test_copy_image_size_3D_2D_array( device, &srcImageInfo, &dstImageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,763 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
size_t random_in_ranges( size_t minimum, size_t rangeA, size_t rangeB, MTdata d )
{
if( rangeB < rangeA )
rangeA = rangeB;
if( rangeA < minimum )
return rangeA;
return (size_t)random_in_range( (int)minimum, (int)rangeA - 1, d );
}
static void CL_CALLBACK free_pitch_buffer( cl_mem image, void *buf )
{
free( buf );
}
cl_mem create_image( cl_context context, BufferOwningPtr<char>& data, image_descriptor *imageInfo, int *error )
{
cl_mem img;
cl_image_desc imageDesc;
cl_mem_flags mem_flags = CL_MEM_READ_ONLY;
void *host_ptr = NULL;
memset(&imageDesc, 0x0, sizeof(cl_image_desc));
imageDesc.image_type = imageInfo->type;
imageDesc.image_width = imageInfo->width;
imageDesc.image_height = imageInfo->height;
imageDesc.image_depth = imageInfo->depth;
imageDesc.image_array_size = imageInfo->arraySize;
imageDesc.image_row_pitch = gEnablePitch ? imageInfo->rowPitch : 0;
imageDesc.image_slice_pitch = gEnablePitch ? imageInfo->slicePitch : 0;
imageDesc.num_mip_levels = gTestMipmaps ? imageInfo->num_mip_levels : 0;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
if ( gDebugTrace )
log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->rowPitch );
break;
case CL_MEM_OBJECT_IMAGE2D:
if ( gDebugTrace )
log_info( " - Creating 2D image %d by %d ...\n", (int)imageInfo->width, (int)imageInfo->height );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->height * imageInfo->rowPitch );
break;
case CL_MEM_OBJECT_IMAGE3D:
if ( gDebugTrace )
log_info( " - Creating 3D image %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->depth * imageInfo->slicePitch );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
if ( gDebugTrace )
log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
if ( gDebugTrace )
log_info( " - Creating 2D image array %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch );
break;
}
if ( gDebugTrace && gTestMipmaps )
log_info(" - with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels);
if (gEnablePitch)
{
if ( NULL == host_ptr )
{
log_error( "ERROR: Unable to create backing store for pitched 3D image. %ld bytes\n", imageInfo->depth * imageInfo->slicePitch );
return NULL;
}
mem_flags = CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR;
}
img = clCreateImage(context, mem_flags, imageInfo->format, &imageDesc, host_ptr, error);
if (gEnablePitch)
{
if ( *error == CL_SUCCESS )
{
int callbackError = clSetMemObjectDestructorCallback( img, free_pitch_buffer, host_ptr );
if ( CL_SUCCESS != callbackError )
{
free( host_ptr );
log_error( "ERROR: Unable to attach destructor callback to pitched 3D image. Err: %d\n", callbackError );
clReleaseMemObject( img );
return NULL;
}
}
else
free(host_ptr);
}
if ( *error != CL_SUCCESS )
{
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( *error ) );
break;
case CL_MEM_OBJECT_IMAGE2D:
log_error( "ERROR: Unable to create 2D image of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, IGetErrorString( *error ) );
break;
case CL_MEM_OBJECT_IMAGE3D:
log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( *error ) );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( *error ) );
break;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( *error ) );
break;
}
log_error("ERROR: and %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels);
return NULL;
}
// Copy the specified data to the image via a Map operation.
size_t mappedRow, mappedSlice;
size_t width = imageInfo->width;
size_t height = 1;
size_t depth = 1;
size_t row_pitch_lod, slice_pitch_lod;
row_pitch_lod = imageInfo->rowPitch;
slice_pitch_lod = imageInfo->slicePitch;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
height = imageInfo->arraySize;
depth = 1;
break;
case CL_MEM_OBJECT_IMAGE1D:
height = depth = 1;
break;
case CL_MEM_OBJECT_IMAGE2D:
height = imageInfo->height;
depth = 1;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
height = imageInfo->height;
depth = imageInfo->arraySize;
break;
case CL_MEM_OBJECT_IMAGE3D:
height = imageInfo->height;
depth = imageInfo->depth;
break;
}
size_t origin[ 4 ] = { 0, 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, height, depth };
for ( size_t lod = 0; (gTestMipmaps && (lod < imageInfo->num_mip_levels)) || (!gTestMipmaps && (lod < 1)); lod++)
{
// Map the appropriate miplevel to copy the specified data.
if(gTestMipmaps)
{
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE3D:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
origin[ 3 ] = lod;
break;
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
origin[ 2 ] = lod;
break;
case CL_MEM_OBJECT_IMAGE1D:
origin[ 1 ] = lod;
break;
}
//Adjust image dimensions as per miplevel
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE3D:
depth = ( imageInfo->depth >> lod ) ? (imageInfo->depth >> lod) : 1;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
case CL_MEM_OBJECT_IMAGE2D:
height = ( imageInfo->height >> lod ) ? (imageInfo->height >> lod) : 1;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
case CL_MEM_OBJECT_IMAGE1D:
width = ( imageInfo->width >> lod ) ? (imageInfo->width >> lod) : 1;
}
row_pitch_lod = width * get_pixel_size(imageInfo->format);
slice_pitch_lod = row_pitch_lod * height;
region[0] = width;
region[1] = height;
region[2] = depth;
}
void* mapped = (char*)clEnqueueMapImage(queue, img, CL_TRUE, CL_MAP_WRITE, origin, region, &mappedRow, &mappedSlice, 0, NULL, NULL, error);
if (*error != CL_SUCCESS)
{
log_error( "ERROR: Unable to map image for writing: %s\n", IGetErrorString( *error ) );
return NULL;
}
size_t mappedSlicePad = mappedSlice - (mappedRow * height);
// Copy the image.
size_t scanlineSize = row_pitch_lod;
size_t sliceSize = slice_pitch_lod - scanlineSize * height;
size_t imageSize = scanlineSize * height * depth;
size_t data_lod_offset = 0;
if( gTestMipmaps )
data_lod_offset = compute_mip_level_offset(imageInfo, lod);
char* src = (char*)data + data_lod_offset;
char* dst = (char*)mapped;
if ((mappedRow == scanlineSize) && (mappedSlicePad==0 || (imageInfo->depth==0 && imageInfo->arraySize==0))) {
// Copy the whole image.
memcpy( dst, src, imageSize );
}
else {
// Else copy one scan line at a time.
size_t dstPitch2D = 0;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE3D:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
case CL_MEM_OBJECT_IMAGE2D:
dstPitch2D = mappedRow;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
case CL_MEM_OBJECT_IMAGE1D:
dstPitch2D = mappedSlice;
break;
}
for ( size_t z = 0; z < depth; z++ )
{
for ( size_t y = 0; y < height; y++ )
{
memcpy( dst, src, scanlineSize );
dst += dstPitch2D;
src += scanlineSize;
}
// mappedSlicePad is incorrect for 2D images here, but we will exit the z loop before this is a problem.
dst += mappedSlicePad;
src += sliceSize;
}
}
// Unmap the image.
*error = clEnqueueUnmapMemObject(queue, img, mapped, 0, NULL, NULL);
if (*error != CL_SUCCESS)
{
log_error( "ERROR: Unable to unmap image after writing: %s\n", IGetErrorString( *error ) );
return NULL;
}
}
return img;
}
// WARNING -- not thread safe
BufferOwningPtr<char> srcData;
BufferOwningPtr<char> dstData;
BufferOwningPtr<char> srcHost;
BufferOwningPtr<char> dstHost;
int test_copy_image_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo,
const size_t sourcePos[], const size_t destPos[], const size_t regionSize[], MTdata d )
{
int error;
clMemWrapper srcImage, dstImage;
if( gDebugTrace )
log_info( " ++ Entering inner test loop...\n" );
// Generate some data to test against
size_t srcBytes = 0;
if( gTestMipmaps )
{
srcBytes = (size_t)compute_mipmapped_image_size( *srcImageInfo );
}
else
{
switch (srcImageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
srcBytes = srcImageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE2D:
srcBytes = srcImageInfo->height * srcImageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE3D:
srcBytes = srcImageInfo->depth * srcImageInfo->slicePitch;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
srcBytes = srcImageInfo->arraySize * srcImageInfo->slicePitch;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
srcBytes = srcImageInfo->arraySize * srcImageInfo->slicePitch;
break;
}
}
if (srcBytes > srcData.getSize())
{
if( gDebugTrace )
log_info( " - Resizing random image data...\n" );
generate_random_image_data( srcImageInfo, srcData, d );
// Update the host verification copy of the data.
srcHost.reset(malloc(srcBytes),NULL,0,srcBytes);
if (srcHost == NULL) {
log_error( "ERROR: Unable to malloc %lu bytes for srcHost\n", srcBytes );
return -1;
}
memcpy(srcHost,srcData,srcBytes);
}
// Construct testing sources
if( gDebugTrace )
log_info( " - Writing source image...\n" );
srcImage = create_image( context, srcData, srcImageInfo, &error );
if( srcImage == NULL )
return error;
// Initialize the destination to empty
size_t destImageSize = 0;
if( gTestMipmaps )
{
destImageSize = (size_t)compute_mipmapped_image_size( *dstImageInfo );
}
else
{
switch (dstImageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
destImageSize = dstImageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE2D:
destImageSize = dstImageInfo->height * dstImageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE3D:
destImageSize = dstImageInfo->depth * dstImageInfo->slicePitch;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
destImageSize = dstImageInfo->arraySize * dstImageInfo->slicePitch;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
destImageSize = dstImageInfo->arraySize * dstImageInfo->slicePitch;
break;
}
}
if (destImageSize > dstData.getSize())
{
if( gDebugTrace )
log_info( " - Resizing destination buffer...\n" );
dstData.reset(malloc(destImageSize),NULL,0,destImageSize);
if (dstData == NULL) {
log_error( "ERROR: Unable to malloc %lu bytes for dstData\n", destImageSize );
return -1;
}
dstHost.reset(malloc(destImageSize),NULL,0,destImageSize);
if (dstHost == NULL) {
dstData.reset(NULL);
log_error( "ERROR: Unable to malloc %lu bytes for dstHost\n", destImageSize );
return -1;
}
}
memset( dstData, 0xff, destImageSize );
memset( dstHost, 0xff, destImageSize );
if( gDebugTrace )
log_info( " - Writing destination image...\n" );
dstImage = create_image( context, dstData, dstImageInfo, &error );
if( dstImage == NULL )
return error;
size_t dstRegion[ 3 ] = { dstImageInfo->width, 1, 1};
size_t dst_lod = 0;
size_t origin[ 4 ] = { 0, 0, 0, 0 };
if(gTestMipmaps)
{
switch(dstImageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
dst_lod = destPos[1];
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
case CL_MEM_OBJECT_IMAGE2D:
dst_lod = destPos[2];
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
case CL_MEM_OBJECT_IMAGE3D:
dst_lod = destPos[3];
break;
}
dstRegion[ 0 ] = (dstImageInfo->width >> dst_lod)?(dstImageInfo->width >> dst_lod) : 1;
}
switch (dstImageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
if( gTestMipmaps )
origin[ 1 ] = dst_lod;
break;
case CL_MEM_OBJECT_IMAGE2D:
dstRegion[ 1 ] = dstImageInfo->height;
if( gTestMipmaps )
{
dstRegion[ 1 ] = (dstImageInfo->height >> dst_lod) ?(dstImageInfo->height >> dst_lod): 1;
origin[ 2 ] = dst_lod;
}
break;
case CL_MEM_OBJECT_IMAGE3D:
dstRegion[ 1 ] = dstImageInfo->height;
dstRegion[ 2 ] = dstImageInfo->depth;
if( gTestMipmaps )
{
dstRegion[ 1 ] = (dstImageInfo->height >> dst_lod) ?(dstImageInfo->height >> dst_lod): 1;
dstRegion[ 2 ] = (dstImageInfo->depth >> dst_lod) ?(dstImageInfo->depth >> dst_lod): 1;
origin[ 3 ] = dst_lod;
}
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
dstRegion[ 1 ] = dstImageInfo->arraySize;
if( gTestMipmaps )
origin[ 2 ] = dst_lod;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
dstRegion[ 1 ] = dstImageInfo->height;
dstRegion[ 2 ] = dstImageInfo->arraySize;
if( gTestMipmaps )
{
dstRegion[ 1 ] = (dstImageInfo->height >> dst_lod) ?(dstImageInfo->height >> dst_lod): 1;
origin[ 3 ] = dst_lod;
}
break;
}
size_t region[ 3 ] = { dstRegion[ 0 ], dstRegion[ 1 ], dstRegion[ 2 ] };
// Now copy a subset to the destination image. This is the meat of what we're testing
if( gDebugTrace )
{
if( gTestMipmaps )
{
log_info( " - Copying from %d,%d,%d,%d to %d,%d,%d,%d size %d,%d,%d\n", (int)sourcePos[ 0 ], (int)sourcePos[ 1 ], (int)sourcePos[ 2 ],(int)sourcePos[ 3 ],
(int)destPos[ 0 ], (int)destPos[ 1 ], (int)destPos[ 2 ],(int)destPos[ 3 ],
(int)regionSize[ 0 ], (int)regionSize[ 1 ], (int)regionSize[ 2 ] );
}
else
{
log_info( " - Copying from %d,%d,%d to %d,%d,%d size %d,%d,%d\n", (int)sourcePos[ 0 ], (int)sourcePos[ 1 ], (int)sourcePos[ 2 ],
(int)destPos[ 0 ], (int)destPos[ 1 ], (int)destPos[ 2 ],
(int)regionSize[ 0 ], (int)regionSize[ 1 ], (int)regionSize[ 2 ] );
}
}
error = clEnqueueCopyImage( queue, srcImage, dstImage, sourcePos, destPos, regionSize, 0, NULL, NULL );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to copy image from pos %d,%d,%d to %d,%d,%d size %d,%d,%d! (%s)\n",
(int)sourcePos[ 0 ], (int)sourcePos[ 1 ], (int)sourcePos[ 2 ], (int)destPos[ 0 ], (int)destPos[ 1 ], (int)destPos[ 2 ],
(int)regionSize[ 0 ], (int)regionSize[ 1 ], (int)regionSize[ 2 ], IGetErrorString( error ) );
return error;
}
// Construct the final dest image values to test against
if( gDebugTrace )
log_info( " - Host verification copy...\n" );
copy_image_data( srcImageInfo, dstImageInfo, srcHost, dstHost, sourcePos, destPos, regionSize );
// Map the destination image to verify the results with the host
// copy. The contents of the entire buffer are compared.
if( gDebugTrace )
log_info( " - Mapping results...\n" );
size_t mappedRow, mappedSlice;
void* mapped = (char*)clEnqueueMapImage(queue, dstImage, CL_TRUE, CL_MAP_READ, origin, region, &mappedRow, &mappedSlice, 0, NULL, NULL, &error);
if (error != CL_SUCCESS)
{
log_error( "ERROR: Unable to map image for verification: %s\n", IGetErrorString( error ) );
return error;
}
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = dstHost;
size_t cur_lod_offset = 0;
char *destPtr = (char*)mapped;
if( gTestMipmaps )
{
cur_lod_offset = compute_mip_level_offset(dstImageInfo, dst_lod);
sourcePtr += cur_lod_offset;
}
size_t scanlineSize = dstImageInfo->width * get_pixel_size( dstImageInfo->format );
size_t rowPitch = dstImageInfo->rowPitch;
size_t slicePitch = dstImageInfo->slicePitch;
size_t dst_height_lod = dstImageInfo->height;
if(gTestMipmaps)
{
size_t dst_width_lod = (dstImageInfo->width >> dst_lod)?(dstImageInfo->width >> dst_lod) : 1;
dst_height_lod = (dstImageInfo->height >> dst_lod)?(dstImageInfo->height >> dst_lod) : 1;
scanlineSize = dst_width_lod * get_pixel_size(dstImageInfo->format);
rowPitch = scanlineSize;
slicePitch = rowPitch * dst_height_lod;
}
if( gDebugTrace )
log_info( " - Scanline verification...\n" );
size_t thirdDim;
size_t secondDim;
if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY)
{
secondDim = dstImageInfo->arraySize;
thirdDim = 1;
}
else if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY)
{
secondDim = dstImageInfo->height;
if( gTestMipmaps )
secondDim = (dstImageInfo->height >> dst_lod) ? (dstImageInfo->height >> dst_lod):1;
thirdDim = dstImageInfo->arraySize;
}
else
{
secondDim = dstImageInfo->height;
thirdDim = dstImageInfo->depth;
if( gTestMipmaps )
{
secondDim = (dstImageInfo->height >> dst_lod) ? (dstImageInfo->height >> dst_lod):1;
if(dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D)
thirdDim = (dstImageInfo->depth >> dst_lod) ? (dstImageInfo->depth >> dst_lod):1;
}
}
for( size_t z = 0; z < thirdDim; z++ )
{
for( size_t y = 0; y < secondDim; y++ )
{
if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 )
{
log_error( "ERROR: Scanline %d did not verify for image size %d,%d,%d pitch %d (extra %d bytes)\n", (int)y, (int)dstImageInfo->width, (int)dstImageInfo->height, (int)dstImageInfo->depth, (int)dstImageInfo->rowPitch, (int)dstImageInfo->rowPitch - (int)dstImageInfo->width * (int)get_pixel_size( dstImageInfo->format ) );
// Find the first missing pixel
size_t pixel_size = get_pixel_size( dstImageInfo->format );
size_t where = 0;
for( where = 0; where < dstImageInfo->width; where++ )
if( memcmp( sourcePtr + pixel_size * where, destPtr + pixel_size * where, pixel_size) )
break;
log_error( "Failed at column: %ld ", where );
switch( pixel_size )
{
case 1:
log_error( "*0x%2.2x vs. 0x%2.2x\n", ((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[0] );
break;
case 2:
log_error( "*0x%4.4x vs. 0x%4.4x\n", ((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[0] );
break;
case 3:
log_error( "*{0x%2.2x, 0x%2.2x, 0x%2.2x} vs. {0x%2.2x, 0x%2.2x, 0x%2.2x}\n",
((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(sourcePtr + pixel_size * where))[1], ((cl_uchar*)(sourcePtr + pixel_size * where))[2],
((cl_uchar*)(destPtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[1], ((cl_uchar*)(destPtr + pixel_size * where))[2]
);
break;
case 4:
log_error( "*0x%8.8x vs. 0x%8.8x\n", ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[0] );
break;
case 6:
log_error( "*{0x%4.4x, 0x%4.4x, 0x%4.4x} vs. {0x%4.4x, 0x%4.4x, 0x%4.4x}\n",
((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(sourcePtr + pixel_size * where))[1], ((cl_ushort*)(sourcePtr + pixel_size * where))[2],
((cl_ushort*)(destPtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[1], ((cl_ushort*)(destPtr + pixel_size * where))[2]
);
break;
case 8:
log_error( "*0x%16.16llx vs. 0x%16.16llx\n", ((cl_ulong*)(sourcePtr + pixel_size * where))[0], ((cl_ulong*)(destPtr + pixel_size * where))[0] );
break;
case 12:
log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x}\n",
((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2],
((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2]
);
break;
case 16:
log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x}\n",
((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2], ((cl_uint*)(sourcePtr + pixel_size * where))[3],
((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2], ((cl_uint*)(destPtr + pixel_size * where))[3]
);
break;
default:
log_error( "Don't know how to print pixel size of %ld\n", pixel_size );
break;
}
return -1;
}
sourcePtr += rowPitch;
if((dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY || dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D))
destPtr += mappedSlice;
else
destPtr += mappedRow;
}
sourcePtr += slicePitch - rowPitch * dst_height_lod;
destPtr += mappedSlice - mappedRow * dst_height_lod;
}
// Unmap the image.
error = clEnqueueUnmapMemObject(queue, dstImage, mapped, 0, NULL, NULL);
if (error != CL_SUCCESS)
{
log_error( "ERROR: Unable to unmap image after verify: %s\n", IGetErrorString( error ) );
return error;
}
return 0;
}
int test_copy_image_size_generic( cl_device_id device, image_descriptor *srcImageInfo, image_descriptor *dstImageInfo, MTdata d )
{
size_t sourcePos[ 3 ], destPos[ 3 ], regionSize[ 3 ];
int ret = 0, retCode;
for (int i = 0; i < 8; i++)
{
switch (srcImageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d );
sourcePos[ 1 ] = 1;
sourcePos[ 2 ] = 1;
break;
case CL_MEM_OBJECT_IMAGE2D:
sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d );
sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->height - 4), d );
sourcePos[ 2 ] = 1;
break;
case CL_MEM_OBJECT_IMAGE3D:
sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d );
sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->height - 4), d );
sourcePos[ 2 ] = random_in_range( 0, (int)(srcImageInfo->depth - 4), d );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d );
sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->arraySize - 4), d );
sourcePos[ 2 ] = 1;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
sourcePos[ 0 ] = random_in_range( 0, (int)(srcImageInfo->width - 4), d );
sourcePos[ 1 ] = random_in_range( 0, (int)(srcImageInfo->height - 4), d );
sourcePos[ 2 ] = random_in_range( 0, (int)(srcImageInfo->arraySize - 4), d );
break;
}
switch (dstImageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d );
destPos[ 1 ] = 1;
destPos[ 2 ] = 1;
break;
case CL_MEM_OBJECT_IMAGE2D:
destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d );
destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->height - 4), d );
destPos[ 2 ] = 1;
break;
case CL_MEM_OBJECT_IMAGE3D:
destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d );
destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->height - 4), d );
destPos[ 2 ] = random_in_range( 0, (int)(dstImageInfo->depth - 4), d );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d );
destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->arraySize - 4), d );
destPos[ 2 ] = 1;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
destPos[ 0 ] = random_in_range( 0, (int)(dstImageInfo->width - 4), d );
destPos[ 1 ] = random_in_range( 0, (int)(dstImageInfo->height - 4), d );
destPos[ 2 ] = random_in_range( 0, (int)(dstImageInfo->arraySize - 4), d );
break;
}
if ( (dstImageInfo->width - destPos[0]) < (srcImageInfo->width - sourcePos[0]) )
regionSize[0] = random_in_range(1, (dstImageInfo->width - destPos[0]), d);
else
regionSize[0] = random_in_range(1, (srcImageInfo->width - sourcePos[0]), d);
if (srcImageInfo->type == CL_MEM_OBJECT_IMAGE1D || dstImageInfo->type == CL_MEM_OBJECT_IMAGE1D)
regionSize[1] = 0;
else
{
if ( (dstImageInfo->height - destPos[1]) < (srcImageInfo->height - sourcePos[1]) )
regionSize[1] = random_in_range(1, (dstImageInfo->height - destPos[1]), d);
else
regionSize[1] = random_in_range(1, (srcImageInfo->height - sourcePos[1]), d);
}
regionSize[2] = 0;
if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D && srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D)
{
if ( (dstImageInfo->depth - destPos[2]) < (srcImageInfo->depth - sourcePos[2]) )
regionSize[2] = random_in_range(1, (dstImageInfo->depth - destPos[2]), d);
else
regionSize[2] = random_in_range(1, (srcImageInfo->depth - sourcePos[2]), d);
}
else if ( (dstImageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY && srcImageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY) )
{
if ( (dstImageInfo->arraySize - destPos[2]) < (srcImageInfo->arraySize - sourcePos[2]) )
regionSize[2] = random_in_range(1, (dstImageInfo->arraySize - destPos[2]), d);
else
regionSize[2] = random_in_range(1, (srcImageInfo->arraySize - sourcePos[2]), d);
}
// Go for it!
retCode = test_copy_image_generic( device, srcImageInfo, dstImageInfo, sourcePos, destPos, regionSize, d );
if( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}

View File

@@ -0,0 +1,274 @@
//
// 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"
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern int gTypesToTest;
extern int gNormalizedModeToUse;
extern bool gTestMipmaps;
extern cl_channel_type gChannelTypeToUse;
extern cl_command_queue queue;
extern cl_context context;
extern cl_channel_type gChannelTypeToUse;
extern cl_channel_order gChannelOrderToUse;
extern bool gDebugTrace;
extern int test_copy_image_set_1D( cl_device_id device, cl_image_format *format );
extern int test_copy_image_set_2D( cl_device_id device, cl_image_format *format );
extern int test_copy_image_set_3D( cl_device_id device, cl_image_format *format );
extern int test_copy_image_set_1D_array( cl_device_id device, cl_image_format *format );
extern int test_copy_image_set_2D_array( cl_device_id device, cl_image_format *format );
extern int test_copy_image_set_2D_3D( cl_device_id device, cl_image_format *format, bool reverse );
extern int test_copy_image_set_2D_2D_array( cl_device_id device, cl_image_format *format, bool reverse );
extern int test_copy_image_set_3D_2D_array( cl_device_id device, cl_image_format *format, bool reverse );
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if( filterFlags[ j ] )
filterFlags[ j ] = false;
// Have we already discarded this via the command line?
if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Have we already discarded the channel order via the command line?
if( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
// We don't filter by channel type
if( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags )
{
int error;
cl_image_format tempList[ 128 ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
imageType, 128, tempList, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
imageType, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_image_type( cl_device_id device, MethodsToTest testMethod, cl_mem_flags flags )
{
const char *name;
cl_mem_object_type imageType;
if ( gTestMipmaps )
{
if ( 0 == is_extension_available( device, "cl_khr_mipmap_image" ))
{
log_info( "-----------------------------------------------------\n" );
log_info( "This device does not support cl_khr_mipmap_image.\nSkipping mipmapped image test. \n" );
log_info( "-----------------------------------------------------\n\n" );
return 0;
}
}
if( testMethod == k1D )
{
name = "1D -> 1D";
imageType = CL_MEM_OBJECT_IMAGE1D;
}
else if( testMethod == k2D )
{
name = "2D -> 2D";
imageType = CL_MEM_OBJECT_IMAGE2D;
}
else if( testMethod == k3D )
{
name = "3D -> 3D";
imageType = CL_MEM_OBJECT_IMAGE3D;
}
else if( testMethod == k1DArray )
{
name = "1D array -> 1D array";
imageType = CL_MEM_OBJECT_IMAGE1D_ARRAY;
}
else if( testMethod == k2DArray )
{
name = "2D array -> 2D array";
imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY;
}
else if( testMethod == k2DTo3D )
{
name = "2D -> 3D";
imageType = CL_MEM_OBJECT_IMAGE3D;
}
else if( testMethod == k3DTo2D )
{
name = "3D -> 2D";
imageType = CL_MEM_OBJECT_IMAGE3D;
}
else if( testMethod == k2DArrayTo2D )
{
name = "2D array -> 2D";
imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY;
}
else if( testMethod == k2DTo2DArray )
{
name = "2D -> 2D array";
imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY;
}
else if( testMethod == k2DArrayTo3D )
{
name = "2D array -> 3D";
imageType = CL_MEM_OBJECT_IMAGE3D;
}
else if( testMethod == k3DTo2DArray )
{
name = "3D -> 2D array";
imageType = CL_MEM_OBJECT_IMAGE3D;
}
if(gTestMipmaps)
log_info( "Running mipmapped %s tests...\n", name );
else
log_info( "Running %s tests...\n", name );
int ret = 0;
// Grab the list of supported image formats for integer reads
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
if( get_format_list( device, imageType, formatList, numFormats, flags ) )
return -1;
filterFlags = new bool[ numFormats ];
if( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
memset( filterFlags, 0, sizeof( bool ) * numFormats );
filter_formats(formatList, filterFlags, numFormats, NULL);
// Run the format list
for( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if( filterFlags[i] )
{
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
if( testMethod == k1D )
test_return = test_copy_image_set_1D( device, &formatList[ i ] );
else if( testMethod == k2D )
test_return = test_copy_image_set_2D( device, &formatList[ i ] );
else if( testMethod == k3D )
test_return = test_copy_image_set_3D( device, &formatList[ i ] );
else if( testMethod == k1DArray )
test_return = test_copy_image_set_1D_array( device, &formatList[ i ] );
else if( testMethod == k2DArray )
test_return = test_copy_image_set_2D_array( device, &formatList[ i ] );
else if( testMethod == k2DTo3D )
test_return = test_copy_image_set_2D_3D( device, &formatList[ i ], false );
else if( testMethod == k3DTo2D )
test_return = test_copy_image_set_2D_3D( device, &formatList[ i ], true );
else if( testMethod == k2DArrayTo2D)
test_return = test_copy_image_set_2D_2D_array( device, &formatList[ i ], true);
else if( testMethod == k2DTo2DArray)
test_return = test_copy_image_set_2D_2D_array( device, &formatList[ i ], false);
else if( testMethod == k2DArrayTo3D)
test_return = test_copy_image_set_3D_2D_array( device, &formatList[ i ], true);
else if( testMethod == k3DTo2DArray)
test_return = test_copy_image_set_3D_2D_array( device, &formatList[ i ], false);
if (test_return) {
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
delete filterFlags;
delete formatList;
return ret;
}
int test_image_set( cl_device_id device, MethodsToTest testMethod )
{
int ret = 0;
ret += test_image_type( device, testMethod, CL_MEM_READ_ONLY );
return ret;
}

View File

@@ -0,0 +1,26 @@
set(MODULE_NAME CL_FILL_IMAGES)
set(${MODULE_NAME}_SOURCES
main.cpp
test_fill_1D.cpp
test_fill_1D_array.cpp
test_fill_2D.cpp
test_fill_2D_array.cpp
test_fill_generic.cpp
test_loops.cpp
test_fill_3D.cpp
# test_fill_2D_3D.cpp
../../../test_common/harness/testHarness.c
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,19 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_cl_fill_images
: main.cpp
test_fill_2D_3D.cpp
test_fill_2D.cpp
test_fill_3D.cpp
test_loops.cpp
;
install dist
: test_cl_fill_images
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/clFillImage
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/clFillImage
;

View File

@@ -0,0 +1,53 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_fill_generic.cpp \
test_fill_1D.cpp \
test_fill_2D.cpp \
test_fill_3D.cpp \
test_fill_1D_array.cpp \
test_fill_2D_array.cpp \
test_loops.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.cpp \
../../../test_common/harness/typeWrappers.cpp \
../../../test_common/harness/mt19937.c
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_cl_fill_images
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = 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,281 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
#include "../../../test_common/harness/testHarness.h"
bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false, gEnablePitch = false;
int gTypesToTest = 0;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
cl_channel_order gChannelOrderToUse = (cl_channel_order)-1;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
cl_context context;
cl_command_queue queue;
static cl_device_id device;
extern int test_image_set( cl_device_id device, MethodsToTest testMethod );
static void printUsage( const char *execName );
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
int test_1D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set(device, k1D);
}
int test_2D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set(device, k2D);
}
int test_1Darray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set(device, k1DArray);
}
int test_2Darray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set(device, k2DArray);
}
int test_3D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set(device, k3D);
}
basefn basefn_list[] = {
test_1D,
test_2D,
test_1Darray,
test_2Darray,
test_3D,
};
const char *basefn_names[] = {
"1D",
"2D",
"1Darray",
"2Darray",
"3D",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_channel_type chanType;
cl_channel_order chanOrder;
bool randomize = false;
test_start();
checkDeviceTypeOverride( &gDeviceType );
const char ** argList = (const char **)calloc( argc, sizeof( char*) );
if( NULL == argList )
{
log_error( "Failed to allocate memory for argList array.\n" );
return 1;
}
argList[0] = argv[0];
size_t argCount = 1;
// Parse arguments
for ( int i = 1; i < argc; i++ )
{
if ( strcmp( argv[i], "cpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if ( strcmp( argv[i], "gpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if ( strcmp( argv[i], "accelerator" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if ( strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if ( strcmp( argv[i], "debug_trace" ) == 0 )
gDebugTrace = true;
else if ( strcmp( argv[i], "small_images" ) == 0 )
gTestSmallImages = true;
else if ( strcmp( argv[i], "max_images" ) == 0 )
gTestMaxImages = true;
else if ( strcmp( argv[i], "use_pitches" ) == 0 )
gEnablePitch = true;
else if ( strcmp( argv[i], "randomize" ) == 0 )
randomize = true;
else if( strcmp( argv[i], "int" ) == 0 )
gTypesToTest |= kTestInt;
else if( strcmp( argv[i], "uint" ) == 0 )
gTypesToTest |= kTestUInt;
else if( strcmp( argv[i], "float" ) == 0 )
gTypesToTest |= kTestFloat;
else if ( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if ( ( chanType = get_channel_type_from_name( argv[i] ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else if ( ( chanOrder = get_channel_order_from_name( argv[i] ) ) != (cl_channel_order)-1 )
gChannelOrderToUse = chanOrder;
else
{
argList[argCount] = argv[i];
argCount++;
}
}
if ( gTypesToTest == 0 )
gTypesToTest = kTestAllTypes;
// Seed the random # generators
if ( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
log_info( "Random seed: %u.\n", gRandomSeed );
gReSeed = 1;
}
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if ( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
error = clGetDeviceIDs(platform, gDeviceType, 1, &device, NULL );
if ( error )
{
print_error( error, "Unable to get specified device" );
test_finish();
return -1;
}
char deviceName[ 128 ], deviceVendor[ 128 ], deviceVersion[ 128 ];
error = clGetDeviceInfo( device, CL_DEVICE_NAME, sizeof( deviceName ), deviceName, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_VENDOR, sizeof( deviceVendor ), deviceVendor, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof( deviceVersion ), deviceVersion, NULL );
if ( error != CL_SUCCESS )
{
print_error( error, "Unable to get device information" );
test_finish();
return -1;
}
log_info("Using compute device: Name = %s, Vendor = %s, Version = %s\n", deviceName, deviceVendor, deviceVersion );
// Check for image support
if (checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) {
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if ( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if ( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if ( gTestSmallImages )
log_info( "Note: Using small test images\n" );
int ret = parseAndCallCommandLineTests( argCount, argList, NULL, num_fns, basefn_list, basefn_names, true, 0, 0 );
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.");
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d sub-tests.\n", gTestCount, gTestCount);
else
log_info("PASSED sub-test.\n");
}
else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d sub-tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED sub-test.\n");
}
// Clean up
clReleaseCommandQueue(queue);
clReleaseContext(context);
free(argList);
test_finish();
return ret;
}
static void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if ( p != NULL )
execName = p + 1;
log_info( "Usage: %s [options] [test_names]\n", execName );
log_info( "Options:\n" );
log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" );
log_info( "\t\tint - Test integer fill\n" );
log_info( "\t\tuint - Test unsigned integer fill\n" );
log_info( "\t\tfloat - Test float fill\n" );
log_info( "\n" );
log_info( "\trandomize - Uses random seed\n" );
log_info( "\tdebug_trace - Enables additional debug info logging\n" );
log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
log_info( "\tuse_pitches - Enables row and slice pitches\n" );
log_info( "\n" );
log_info( "Test names:\n" );
for( int i = 0; i < num_fns; i++ )
{
log_info( "\t%s\n", basefn_names[i] );
}
log_info( "\n" );
log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" );
}

View File

@@ -0,0 +1,181 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_fill_2D_3D.cpp
extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo,
const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d );
int test_fill_image_size_1D( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d )
{
size_t origin[ 3 ], region[ 3 ];
int ret = 0, retCode;
// First, try just a full covering region fill
origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0;
region[ 0 ] = imageInfo->width;
region[ 1 ] = 1;
region[ 2 ] = 1;
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for ( int i = 0; i < 8; i++ )
{
// Pick a random size
region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width;
// Now pick positions within valid ranges
origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_fill_image_set_1D( cl_device_id device, cl_image_format *format, ExplicitType outputType )
{
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed(gRandomSeed);
const size_t rowPadding_default = 48;
size_t rowPadding = gEnablePitch ? rowPadding_default : 0;
size_t pixelSize;
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
if ( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int ret = test_fill_image_size_1D( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
log_info( "Testing %d\n", (int)sizes[ idx ][ 0 ] );
if ( gDebugTrace )
log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] );
if ( test_fill_image_size_1D( device, &imageInfo, outputType, seed ) )
return -1;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
size = (size_t)imageInfo.rowPitch * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
int ret = test_fill_image_size_1D( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,193 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_fill_2D_3D.cpp
extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo,
const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d );
int test_fill_image_size_1D_array( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d )
{
size_t origin[ 3 ], region[ 3 ];
int ret = 0, retCode;
// First, try just a full covering region fill
origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0;
region[ 0 ] = imageInfo->width;
region[ 1 ] = imageInfo->arraySize;
region[ 2 ] = 1;
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for ( int i = 0; i < 8; i++ )
{
// Pick a random size
region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width;
region[ 1 ] = ( imageInfo->arraySize > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->arraySize - 1, d ) : imageInfo->arraySize;
// Now pick positions within valid ranges
origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0;
origin[ 1 ] = ( imageInfo->arraySize > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - region[ 1 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_fill_image_set_1D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType )
{
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed(gRandomSeed);
const size_t rowPadding_default = 48;
size_t rowPadding = gEnablePitch ? rowPadding_default : 0;
size_t pixelSize;
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch;
for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize );
int ret = test_fill_image_size_1D_array( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch;
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
if ( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
if ( test_fill_image_size_1D_array( device, &imageInfo, outputType, seed ) )
return -1;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch;
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
int ret = test_fill_image_size_1D_array( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,189 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_fill_2D_3D.cpp
extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo,
const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d );
int test_fill_image_size_2D( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d )
{
size_t origin[ 3 ], region[ 3 ];
int ret = 0, retCode;
// First, try just a full covering region fill
origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0;
region[ 0 ] = imageInfo->width;
region[ 1 ] = imageInfo->height;
region[ 2 ] = 1;
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for ( int i = 0; i < 8; i++ )
{
// Pick a random size
region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width;
region[ 1 ] = ( imageInfo->height > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->height - 1, d ) : imageInfo->height;
// Now pick positions within valid ranges
origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0;
origin[ 1 ] = ( imageInfo->height > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->height - region[ 1 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_fill_image_set_2D( cl_device_id device, cl_image_format *format, ExplicitType outputType )
{
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed(gRandomSeed);
const size_t rowPadding_default = 48;
size_t rowPadding = gEnablePitch ? rowPadding_default : 0;
size_t pixelSize;
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int ret = test_fill_image_size_2D( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
if ( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
if ( test_fill_image_size_2D( device, &imageInfo, outputType, seed ) )
return -1;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
int ret = test_fill_image_size_2D( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,200 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_fill_2D_3D.cpp
extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo,
const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d );
static int test_fill_image_2D_array( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d )
{
size_t origin[ 3 ], region[ 3 ];
int ret = 0, retCode;
// First, try just a full covering region
origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0;
region[ 0 ] = imageInfo->width;
region[ 1 ] = imageInfo->height;
region[ 2 ] = imageInfo->arraySize;
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for ( int i = 0; i < 8; i++ )
{
// Pick a random size
region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width;
region[ 1 ] = ( imageInfo->height > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->height - 1, d ) : imageInfo->height;
region[ 2 ] = ( imageInfo->arraySize > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->arraySize - 1, d ) : imageInfo->arraySize;
// Now pick positions within valid ranges
origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0;
origin[ 1 ] = ( imageInfo->height > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->height - region[ 1 ] - 1 ), d ) : 0;
origin[ 2 ] = ( imageInfo->arraySize > region[ 2 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->arraySize - region[ 2 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_fill_image_set_2D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType )
{
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
const size_t rowPadding_default = 80;
size_t rowPadding = gEnablePitch ? rowPadding_default : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
size_t pixelSize;
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize );
int ret = test_fill_image_2D_array( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if ( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if ( test_fill_image_2D_array( device, &imageInfo, outputType, seed ) )
return -1;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 64, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 64, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32,seed );
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize );
int ret = test_fill_image_2D_array( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,200 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gEnablePitch, gTestRounding;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern cl_command_queue queue;
extern cl_context context;
// Defined in test_fill_2D_3D.cpp
extern int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo,
const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d );
int test_fill_image_3D( cl_device_id device, image_descriptor *imageInfo, ExplicitType outputType, MTdata d )
{
size_t origin[ 3 ], region[ 3 ];
int ret = 0, retCode;
// First, try just a full covering region
origin[ 0 ] = origin[ 1 ] = origin[ 2 ] = 0;
region[ 0 ] = imageInfo->width;
region[ 1 ] = imageInfo->height;
region[ 2 ] = imageInfo->depth;
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
// Now try a sampling of different random regions
for ( int i = 0; i < 8; i++ )
{
// Pick a random size
region[ 0 ] = ( imageInfo->width > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->width - 1, d ) : imageInfo->width;
region[ 1 ] = ( imageInfo->height > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->height - 1, d ) : imageInfo->height;
region[ 2 ] = ( imageInfo->depth > 8 ) ? (size_t)random_in_range( 8, (int)imageInfo->depth - 1, d ) : imageInfo->depth;
// Now pick positions within valid ranges
origin[ 0 ] = ( imageInfo->width > region[ 0 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->width - region[ 0 ] - 1 ), d ) : 0;
origin[ 1 ] = ( imageInfo->height > region[ 1 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->height - region[ 1 ] - 1 ), d ) : 0;
origin[ 2 ] = ( imageInfo->depth > region[ 2 ] ) ? (size_t)random_in_range( 0, (int)( imageInfo->depth - region[ 2 ] - 1 ), d ) : 0;
// Go for it!
retCode = test_fill_image_generic( device, imageInfo, origin, region, outputType, d );
if ( retCode < 0 )
return retCode;
else
ret += retCode;
}
return ret;
}
int test_fill_image_set_3D( cl_device_id device, cl_image_format *format, ExplicitType outputType )
{
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
const size_t rowPadding_default = 80;
size_t rowPadding = gEnablePitch ? rowPadding_default : 0;
size_t slicePadding = gEnablePitch ? 3 : 0;
size_t pixelSize;
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
for ( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth );
int ret = test_fill_image_3D( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.depth = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if ( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if ( test_fill_image_3D( device, &imageInfo, outputType, seed ) )
return -1;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
if (gEnablePitch)
{
rowPadding = rowPadding_default;
do {
rowPadding++;
imageInfo.rowPitch = imageInfo.width * pixelSize + rowPadding;
} while ((imageInfo.rowPitch % pixelSize) != 0);
}
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + slicePadding);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth );
int ret = test_fill_image_3D( device, &imageInfo, outputType, seed );
if ( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,556 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gTestMaxImages, gTestRounding, gEnablePitch;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
extern void read_image_pixel_float( void *imageData, image_descriptor *imageInfo, int x, int y, int z, float *outData );
static void CL_CALLBACK free_pitch_buffer( cl_mem image, void *buf )
{
free( buf );
}
cl_mem create_image( cl_context context, BufferOwningPtr<char>& data, image_descriptor *imageInfo, int *error )
{
cl_mem img;
cl_image_desc imageDesc;
cl_mem_flags mem_flags = CL_MEM_READ_ONLY;
void *host_ptr = NULL;
memset(&imageDesc, 0x0, sizeof(cl_image_desc));
imageDesc.image_type = imageInfo->type;
imageDesc.image_width = imageInfo->width;
imageDesc.image_height = imageInfo->height;
imageDesc.image_depth = imageInfo->depth;
imageDesc.image_array_size = imageInfo->arraySize;
imageDesc.image_row_pitch = gEnablePitch ? imageInfo->rowPitch : 0;
imageDesc.image_slice_pitch = gEnablePitch ? imageInfo->slicePitch : 0;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
if ( gDebugTrace )
log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->rowPitch );
break;
case CL_MEM_OBJECT_IMAGE2D:
if ( gDebugTrace )
log_info( " - Creating 2D image %d by %d ...\n", (int)imageInfo->width, (int)imageInfo->height );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->height * imageInfo->rowPitch );
break;
case CL_MEM_OBJECT_IMAGE3D:
if ( gDebugTrace )
log_info( " - Creating 3D image %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->depth * imageInfo->slicePitch );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
if ( gDebugTrace )
log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
if ( gDebugTrace )
log_info( " - Creating 2D image array %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize );
if ( gEnablePitch )
host_ptr = malloc( imageInfo->arraySize * imageInfo->slicePitch );
break;
}
if (gEnablePitch)
{
if ( NULL == host_ptr )
{
log_error( "ERROR: Unable to create backing store for pitched 3D image. %ld bytes\n", imageInfo->depth * imageInfo->slicePitch );
return NULL;
}
mem_flags = CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR;
}
img = clCreateImage(context, mem_flags, imageInfo->format, &imageDesc, host_ptr, error);
if (gEnablePitch)
{
if ( *error == CL_SUCCESS )
{
int callbackError = clSetMemObjectDestructorCallback( img, free_pitch_buffer, host_ptr );
if ( CL_SUCCESS != callbackError )
{
free( host_ptr );
log_error( "ERROR: Unable to attach destructor callback to pitched 3D image. Err: %d\n", callbackError );
clReleaseMemObject( img );
return NULL;
}
}
else
free(host_ptr);
}
if ( *error != CL_SUCCESS )
{
long long unsigned imageSize = get_image_size_mb( imageInfo );
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
log_error( "ERROR: Unable to create 1D image of size %d (%llu MB): %s\n", (int)imageInfo->width, imageSize, IGetErrorString( *error ) );
break;
case CL_MEM_OBJECT_IMAGE2D:
log_error( "ERROR: Unable to create 2D image of size %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->height, imageSize, IGetErrorString( *error ) );
break;
case CL_MEM_OBJECT_IMAGE3D:
log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, imageSize, IGetErrorString( *error ) );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
log_error( "ERROR: Unable to create 1D image array of size %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->arraySize, imageSize, IGetErrorString( *error ) );
break;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%llu MB): %s\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, imageSize, IGetErrorString( *error ) );
break;
}
return NULL;
}
// Copy the specified data to the image via a Map operation.
size_t mappedRow, mappedSlice;
size_t height;
size_t depth;
size_t imageSize = 0;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
height = imageInfo->arraySize;
depth = 1;
imageSize = imageInfo->rowPitch * imageInfo->arraySize;
break;
case CL_MEM_OBJECT_IMAGE1D:
height = depth = 1;
imageSize = imageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE2D:
height = imageInfo->height;
depth = 1;
imageSize = imageInfo->rowPitch * imageInfo->height;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
height = imageInfo->height;
depth = imageInfo->arraySize;
imageSize = imageInfo->slicePitch * imageInfo->arraySize;
break;
case CL_MEM_OBJECT_IMAGE3D:
height = imageInfo->height;
depth = imageInfo->depth;
imageSize = imageInfo->slicePitch * imageInfo->depth;
break;
}
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, height, depth };
void* mapped = (char*)clEnqueueMapImage(queue, img, CL_TRUE, CL_MAP_WRITE, origin, region, &mappedRow, &mappedSlice, 0, NULL, NULL, error);
if (*error != CL_SUCCESS || !mapped)
{
log_error( "ERROR: Unable to map image for writing: %s\n", IGetErrorString( *error ) );
return NULL;
}
size_t mappedSlicePad = mappedSlice - (mappedRow * height);
// Copy the image.
size_t scanlineSize = imageInfo->rowPitch;
size_t sliceSize = imageInfo->slicePitch - scanlineSize * height;
char* src = (char*)data;
char* dst = (char*)mapped;
if ((mappedRow == scanlineSize) && ((mappedSlice == imageInfo->slicePitch) || (imageInfo->depth==0 && imageInfo->arraySize==0))) {
// Copy the whole image.
memcpy( dst, src, imageSize );
}
else {
// Else copy one scan line at a time.
for ( size_t z = 0; z < depth; z++ )
{
for ( size_t y = 0; y < height; y++ )
{
memcpy( dst, src, imageInfo->width * get_pixel_size(imageInfo->format) );
dst += mappedRow;
src += scanlineSize;
}
// mappedSlicePad is incorrect for 2D images here, but we will exit the z loop before this is a problem.
dst += mappedSlicePad;
src += sliceSize;
}
}
// Unmap the image.
*error = clEnqueueUnmapMemObject(queue, img, mapped, 0, NULL, NULL);
if (*error != CL_SUCCESS)
{
log_error( "ERROR: Unable to unmap image after writing: %s\n", IGetErrorString( *error ) );
return NULL;
}
return img;
}
static void fill_region_with_value( image_descriptor *imageInfo, void *imageValues,
void *value, const size_t origin[], const size_t region[] )
{
size_t pixelSize = get_pixel_size( imageInfo->format );
// Get initial pointer
char *destPtr = (char *)imageValues + origin[ 2 ] * imageInfo->slicePitch
+ origin[ 1 ] * imageInfo->rowPitch + pixelSize * origin[ 0 ];
char *fillColor = (char *)malloc(pixelSize);
memcpy(fillColor, value, pixelSize);
// Use pixel at origin to fill region.
for( size_t z = 0; z < ( region[ 2 ] > 0 ? region[ 2 ] : 1 ); z++ ) {
char *rowDestPtr = destPtr;
for( size_t y = 0; y < region[ 1 ]; y++ ) {
char *pixelDestPtr = rowDestPtr;
for( size_t x = 0; x < region[ 0 ]; x++ ) {
memcpy( pixelDestPtr, fillColor, pixelSize );
pixelDestPtr += pixelSize;
}
rowDestPtr += imageInfo->rowPitch;
}
destPtr += imageInfo->slicePitch;
}
free(fillColor);
}
int test_fill_image_generic( cl_device_id device, image_descriptor *imageInfo,
const size_t origin[], const size_t region[], ExplicitType outputType, MTdata d )
{
BufferOwningPtr<char> imgData;
BufferOwningPtr<char> imgHost;
int error;
clMemWrapper image;
if ( gDebugTrace )
log_info( " ++ Entering inner test loop...\n" );
// Generate some data to test against
size_t dataBytes = 0;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
dataBytes = imageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE2D:
dataBytes = imageInfo->height * imageInfo->rowPitch;
break;
case CL_MEM_OBJECT_IMAGE3D:
dataBytes = imageInfo->depth * imageInfo->slicePitch;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
dataBytes = imageInfo->arraySize * imageInfo->slicePitch;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
dataBytes = imageInfo->arraySize * imageInfo->slicePitch;
break;
}
if (dataBytes > imgData.getSize())
{
if ( gDebugTrace )
log_info( " - Resizing random image data...\n" );
generate_random_image_data( imageInfo, imgData, d );
imgHost.reset( NULL ); // Free previously allocated memory first.
imgHost.reset(malloc(dataBytes),NULL,0,dataBytes);
if (imgHost == NULL)
{
log_error( "ERROR: Unable to malloc %lu bytes for imgHost\n", dataBytes );
return -1;
}
}
// Reset the host verification copy of the data.
memcpy(imgHost, imgData, dataBytes);
// Construct testing sources
if ( gDebugTrace )
log_info( " - Creating image...\n" );
image = create_image( context, imgData, imageInfo, &error );
if ( image == NULL )
return error;
// Now fill the region defined by origin, region with the pixel value found at origin.
if ( gDebugTrace )
log_info( " - Filling at %d,%d,%d size %d,%d,%d\n", (int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ],
(int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ] );
// We need to know the rounding mode, in the case of half to allow the
// pixel pack that generates the verification value to succeed.
if (imageInfo->format->image_channel_data_type == CL_HALF_FLOAT)
DetectFloatToHalfRoundingMode(queue);
if( outputType == kFloat )
{
cl_float fillColor[ 4 ];
read_image_pixel_float( imgHost, imageInfo, origin[ 0 ], origin[ 1 ], origin[ 2 ], fillColor );
if ( gDebugTrace )
log_info( " - with value %g, %g, %g, %g\n", fillColor[ 0 ], fillColor[ 1 ], fillColor[ 2 ], fillColor[ 3 ] );
error = clEnqueueFillImage ( queue, image, fillColor, origin, region, 0, NULL, NULL );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to fill image at %d,%d,%d size %d,%d,%d! (%s)\n",
(int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ],
(int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ], IGetErrorString( error ) );
return error;
}
// Write the approriate verification value to the correct region.
void* verificationValue = malloc(get_pixel_size(imageInfo->format));
pack_image_pixel(fillColor, imageInfo->format, verificationValue);
fill_region_with_value( imageInfo, imgHost, verificationValue, origin, region );
free(verificationValue);
}
else if( outputType == kInt )
{
cl_int fillColor[ 4 ];
read_image_pixel<cl_int>( imgHost, imageInfo, origin[ 0 ], origin[ 1 ], origin[ 2 ], fillColor );
if ( gDebugTrace )
log_info( " - with value %d, %d, %d, %d\n", fillColor[ 0 ], fillColor[ 1 ], fillColor[ 2 ], fillColor[ 3 ] );
error = clEnqueueFillImage ( queue, image, fillColor, origin, region, 0, NULL, NULL );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to fill image at %d,%d,%d size %d,%d,%d! (%s)\n",
(int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ],
(int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ], IGetErrorString( error ) );
return error;
}
// Write the approriate verification value to the correct region.
void* verificationValue = malloc(get_pixel_size(imageInfo->format));
pack_image_pixel(fillColor, imageInfo->format, verificationValue);
fill_region_with_value( imageInfo, imgHost, verificationValue, origin, region );
free(verificationValue);
}
else // if( outputType == kUInt )
{
cl_uint fillColor[ 4 ];
read_image_pixel<cl_uint>( imgHost, imageInfo, origin[ 0 ], origin[ 1 ], origin[ 2 ], fillColor );
if ( gDebugTrace )
log_info( " - with value %u, %u, %u, %u\n", fillColor[ 0 ], fillColor[ 1 ], fillColor[ 2 ], fillColor[ 3 ] );
error = clEnqueueFillImage ( queue, image, fillColor, origin, region, 0, NULL, NULL );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to fill image at %d,%d,%d size %d,%d,%d! (%s)\n",
(int)origin[ 0 ], (int)origin[ 1 ], (int)origin[ 2 ],
(int)region[ 0 ], (int)region[ 1 ], (int)region[ 2 ], IGetErrorString( error ) );
return error;
}
// Write the approriate verification value to the correct region.
void* verificationValue = malloc(get_pixel_size(imageInfo->format));
pack_image_pixel(fillColor, imageInfo->format, verificationValue);
fill_region_with_value( imageInfo, imgHost, verificationValue, origin, region );
free(verificationValue);
}
// Map the destination image to verify the results with the host
// copy. The contents of the entire buffer are compared.
if ( gDebugTrace )
log_info( " - Mapping results...\n" );
size_t imageOrigin[ 3 ] = { 0, 0, 0 };
size_t imageRegion[ 3 ] = { imageInfo->width, 1, 1 };
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
break;
case CL_MEM_OBJECT_IMAGE2D:
imageRegion[ 1 ] = imageInfo->height;
break;
case CL_MEM_OBJECT_IMAGE3D:
imageRegion[ 1 ] = imageInfo->height;
imageRegion[ 2 ] = imageInfo->depth;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
imageRegion[ 1 ] = imageInfo->arraySize;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
imageRegion[ 1 ] = imageInfo->height;
imageRegion[ 2 ] = imageInfo->arraySize;
break;
}
size_t mappedRow, mappedSlice;
void* mapped = (char*)clEnqueueMapImage(queue, image, CL_TRUE, CL_MAP_READ, imageOrigin, imageRegion, &mappedRow, &mappedSlice, 0, NULL, NULL, &error);
if (error != CL_SUCCESS)
{
log_error( "ERROR: Unable to map image for verification: %s\n", IGetErrorString( error ) );
return NULL;
}
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = imgHost;
char *destPtr = (char*)mapped;
size_t scanlineSize = imageInfo->width * get_pixel_size( imageInfo->format );
if ( gDebugTrace )
log_info( " - Scanline verification...\n" );
size_t thirdDim = 1;
size_t secondDim = 1;
switch (imageInfo->type) {
case CL_MEM_OBJECT_IMAGE1D:
secondDim = 1;
thirdDim = 1;
break;
case CL_MEM_OBJECT_IMAGE2D:
secondDim = imageInfo->height;
thirdDim = 1;
break;
case CL_MEM_OBJECT_IMAGE3D:
secondDim = imageInfo->height;
thirdDim = imageInfo->depth;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
secondDim = imageInfo->arraySize;
thirdDim = 1;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
secondDim = imageInfo->height;
thirdDim = imageInfo->arraySize;
break;
default:
log_error("Test error: unhandled image type at %s:%d\n",__FILE__,__LINE__);
};
// Count the number of bytes successfully matched
size_t total_matched = 0;
for ( size_t z = 0; z < thirdDim; z++ )
{
for ( size_t y = 0; y < secondDim; y++ )
{
// If the data type is 101010 ignore bits 31 and 32 when comparing the row
if (imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010) {
for (size_t w=0;w!=scanlineSize/4;++w) {
((cl_uint*)sourcePtr)[w] &= 0x3FFFFFFF;
((cl_uint*)destPtr)[w] &= 0x3FFFFFFF;
}
}
if (memcmp( sourcePtr, destPtr, scanlineSize ) != 0)
{
log_error( "ERROR: Scanline %d did not verify for image size %d,%d,%d pitch %d (extra %d bytes)\n", (int)y, (int)imageInfo->width, (int)imageInfo->height, (int)thirdDim, (int)imageInfo->rowPitch, (int)imageInfo->rowPitch - (int)imageInfo->width * (int)get_pixel_size( imageInfo->format ) );
// Find the first missing pixel
size_t pixel_size = get_pixel_size( imageInfo->format );
size_t where = 0;
for ( where = 0; where < imageInfo->width; where++ )
if ( memcmp( sourcePtr + pixel_size * where, destPtr + pixel_size * where, pixel_size) )
break;
log_error( "Failed at column: %ld ", where );
switch ( pixel_size )
{
case 1:
log_error( "*0x%2.2x vs. 0x%2.2x\n", ((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[0] );
break;
case 2:
log_error( "*0x%4.4x vs. 0x%4.4x\n", ((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[0] );
break;
case 3:
log_error( "*{0x%2.2x, 0x%2.2x, 0x%2.2x} vs. {0x%2.2x, 0x%2.2x, 0x%2.2x}\n",
((cl_uchar*)(sourcePtr + pixel_size * where))[0], ((cl_uchar*)(sourcePtr + pixel_size * where))[1], ((cl_uchar*)(sourcePtr + pixel_size * where))[2],
((cl_uchar*)(destPtr + pixel_size * where))[0], ((cl_uchar*)(destPtr + pixel_size * where))[1], ((cl_uchar*)(destPtr + pixel_size * where))[2]
);
break;
case 4:
log_error( "*0x%8.8x vs. 0x%8.8x\n", ((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[0] );
break;
case 6:
log_error( "*{0x%4.4x, 0x%4.4x, 0x%4.4x} vs. {0x%4.4x, 0x%4.4x, 0x%4.4x}\n",
((cl_ushort*)(sourcePtr + pixel_size * where))[0], ((cl_ushort*)(sourcePtr + pixel_size * where))[1], ((cl_ushort*)(sourcePtr + pixel_size * where))[2],
((cl_ushort*)(destPtr + pixel_size * where))[0], ((cl_ushort*)(destPtr + pixel_size * where))[1], ((cl_ushort*)(destPtr + pixel_size * where))[2]
);
break;
case 8:
log_error( "*0x%16.16llx vs. 0x%16.16llx\n", ((cl_ulong*)(sourcePtr + pixel_size * where))[0], ((cl_ulong*)(destPtr + pixel_size * where))[0] );
break;
case 12:
log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x}\n",
((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2],
((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2]
);
break;
case 16:
log_error( "*{0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x} vs. {0x%8.8x, 0x%8.8x, 0x%8.8x, 0x%8.8x}\n",
((cl_uint*)(sourcePtr + pixel_size * where))[0], ((cl_uint*)(sourcePtr + pixel_size * where))[1], ((cl_uint*)(sourcePtr + pixel_size * where))[2], ((cl_uint*)(sourcePtr + pixel_size * where))[3],
((cl_uint*)(destPtr + pixel_size * where))[0], ((cl_uint*)(destPtr + pixel_size * where))[1], ((cl_uint*)(destPtr + pixel_size * where))[2], ((cl_uint*)(destPtr + pixel_size * where))[3]
);
break;
default:
log_error( "Don't know how to print pixel size of %ld\n", pixel_size );
break;
}
return -1;
}
total_matched += scanlineSize;
sourcePtr += imageInfo->rowPitch;
destPtr += mappedRow;
}
sourcePtr += imageInfo->slicePitch - ( imageInfo->rowPitch * (imageInfo->height > 0 ? imageInfo->height : 1) );
destPtr += mappedSlice - ( mappedRow * (imageInfo->height > 0 ? imageInfo->height : 1) );
}
// Unmap the image.
error = clEnqueueUnmapMemObject(queue, image, mapped, 0, NULL, NULL);
if (error != CL_SUCCESS)
{
log_error( "ERROR: Unable to unmap image after verify: %s\n", IGetErrorString( error ) );
return NULL;
}
imgHost.reset(0x0);
imgData.reset(0x0);
size_t expected_bytes = scanlineSize * imageRegion[1] * imageRegion[2];
return (total_matched == expected_bytes) ? 0 : -1;
}

View File

@@ -0,0 +1,327 @@
//
// 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"
extern bool gDebugTrace;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern int gTypesToTest;
extern int gNormalizedModeToUse;
extern cl_channel_type gChannelTypeToUse;
extern cl_channel_order gChannelOrderToUse;
extern cl_command_queue queue;
extern cl_context context;
extern int test_fill_image_set_1D( cl_device_id device, cl_image_format *format, ExplicitType outputType );
extern int test_fill_image_set_2D( cl_device_id device, cl_image_format *format, ExplicitType outputType );
extern int test_fill_image_set_3D( cl_device_id device, cl_image_format *format, ExplicitType outputType );
extern int test_fill_image_set_1D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType );
extern int test_fill_image_set_2D_array( cl_device_id device, cl_image_format *format, ExplicitType outputType );
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for ( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if ( filterFlags[ j ] )
filterFlags[ j ] = false;
// Have we already discarded this via the command line?
if ( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Have we already discarded the channel order via the command line?
if ( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
// We don't filter by channel type
if( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for ( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if ( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if ( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type image_type, cl_image_format * &outFormatList,
unsigned int &outFormatCount, cl_mem_flags flags )
{
int error;
cl_image_format tempList[ 128 ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
image_type, 128, tempList, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
image_type, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_image_type( cl_device_id device, MethodsToTest testMethod, cl_mem_flags flags )
{
const char *name;
cl_mem_object_type imageType;
if ( testMethod == k1D )
{
name = "1D Image Fill";
imageType = CL_MEM_OBJECT_IMAGE1D;
}
else if ( testMethod == k2D )
{
name = "2D Image Fill";
imageType = CL_MEM_OBJECT_IMAGE2D;
}
else if ( testMethod == k1DArray )
{
name = "1D Image Array Fill";
imageType = CL_MEM_OBJECT_IMAGE1D_ARRAY;
}
else if ( testMethod == k2DArray )
{
name = "2D Image Array Fill";
imageType = CL_MEM_OBJECT_IMAGE2D_ARRAY;
}
else if ( testMethod == k3D )
{
name = "3D Image Fill";
imageType = CL_MEM_OBJECT_IMAGE3D;
}
log_info( "Running %s tests...\n", name );
int ret = 0;
// Grab the list of supported image formats
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
if ( get_format_list( device, imageType, formatList, numFormats, flags ) )
return -1;
filterFlags = new bool[ numFormats ];
if ( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
memset( filterFlags, 0, sizeof( bool ) * numFormats );
/////// float tests ///////
if( gTypesToTest & kTestFloat )
{
cl_channel_type floatFormats[] = { CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010,
#ifdef OBSOLETE_FORAMT
CL_UNORM_SHORT_565_REV, CL_UNORM_SHORT_555_REV, CL_UNORM_INT_8888, CL_UNORM_INT_8888_REV, CL_UNORM_INT_101010_REV,
#endif
#ifdef CL_SFIXED14_APPLE
CL_SFIXED14_APPLE,
#endif
CL_UNORM_INT8, CL_SNORM_INT8,
CL_UNORM_INT16, CL_SNORM_INT16, CL_FLOAT, CL_HALF_FLOAT, (cl_channel_type)-1 };
if( filter_formats( formatList, filterFlags, numFormats, floatFormats ) == 0 )
{
log_info( "No formats supported for float type\n" );
}
else
{
// Run the format list
for ( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if ( filterFlags[i] )
{
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
if ( testMethod == k1D )
test_return = test_fill_image_set_1D( device, &formatList[ i ], kFloat );
else if ( testMethod == k2D )
test_return = test_fill_image_set_2D( device, &formatList[ i ], kFloat );
else if ( testMethod == k1DArray )
test_return = test_fill_image_set_1D_array( device, &formatList[ i ], kFloat );
else if ( testMethod == k2DArray )
test_return = test_fill_image_set_2D_array( device, &formatList[ i ], kFloat );
else if ( testMethod == k3D )
test_return = test_fill_image_set_3D( device, &formatList[ i ], kFloat );
if (test_return)
{
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
}
}
/////// int tests ///////
if( gTypesToTest & kTestInt )
{
cl_channel_type intFormats[] = { CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, (cl_channel_type)-1 };
if( filter_formats( formatList, filterFlags, numFormats, intFormats ) == 0 )
{
log_info( "No formats supported for integer type\n" );
}
else
{
// Run the format list
for ( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if ( filterFlags[i] )
{
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
if ( testMethod == k1D )
test_return = test_fill_image_set_1D( device, &formatList[ i ], kInt );
else if ( testMethod == k2D )
test_return = test_fill_image_set_2D( device, &formatList[ i ], kInt );
else if ( testMethod == k1DArray )
test_return = test_fill_image_set_1D_array( device, &formatList[ i ], kInt );
else if ( testMethod == k2DArray )
test_return = test_fill_image_set_2D_array( device, &formatList[ i ], kInt );
else if ( testMethod == k3D )
test_return = test_fill_image_set_3D( device, &formatList[ i ], kInt );
if (test_return) {
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
}
}
/////// uint tests ///////
if( gTypesToTest & kTestUInt )
{
cl_channel_type uintFormats[] = { CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, (cl_channel_type)-1 };
if( filter_formats( formatList, filterFlags, numFormats, uintFormats ) == 0 )
{
log_info( "No formats supported for unsigned int type\n" );
}
else
{
// Run the format list
for ( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if ( filterFlags[i] )
{
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
if ( testMethod == k1D )
test_return = test_fill_image_set_1D( device, &formatList[ i ], kUInt );
else if ( testMethod == k2D )
test_return = test_fill_image_set_2D( device, &formatList[ i ], kUInt );
else if ( testMethod == k1DArray )
test_return = test_fill_image_set_1D_array( device, &formatList[ i ], kUInt );
else if ( testMethod == k2DArray )
test_return = test_fill_image_set_2D_array( device, &formatList[ i ], kUInt );
else if ( testMethod == k3D )
test_return = test_fill_image_set_3D( device, &formatList[ i ], kUInt );
if (test_return) {
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
}
}
delete filterFlags;
delete formatList;
return ret;
}
int test_image_set( cl_device_id device, MethodsToTest testMethod )
{
int ret = 0;
ret += test_image_type( device, testMethod, CL_MEM_READ_ONLY );
return ret;
}

View File

@@ -0,0 +1,21 @@
set(MODULE_NAME CL_GET_INFO)
set(${MODULE_NAME}_SOURCES
main.cpp
test_1D_2D_array.cpp
test_1D.cpp
test_2D.cpp
test_loops.cpp
test_3D.cpp
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/testHarness.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,18 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_cl_get_info
: main.cpp
test_2D.cpp
test_3D.cpp
test_loops.cpp
;
install dist
: test_cl_get_info
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/clGetInfo
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/clGetInfo
;

View File

@@ -0,0 +1,50 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_1D.cpp \
test_2D.cpp \
test_1D_2D_array.cpp \
test_loops.cpp \
test_3D.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.c \
../../../test_common/harness/mt19937.c \
../../../test_common/harness/typeWrappers.cpp
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_cl_get_info
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = 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,313 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false;
int gTypesToTest = 0;
static bool gTest3DImages = true;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
cl_command_queue queue;
cl_context context;
static cl_device_id device;
extern int test_image_set( cl_device_id device, cl_mem_object_type image_type );
static void printUsage( const char *execName );
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
int test_1D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D );
}
int test_2D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D );
}
int test_3D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
if( !gTest3DImages )
{
log_info("3D image is not supported, test not run.\n");
return 0;
}
return test_image_set( device, CL_MEM_OBJECT_IMAGE3D );
}
int test_1DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY );
}
int test_2DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY );
}
basefn basefn_list[] = {
test_1D,
test_2D,
test_3D,
test_1DArray,
test_2DArray,
};
const char *basefn_names[] = {
"1D",
"2D",
"3D",
"1DArray",
"2DArray",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_channel_type chanType;
bool randomize = false;
test_start();
checkDeviceTypeOverride( &gDeviceType );
const char ** argList = (const char **)calloc( argc, sizeof( char*) );
if( NULL == argList )
{
log_error( "Failed to allocate memory for argList array.\n" );
return 1;
}
argList[0] = argv[0];
size_t argCount = 1;
// Parse arguments
for( int i = 1; i < argc; i++ )
{
if( strcmp( argv[i], "cpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if( strcmp( argv[i], "gpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if( strcmp( argv[i], "accelerator" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if( strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if( strcmp( argv[i], "debug_trace" ) == 0 )
gDebugTrace = true;
else if( strcmp( argv[i], "small_images" ) == 0 )
gTestSmallImages = true;
else if( strcmp( argv[i], "max_images" ) == 0 )
gTestMaxImages = true;
else if( strcmp( argv[i], "randomize" ) == 0 )
randomize = true;
else if( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if( ( chanType = get_channel_type_from_name( argv[i] ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else
{
argList[argCount] = argv[i];
argCount++;
}
}
// Seed the random # generators
if( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
log_info( "Random seed: %u.\n", gRandomSeed );
gReSeed = 1;
}
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
unsigned int num_devices;
error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices);
if( error )
{
print_error( error, "Unable to get number of devices" );
test_finish();
return -1;
}
uint32_t gDeviceIndex = 0;
const char* device_index_env = getenv("CL_DEVICE_INDEX");
if (device_index_env) {
if (device_index_env) {
gDeviceIndex = atoi(device_index_env);
}
if (gDeviceIndex >= num_devices) {
vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", gDeviceIndex);
gDeviceIndex = 0;
}
}
cl_device_id *gDeviceList = (cl_device_id *)malloc( num_devices * sizeof( cl_device_id ) );
error = clGetDeviceIDs(platform, gDeviceType, num_devices, gDeviceList, NULL);
if( error )
{
print_error( error, "Unable to get devices" );
free( gDeviceList );
test_finish();
return -1;
}
device = gDeviceList[gDeviceIndex];
free( gDeviceList );
log_info( "Using " );
if( printDeviceHeader( device ) != CL_SUCCESS )
{
test_finish();
return -1;
}
// Check for image support
if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) {
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Check for 3D image support
{
size_t max_height, max_depth, max_width;
max_height = max_depth = max_width = -1L;
if( (error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( max_width ), &max_width, NULL ) ))
{ print_error( error, "FAILURE: Unable to get CL_DEVICE_IMAGE3D_MAX_WIDTH" ); test_finish(); return -1; }
if( (error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( max_height ), &max_height, NULL ) ))
{ print_error( error, "FAILURE: Unable to get CL_DEVICE_IMAGE3D_MAX_HEIGHT"); test_finish(); return -1; }
if( (error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( max_depth ), &max_depth, NULL ) ))
{ print_error( error, "FAILURE: Unable to get CL_DEVICE_IMAGE3D_MAX_DEPTH" ); test_finish(); return -1; }
if( 0 == (max_height | max_depth | max_width) )
{
char deviceProfile[128];
error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( deviceProfile ), deviceProfile, NULL );
if( error )
{
print_error( error, "Unable to get device profile" );
test_finish();
return -1;
}
if( strcmp( deviceProfile, "EMBEDDED_PROFILE" ) )
{
log_error( "FAILURE: non-Embedded device with image support does not support 3D images." );
test_finish();
return -1;
}
gTest3DImages = false;
}
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if( gTestSmallImages )
log_info( "Note: Using small test images\n" );
int ret = parseAndCallCommandLineTests( argCount, argList, NULL, num_fns, basefn_list, basefn_names, true, 0, 0 );
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d sub-tests.\n", gTestCount, gTestCount);
else
log_info("PASSED sub-test.\n");
} else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d sub-tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED sub-test.\n");
}
// Clean up
clReleaseCommandQueue(queue);
clReleaseContext(context);
free(argList);
test_finish();
return ret;
}
static void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if( p != NULL )
execName = p + 1;
log_info( "Usage: %s [options] [test_names]\n", execName );
log_info( "Options:\n" );
log_info( "\tdebug_trace - Enables additional debug info logging (default no debug info)\n" );
log_info( "\n" );
log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes (default test random sizes)\n" );
log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128 (default test random sizes)\n" );
log_info( "\n" );
log_info( "\trandomize - Seed random number generator (default do not seed random number generator)\n" );
log_info( "\n" );
log_info( "Test names:\n" );
for( int i = 0; i < num_fns; i++ )
{
log_info( "\t%s\n", basefn_names[i] );
}
}

View File

@@ -0,0 +1,138 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch );
int test_get_image_info_1D( cl_device_id device, cl_image_format *format, cl_mem_flags flags )
{
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
cl_mem_flags all_host_ptr_flags[5] = {
flags,
CL_MEM_ALLOC_HOST_PTR | flags,
CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_USE_HOST_PTR | flags
};
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info( "Testing %d x 1\n", (int)sizes[ idx ][ 0 ]);
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at max size %d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size = (cl_ulong)imageInfo.rowPitch * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d (flags[%u] 0x%x pitch %d) out of %d\n", (int)imageInfo.width, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
return 0;
}

View File

@@ -0,0 +1,279 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch );
int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags )
{
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
cl_mem_flags all_host_ptr_flags[5] = {
flags,
CL_MEM_ALLOC_HOST_PTR | flags,
CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_USE_HOST_PTR | flags
};
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize,
CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.arraySize = sizes [ idx] [ 2 ];
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch;
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at max size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
imageInfo.slicePitch = imageInfo.rowPitch;
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d (flags[%u] 0x%x pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
return 0;
}
int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags )
{
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
cl_mem_flags all_host_ptr_flags[5] = {
flags,
CL_MEM_ALLOC_HOST_PTR | flags,
CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_USE_HOST_PTR | flags
};
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at max size %d,%d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size_t extraHeight = (int)random_log_in_range( 0, 8, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d,%d (flags[%u] 0x%x pitch %d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
return 0;
}

View File

@@ -0,0 +1,385 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern cl_command_queue queue;
extern cl_context context;
int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch )
{
int error;
clMemWrapper image;
cl_image_desc imageDesc;
void *host_ptr = NULL;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if (flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) {
host_ptr = (char *)imageValues;
}
memset(&imageDesc, 0x0, sizeof(cl_image_desc));
imageDesc.image_type = imageInfo->type;
imageDesc.image_width = imageInfo->width;
imageDesc.image_height = imageInfo->height;
imageDesc.image_depth = imageInfo->depth;
imageDesc.image_array_size = imageInfo->arraySize;
imageDesc.image_row_pitch = row_pitch;
imageDesc.image_slice_pitch = slice_pitch;
// Construct testing source
// Note: for now, just reset the pitches, since they only can actually be different
// if we use CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR
imageInfo->rowPitch = imageInfo->width * get_pixel_size( imageInfo->format );
imageInfo->slicePitch = 0;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
if ( gDebugTrace )
log_info( " - Creating 1D image %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr );
break;
case CL_MEM_OBJECT_IMAGE2D:
if ( gDebugTrace )
log_info( " - Creating 2D image %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->height, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr );
break;
case CL_MEM_OBJECT_IMAGE3D:
imageInfo->slicePitch = imageInfo->rowPitch * imageInfo->height;
if ( gDebugTrace )
log_info( " - Creating 3D image %d by %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
imageInfo->slicePitch = imageInfo->rowPitch;
if ( gDebugTrace )
log_info( " - Creating 1D image array %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->arraySize, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
imageInfo->slicePitch = imageInfo->rowPitch * imageInfo->height;
if ( gDebugTrace )
log_info( " - Creating 2D image array %d by %d by %d with flags=0x%lx row_pitch=%d slice_pitch=%d host_ptr=%p...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (unsigned long)flags, (int)row_pitch, (int)slice_pitch, host_ptr );
break;
}
image = clCreateImage(context, flags, imageInfo->format, &imageDesc, host_ptr, &error);
if( image == NULL )
{
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( error ) );
break;
case CL_MEM_OBJECT_IMAGE2D:
log_error( "ERROR: Unable to create 2D image of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, IGetErrorString( error ) );
break;
case CL_MEM_OBJECT_IMAGE3D:
log_error( "ERROR: Unable to create 3D image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( error ) );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( error ) );
break;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( error ) );
break;
}
return -1;
}
// Get info of the image and verify each item is correct
cl_image_format outFormat;
error = clGetImageInfo( image, CL_IMAGE_FORMAT, sizeof( outFormat ), &outFormat, NULL );
test_error( error, "Unable to get image info (format)" );
if( outFormat.image_channel_order != imageInfo->format->image_channel_order ||
outFormat.image_channel_data_type != imageInfo->format->image_channel_data_type )
{
log_error( "ERROR: image format returned is invalid! (expected %s:%s, got %s:%s (%d:%d))\n",
GetChannelOrderName( imageInfo->format->image_channel_order ), GetChannelTypeName( imageInfo->format->image_channel_data_type ),
GetChannelOrderName( outFormat.image_channel_order ), GetChannelTypeName( outFormat.image_channel_data_type ),
(int)outFormat.image_channel_order, (int)outFormat.image_channel_data_type );
return 1;
}
size_t outElementSize;
error = clGetImageInfo( image, CL_IMAGE_ELEMENT_SIZE, sizeof( outElementSize ), &outElementSize, NULL );
test_error( error, "Unable to get image info (element size)" );
if( outElementSize != get_pixel_size( imageInfo->format ) )
{
log_error( "ERROR: image element size returned is invalid! (expected %d, got %d)\n",
(int)get_pixel_size( imageInfo->format ), (int)outElementSize );
return 1;
}
size_t outRowPitch;
error = clGetImageInfo( image, CL_IMAGE_ROW_PITCH, sizeof( outRowPitch ), &outRowPitch, NULL );
test_error( error, "Unable to get image info (row pitch)" );
size_t outSlicePitch;
error = clGetImageInfo( image, CL_IMAGE_SLICE_PITCH, sizeof( outSlicePitch ), &outSlicePitch, NULL );
test_error( error, "Unable to get image info (row pitch)" );
if( imageInfo->type == CL_MEM_OBJECT_IMAGE1D && outSlicePitch != 0 )
{
log_error( "ERROR: slice pitch returned is invalid! (expected %d, got %d)\n",
(int)0, (int)outSlicePitch );
return 1;
}
size_t outWidth;
error = clGetImageInfo( image, CL_IMAGE_WIDTH, sizeof( outWidth ), &outWidth, NULL );
test_error( error, "Unable to get image info (width)" );
if( outWidth != imageInfo->width )
{
log_error( "ERROR: image width returned is invalid! (expected %d, got %d)\n",
(int)imageInfo->width, (int)outWidth );
return 1;
}
size_t required_height;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
required_height = 0;
break;
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
case CL_MEM_OBJECT_IMAGE3D:
required_height = imageInfo->height;
break;
}
size_t outHeight;
error = clGetImageInfo( image, CL_IMAGE_HEIGHT, sizeof( outHeight ), &outHeight, NULL );
test_error( error, "Unable to get image info (height)" );
if( outHeight != required_height )
{
log_error( "ERROR: image height returned is invalid! (expected %d, got %d)\n",
(int)required_height, (int)outHeight );
return 1;
}
size_t required_depth;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
required_depth = 0;
break;
case CL_MEM_OBJECT_IMAGE3D:
required_depth = imageInfo->depth;
break;
}
size_t outDepth;
error = clGetImageInfo( image, CL_IMAGE_DEPTH, sizeof( outDepth ), &outDepth, NULL );
test_error( error, "Unable to get image info (depth)" );
if( outDepth != required_depth )
{
log_error( "ERROR: image depth returned is invalid! (expected %d, got %d)\n",
(int)required_depth, (int)outDepth );
return 1;
}
size_t required_array_size;
switch (imageInfo->type)
{
case CL_MEM_OBJECT_IMAGE1D:
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE3D:
required_array_size = 0;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
required_array_size = imageInfo->arraySize;
break;
}
size_t outArraySize;
error = clGetImageInfo( image, CL_IMAGE_ARRAY_SIZE, sizeof( outArraySize ), &outArraySize, NULL );
test_error( error, "Unable to get image info (array size)" );
if( outArraySize != required_array_size )
{
log_error( "ERROR: image array size returned is invalid! (expected %d, got %d)\n",
(int)required_array_size, (int)outArraySize );
return 1;
}
cl_mem outBuffer;
error = clGetImageInfo( image, CL_IMAGE_BUFFER, sizeof( outBuffer ), &outBuffer, NULL );
test_error( error, "Unable to get image info (buffer)" );
if (imageInfo->type == CL_MEM_OBJECT_IMAGE1D_BUFFER) {
if (outBuffer != imageInfo->buffer) {
log_error( "ERROR: cl_mem returned is invalid! (expected %p, got %p)\n",
imageInfo->buffer, outBuffer );
return 1;
}
} else {
if (outBuffer != (cl_mem)NULL) {
log_error( "ERROR: cl_mem returned is invalid! (expected %p, got %p)\n",
(cl_mem)NULL, outBuffer );
return 1;
}
}
cl_uint numMipLevels;
error = clGetImageInfo( image, CL_IMAGE_NUM_MIP_LEVELS, sizeof( numMipLevels ), &numMipLevels, NULL );
test_error( error, "Unable to get image info (num mip levels)" );
if( numMipLevels != 0 )
{
log_error( "ERROR: image num_mip_levels returned is invalid! (expected %d, got %d)\n",
(int)0, (int)numMipLevels );
return 1;
}
cl_uint numSamples;
error = clGetImageInfo( image, CL_IMAGE_NUM_SAMPLES, sizeof( numSamples ), &numSamples, NULL );
test_error( error, "Unable to get image info (num samples)" );
if( numSamples != 0 )
{
log_error( "ERROR: image num_samples returned is invalid! (expected %d, got %d)\n",
(int)0, (int)numSamples );
return 1;
}
return 0;
}
int test_get_image_info_2D( cl_device_id device, cl_image_format *format, cl_mem_flags flags )
{
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
cl_mem_flags all_host_ptr_flags[5] = {
flags,
CL_MEM_ALLOC_HOST_PTR | flags,
CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_USE_HOST_PTR | flags
};
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D width or max image 3D height or max memory allocation size or global memory size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at max size %d,%d (flags[%u] 0x%x pitch %d)\n", (int)imageInfo.width, (int)imageInfo.height, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch );
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.height * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d (flags[%u] 0x%x pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, j, (unsigned int) all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, 0 ) )
return -1;
}
}
}
}
return 0;
}

View File

@@ -0,0 +1,158 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d, cl_mem_flags flags, size_t row_pitch, size_t slice_pitch );
int test_get_image_info_3D( cl_device_id device, cl_image_format *format, cl_mem_flags flags )
{
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
cl_mem_flags all_host_ptr_flags[] = {
flags,
CL_MEM_ALLOC_HOST_PTR | flags,
CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR | flags,
CL_MEM_USE_HOST_PTR | flags
};
memset(&imageInfo, 0x0, sizeof(image_descriptor));
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ )
{
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d,%d (flags[%u] 0x%lx pitch %d,%d)\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, j, (unsigned long)all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)imageInfo.slicePitch );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, imageInfo.slicePitch ) )
return -1;
}
}
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.depth = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at max size %d,%d,%d (flags[%u] 0x%lx pitch %d,%d)\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ], j, (unsigned long)all_host_ptr_flags[j], (int)imageInfo.rowPitch, (int)imageInfo.slicePitch );
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, imageInfo.slicePitch ) )
return -1;
}
}
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size_t extraHeight = (int)random_log_in_range( 0, 8, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
for (unsigned int j=0; j < sizeof(all_host_ptr_flags)/sizeof(cl_mem_flags); j++)
{
if( gDebugTrace )
log_info( " at size %d,%d,%d (flags[%u] 0x%lx pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, j, (unsigned long) all_host_ptr_flags[i], (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth );
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], 0, 0 ) )
return -1;
if (all_host_ptr_flags[j] & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { // skip test when host_ptr is NULL
if ( test_get_image_info_single( device, &imageInfo, seed, all_host_ptr_flags[j], imageInfo.rowPitch, imageInfo.slicePitch ) )
return -1;
}
}
}
}
return 0;
}

View File

@@ -0,0 +1,228 @@
//
// 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"
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern int gTypesToTest;
extern int gNormalizedModeToUse;
extern cl_channel_type gChannelTypeToUse;
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace;
extern int test_get_image_info_1D( cl_device_id device, cl_image_format *format, cl_mem_flags flags );
extern int test_get_image_info_2D( cl_device_id device, cl_image_format *format, cl_mem_flags flags );
extern int test_get_image_info_3D( cl_device_id device, cl_image_format *format, cl_mem_flags flags );
extern int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags );
extern int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format, cl_mem_flags flags );
static const char *str_1d_image = "1D";
static const char *str_2d_image = "2D";
static const char *str_3d_image = "3D";
static const char *str_1d_image_array = "1D array";
static const char *str_2d_image_array = "2D array";
static const char *convert_image_type_to_string(cl_mem_object_type image_type)
{
const char *p;
switch (image_type)
{
case CL_MEM_OBJECT_IMAGE1D:
p = str_1d_image;
break;
case CL_MEM_OBJECT_IMAGE2D:
p = str_2d_image;
break;
case CL_MEM_OBJECT_IMAGE3D:
p = str_3d_image;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
p = str_1d_image_array;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
p = str_2d_image_array;
break;
}
return p;
}
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if( filterFlags[ j ] )
filterFlags[ j ] = false;
// Have we already discarded this via the command line?
if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
// We don't filter by channel type
if( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type image_type, cl_image_format * &outFormatList,
unsigned int &outFormatCount, cl_mem_flags flags )
{
int error;
cl_image_format tempList[ 128 ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
image_type, 128, tempList, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
image_type, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_image_type( cl_device_id device, cl_mem_object_type image_type, cl_mem_flags flags )
{
log_info( "Running %s %s-only tests...\n", convert_image_type_to_string(image_type), flags == CL_MEM_READ_ONLY ? "read" : "write" );
int ret = 0;
// Grab the list of supported image formats for integer reads
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
if ( get_format_list( device, image_type, formatList, numFormats, flags ) )
return -1;
BufferOwningPtr<cl_image_format> formatListBuf(formatList);
if ((image_type == CL_MEM_OBJECT_IMAGE3D) && (flags != CL_MEM_READ_ONLY)) {
log_info("No requirement for 3D write in OpenCL 1.2. Not checking formats.\n");
} else {
log_info("Checking for required OpenCL 1.2 formats.\n");
if (check_minimum_supported( formatList, numFormats, flags ) == false) {
ret++;
} else {
log_info("All required formats present.\n");
}
}
filterFlags = new bool[ numFormats ];
BufferOwningPtr<bool> filterFlagsBuf(filterFlags);
if( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
memset( filterFlags, 0, sizeof( bool ) * numFormats );
filter_formats( formatList, filterFlags, numFormats, 0 );
// Run the format list
for( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if( filterFlags[i] )
{
log_info( "NOT RUNNING: " );
print_header( &formatList[ i ], false );
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
switch (image_type) {
case CL_MEM_OBJECT_IMAGE1D:
test_return = test_get_image_info_1D( device, &formatList[ i ], flags );
break;
case CL_MEM_OBJECT_IMAGE2D:
test_return = test_get_image_info_2D( device, &formatList[ i ], flags );
break;
case CL_MEM_OBJECT_IMAGE3D:
test_return = test_get_image_info_3D( device, &formatList[ i ], flags );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
test_return = test_get_image_info_1D_array( device, &formatList[ i ], flags );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
test_return = test_get_image_info_2D_array( device, &formatList[ i ], flags );
break;
}
if (test_return) {
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
return ret;
}
int test_image_set( cl_device_id device, cl_mem_object_type image_type )
{
int ret = 0;
ret += test_image_type( device, image_type, CL_MEM_READ_ONLY );
ret += test_image_type( device, image_type, CL_MEM_WRITE_ONLY );
return ret;
}

View File

@@ -0,0 +1,23 @@
set(MODULE_NAME CL_READ_WRITE_IMAGES)
set(${MODULE_NAME}_SOURCES
main.cpp
test_read_1D.cpp
test_read_1D_array.cpp
test_read_2D.cpp
test_read_2D_array.cpp
test_loops.cpp
test_read_3D.cpp
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/testHarness.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,18 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_cl_read_write_images
: main.cpp
test_read_2D.cpp
test_read_3D.cpp
test_loops.cpp
;
install dist
: test_cl_read_write_images
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/clReadWriteImage
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/clReadWriteImage
;

View File

@@ -0,0 +1,51 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_read_1D.cpp \
test_read_1D_array.cpp \
test_read_2D.cpp \
test_read_2D_array.cpp \
test_loops.cpp \
test_read_3D.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.c \
../../../test_common/harness/mt19937.c \
../../../test_common/harness/typeWrappers.cpp
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_cl_read_write_images
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = 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,287 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gUseRamp = false, gTestRounding = false, gTestMipmaps = false;
int gTypesToTest = 0;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
bool gEnablePitch = false;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
cl_command_queue queue;
cl_context context;
static cl_device_id device;
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
static void printUsage( const char *execName );
extern int test_image_set( cl_device_id device, cl_mem_object_type image_type );
int test_1D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D );
}
int test_2D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D );
}
int test_3D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE3D );
}
int test_1DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY );
}
int test_2DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY );
}
basefn basefn_list[] = {
test_1D,
test_2D,
test_3D,
test_1DArray,
test_2DArray,
};
const char *basefn_names[] = {
"1D",
"2D",
"3D",
"1DArray",
"2DArray",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_channel_type chanType;
bool randomize = false;
test_start();
checkDeviceTypeOverride( &gDeviceType );
const char ** argList = (const char **)calloc( argc, sizeof( char*) );
if( NULL == argList )
{
log_error( "Failed to allocate memory for argList array.\n" );
return 1;
}
argList[0] = argv[0];
size_t argCount = 1;
// Parse arguments
for( int i = 1; i < argc; i++ )
{
if( strcmp( argv[i], "cpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if( strcmp( argv[i], "gpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if( strcmp( argv[i], "accelerator" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if( strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if( strcmp( argv[i], "debug_trace" ) == 0 )
gDebugTrace = true;
else if( strcmp( argv[i], "small_images" ) == 0 )
gTestSmallImages = true;
else if( strcmp( argv[i], "max_images" ) == 0 )
gTestMaxImages = true;
else if( strcmp( argv[i], "use_pitches" ) == 0 )
gEnablePitch = true;
else if( strcmp( argv[i], "use_ramps" ) == 0 )
gUseRamp = true;
else if( strcmp( argv[i], "test_mipmaps") == 0 ) {
gTestMipmaps = true;
// Don't test pitches with mipmaps right now.
gEnablePitch = false;
}
else if( strcmp( argv[i], "randomize" ) == 0 )
randomize = true;
else if( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if( ( chanType = get_channel_type_from_name( argv[i] ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else
{
argList[argCount] = argv[i];
argCount++;
}
}
// Seed the random # generators
if( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
log_info( "Random seed: %u.\n", gRandomSeed );
gReSeed = 1;
}
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
unsigned int num_devices;
error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices);
if( error )
{
print_error( error, "Unable to get number of devices" );
test_finish();
return -1;
}
uint32_t gDeviceIndex = 0;
const char* device_index_env = getenv("CL_DEVICE_INDEX");
if (device_index_env) {
if (device_index_env) {
gDeviceIndex = atoi(device_index_env);
}
if (gDeviceIndex >= num_devices) {
vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", gDeviceIndex);
gDeviceIndex = 0;
}
}
cl_device_id *gDeviceList = (cl_device_id *)malloc( num_devices * sizeof( cl_device_id ) );
error = clGetDeviceIDs(platform, gDeviceType, num_devices, gDeviceList, NULL);
if( error )
{
print_error( error, "Unable to get devices" );
free( gDeviceList );
test_finish();
return -1;
}
device = gDeviceList[gDeviceIndex];
free( gDeviceList );
log_info( "Using " );
if( printDeviceHeader( device ) != CL_SUCCESS )
{
test_finish();
return -1;
}
// Check for image support
if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) {
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if( gTestSmallImages )
log_info( "Note: Using small test images\n" );
int ret = parseAndCallCommandLineTests( argCount, argList, NULL, num_fns, basefn_list, basefn_names, true, 0, 0 );
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.");
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d sub-tests.\n", gTestCount, gTestCount);
else
log_info("PASSED sub-test.\n");
} else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d sub-tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED sub-test.\n");
}
// Clean up
clReleaseCommandQueue(queue);
clReleaseContext(context);
free(argList);
test_finish();
return ret;
}
static void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if( p != NULL )
execName = p + 1;
log_info( "Usage: %s [options] [test_names]\n", execName );
log_info( "Options:\n" );
log_info( "\tdebug_trace - Enables additional debug info logging\n" );
log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
log_info( "\tuse_pitches - Enables row and slice pitches\n" );
log_info( "\tuse_ramp - Instead of random data, uses images filled with ramps (and 0xff on any padding pixels) to ease debugging\n" );
log_info( "\ttest_mipmaps - Test mipmapped images\n" );
log_info( "\trandomize - Uses random seed\n" );
log_info( "\n" );
log_info( "Test names:\n" );
for( int i = 0; i < num_fns; i++ )
{
log_info( "\t%s\n", basefn_names[i] );
}
}

View File

@@ -0,0 +1,227 @@
//
// 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"
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern int gTypesToTest;
extern int gNormalizedModeToUse;
extern cl_channel_type gChannelTypeToUse;
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace;
extern bool gTestMipmaps;
extern int test_read_image_set_1D( cl_device_id device, cl_image_format *format );
extern int test_read_image_set_2D( cl_device_id device, cl_image_format *format );
extern int test_read_image_set_3D( cl_device_id device, cl_image_format *format );
extern int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format );
extern int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format );
static const char *str_1d_image = "1D";
static const char *str_2d_image = "2D";
static const char *str_3d_image = "3D";
static const char *str_1d_image_array = "1D array";
static const char *str_2d_image_array = "2D array";
static const char *convert_image_type_to_string(cl_mem_object_type imageType)
{
const char *p;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
p = str_1d_image;
break;
case CL_MEM_OBJECT_IMAGE2D:
p = str_2d_image;
break;
case CL_MEM_OBJECT_IMAGE3D:
p = str_3d_image;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
p = str_1d_image_array;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
p = str_2d_image_array;
break;
}
return p;
}
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if( filterFlags[ j ] )
filterFlags[ j ] = false;
// Have we already discarded this via the command line?
if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
// We don't filter by channel type
if( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags )
{
int error;
cl_image_format tempList[ 128 ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
imageType, 128, tempList, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
imageType, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_image_type( cl_device_id device, cl_mem_object_type imageType, cl_mem_flags flags )
{
log_info( "Running %s %s %s-only tests...\n", gTestMipmaps?"mipmapped":"",convert_image_type_to_string(imageType), flags == CL_MEM_READ_ONLY ? "read" : "write" );
int ret = 0;
// Grab the list of supported image formats for integer reads
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
if ( gTestMipmaps )
{
if ( 0 == is_extension_available( device, "cl_khr_mipmap_image" ))
{
log_info( "-----------------------------------------------------\n" );
log_info( "This device does not support cl_khr_mipmap_image.\nSkipping mipmapped image test. \n" );
log_info( "-----------------------------------------------------\n\n" );
return 0;
}
}
if( get_format_list( device, imageType, formatList, numFormats, flags ) )
return -1;
filterFlags = new bool[ numFormats ];
if( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
memset( filterFlags, 0, sizeof( bool ) * numFormats );
filter_formats( formatList, filterFlags, numFormats, 0 );
// Run the format list
for( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if( filterFlags[i] )
{
log_info( "NOT RUNNING: " );
print_header( &formatList[ i ], false );
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
switch (imageType) {
case CL_MEM_OBJECT_IMAGE1D:
test_return = test_read_image_set_1D( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE2D:
test_return = test_read_image_set_2D( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE3D:
test_return = test_read_image_set_3D( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
test_return = test_read_image_set_1D_array( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
test_return = test_read_image_set_2D_array( device, &formatList[ i ] );
break;
}
if (test_return) {
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
delete filterFlags;
delete formatList;
return ret;
}
int test_image_set( cl_device_id device, cl_mem_object_type imageType )
{
int ret = 0;
ret += test_image_type( device, imageType, CL_MEM_READ_ONLY );
ret += test_image_type( device, imageType, CL_MEM_WRITE_ONLY );
return ret;
}

View File

@@ -0,0 +1,273 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
int test_read_image_1D( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error;
clMemWrapper image;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if( gDebugTrace )
{
log_info( " - Creating %s 1D image %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width );
log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels );
}
// Construct testing sources
if(!gTestMipmaps)
{
image = create_image_1d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, 0, NULL, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( error ) );
return -1;
}
}
else
{
cl_image_desc image_desc = {0};
image_desc.image_type = CL_MEM_OBJECT_IMAGE1D;
image_desc.image_width = imageInfo->width;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level mipmapped 1D image of size %d x %d (pitch %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
}
if( gDebugTrace )
log_info( " - Writing image...\n" );
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { 0, 1, 1 };
size_t fullImageSize;
if( gTestMipmaps )
{
fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo );
}
else
{
fullImageSize = imageInfo->rowPitch;
}
BufferOwningPtr<char> resultValues(malloc(fullImageSize));
size_t imgValMipLevelOffset = 0;
for( size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
float lod_float = (float) lod;
origin[1] = lod;
size_t width_lod, row_pitch_lod;
width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1;
row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch;
region[0] = width_lod;
if ( gDebugTrace )
if ( gTestMipmaps) {
log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod);
}
error = clEnqueueWriteImage(queue, image, CL_FALSE,
origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), 0,
(char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL);
if (error != CL_SUCCESS) {
log_error( "ERROR: Unable to write to 1D image of size %d \n", (int)width_lod );
return -1;
}
// To verify, we just read the results right back and see whether they match the input
if( gDebugTrace )
{
log_info( " - Initing result array...\n" );
}
// Note: we read back without any pitch, to verify pitch actually WORKED
size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format );
size_t imageSize = scanlineSize;
memset( resultValues, 0xff, imageSize );
if( gDebugTrace )
log_info( " - Reading results...\n" );
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read image values" );
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = (char*)imageValues + imgValMipLevelOffset;
char *destPtr = resultValues;
if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 )
{
log_error( "ERROR: Scanline did not verify for image size %d pitch %d (extra %d bytes)\n", (int)width_lod, (int)row_pitch_lod, (int)row_pitch_lod - (int)width_lod * (int)get_pixel_size( imageInfo->format ) );
log_error( "First few values: \n" );
log_error( " Input: " );
uint32_t *s = (uint32_t *)sourcePtr;
uint32_t *d = (uint32_t *)destPtr;
for( int q = 0; q < 12; q++ )
log_error( "%08x ", s[ q ] );
log_error( "\nOutput: " );
for( int q = 0; q < 12; q++ )
log_error( "%08x ", d[ q ] );
log_error( "\n" );
int outX;
int offset = (int)get_pixel_size( imageInfo->format ) * (int)( width_lod - 16 );
if( offset < 0 )
offset = 0;
int foundCount = debug_find_vector_in_image( (char*)imageValues + imgValMipLevelOffset, imageInfo, destPtr + offset, get_pixel_size( imageInfo->format ), &outX, NULL, NULL );
if( foundCount > 0 )
{
int returnedOffset = ( offset / (int)get_pixel_size( imageInfo->format ) ) - outX;
if( memcmp( sourcePtr + returnedOffset * get_pixel_size( imageInfo->format ), destPtr, get_pixel_size( imageInfo->format ) * 8 ) == 0 )
log_error( " Values appear to be offsetted by %d\n", returnedOffset );
else
log_error( " Calculated offset is %d but unable to verify\n", returnedOffset );
}
else
{
log_error( " Unable to determine offset\n" );
}
return -1;
}
imgValMipLevelOffset += width_lod * get_pixel_size( imageInfo->format );
}
return 0;
}
int test_read_image_set_1D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = imageInfo.slicePitch = 0;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
if( gDebugTrace )
log_info( " at size %d\n", (int)imageInfo.width );
int ret = test_read_image_1D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[idx][0];
imageInfo.rowPitch = imageInfo.width * pixelSize;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
log_info("Testing %d\n", (int)imageInfo.width);
if( gDebugTrace )
log_info( " at max size %d\n", (int)maxWidth );
if( test_read_image_1D( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
size = compute_mipmapped_image_size( imageInfo );
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
}
size = (size_t)imageInfo.rowPitch * 4;
}
} while( size > maxAllocSize || ( size / 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
int ret = test_read_image_1D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,287 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
int test_read_image_1D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error;
clMemWrapper image;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if( gDebugTrace )
{
log_info( " - Creating %s image array of size %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->arraySize );
if( gTestMipmaps )
log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels );
}
// Construct testing sources
if(!gTestMipmaps)
{
image = create_image_1d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->arraySize, 0, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( error ) );
return -1;
}
}
else
{
cl_image_desc image_desc = {0};
image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
image_desc.image_width = imageInfo->width;
image_desc.image_array_size = imageInfo->arraySize;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level mipmapped 1D image of width %d and array size %d (pitch %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
}
if( gDebugTrace )
log_info( " - Writing image...\n" );
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { 0, 0, 1 };
size_t fullImageSize;
if( gTestMipmaps )
{
fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo );
}
else
{
fullImageSize = imageInfo->arraySize * imageInfo->slicePitch;
}
size_t imgValMipLevelOffset = 0;
BufferOwningPtr<char> resultValues(malloc(fullImageSize));
for( size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
float lod_float = (float) lod;
size_t width_lod, row_pitch_lod, slice_pitch_lod;
if( gTestMipmaps )
origin[2] = lod;
width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1;
row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch;
slice_pitch_lod = row_pitch_lod;
region[0] = width_lod;
region[1] = imageInfo->arraySize;
if ( gDebugTrace && gTestMipmaps )
log_info("Working at mip level %llu\n", (unsigned long long) lod);
error = clEnqueueWriteImage(queue, image, CL_FALSE,
origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), 0,
(char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL);
if (error != CL_SUCCESS) {
log_error( "ERROR: Unable to write to 1D image array of width %d and size %d\n", (int)width_lod, (int)imageInfo->arraySize );
return -1;
}
// To verify, we just read the results right back and see whether they match the input
if( gDebugTrace )
log_info( " - Initing result array...\n" );
// Note: we read back without any pitch, to verify pitch actually WORKED
size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format );
size_t imageSize = scanlineSize * imageInfo->arraySize;
memset( resultValues, 0xff, imageSize );
if( gDebugTrace )
log_info( " - Reading results...\n" );
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read image values" );
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = (char *)imageValues + imgValMipLevelOffset;
char *destPtr = resultValues;
for( size_t y = 0; y < imageInfo->arraySize; y++ )
{
if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 )
{
log_error( "ERROR: Image array index %d did not verify for image size %d,%d pitch %d (extra %d bytes)\n", (int)y, (int)width_lod, (int)imageInfo->arraySize, (int)row_pitch_lod, (int)row_pitch_lod - (int)width_lod * (int)get_pixel_size( imageInfo->format ) );
log_error( "First few values: \n" );
log_error( " Input: " );
uint32_t *s = (uint32_t *)sourcePtr;
uint32_t *d = (uint32_t *)destPtr;
for( int q = 0; q < 12; q++ )
log_error( "%08x ", s[ q ] );
log_error( "\nOutput: " );
for( int q = 0; q < 12; q++ )
log_error( "%08x ", d[ q ] );
log_error( "\n" );
int outX, outY;
int offset = (int)get_pixel_size( imageInfo->format ) * (int)( width_lod - 16 );
if( offset < 0 )
offset = 0;
int foundCount = debug_find_vector_in_image( imageValues + imgValMipLevelOffset, imageInfo, destPtr + offset, get_pixel_size( imageInfo->format ), &outX, &outY, NULL );
if( foundCount > 0 )
{
int returnedOffset = ( (int)y * (int)width_lod + offset / (int)get_pixel_size( imageInfo->format ) ) - ( outY * (int)width_lod + outX );
if( memcmp( sourcePtr + returnedOffset * get_pixel_size( imageInfo->format ), destPtr, get_pixel_size( imageInfo->format ) * 8 ) == 0 )
log_error( " Values appear to be offsetted by %d\n", returnedOffset );
else
log_error( " Calculated offset is %d but unable to verify\n", returnedOffset );
}
else
{
log_error( " Unable to determine offset\n" );
}
return -1;
}
sourcePtr += row_pitch_lod;
destPtr += scanlineSize;
}
imgValMipLevelOffset += width_lod * imageInfo->arraySize * get_pixel_size( imageInfo->format );
}
return 0;
}
int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = 0;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize );
int ret = test_read_image_1D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[idx][0];
imageInfo.arraySize = sizes[idx][2];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.arraySize);
if( gDebugTrace )
log_info( " at max size %d,%d\n", (int)maxWidth, (int)maxArraySize );
if( test_read_image_1D_array( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, 0, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch;
size = compute_mipmapped_image_size( imageInfo );
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
}
imageInfo.slicePitch = imageInfo.rowPitch;
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
int ret = test_read_image_1D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,286 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern uint64_t gRoundingStartValue;
extern cl_command_queue queue;
extern cl_context context;
int test_read_image_2D( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error;
clMemWrapper image;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if( gDebugTrace )
{
log_info( " - Creating %s image %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->height );
if( gTestMipmaps )
log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels );
}
// Construct testing sources
if(!gTestMipmaps)
{
image = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 2D image of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, IGetErrorString( error ) );
return -1;
}
}
else
{
cl_image_desc image_desc = {0};
image_desc.image_type = CL_MEM_OBJECT_IMAGE2D;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level mipmapped 2D image of size %d x %d (pitch %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
}
if( gDebugTrace )
log_info( " - Writing image...\n" );
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { 0, 0, 1 };
size_t fullImageSize;
if( gTestMipmaps )
{
fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo );
}
else
{
fullImageSize = imageInfo->height * imageInfo->rowPitch;
}
BufferOwningPtr<char> resultValues(malloc(fullImageSize));
size_t imgValMipLevelOffset = 0;
for( size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
float lod_float = (float) lod;
origin[2] = lod;
size_t width_lod, height_lod, row_pitch_lod;
width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1;
height_lod = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1;
row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch;
region[0] = width_lod;
region[1] = height_lod;
if ( gDebugTrace && gTestMipmaps) {
log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod);
}
error = clEnqueueWriteImage(queue, image, CL_FALSE,
origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), 0,
(char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL);
if (error != CL_SUCCESS) {
log_error( "ERROR: Unable to write to 2D image of size %d x %d \n", (int)width_lod, (int)height_lod );
return -1;
}
// To verify, we just read the results right back and see whether they match the input
if( gDebugTrace ) {
log_info( " - Initing result array...\n" );
}
// Note: we read back without any pitch, to verify pitch actually WORKED
size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format );
size_t imageSize = scanlineSize * height_lod;
memset( resultValues, 0xff, imageSize );
if( gDebugTrace )
log_info( " - Reading results...\n" );
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read image values" );
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = (char *)imageValues + imgValMipLevelOffset;
char *destPtr = resultValues;
for( size_t y = 0; y < height_lod; y++ )
{
if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 )
{
if(gTestMipmaps)
{
log_error("At mip level %llu\n",(unsigned long long) lod);
}
log_error( "ERROR: Scanline %d did not verify for image size %d,%d pitch %d (extra %d bytes)\n", (int)y, (int)width_lod, (int)height_lod, (int)row_pitch_lod, (int)row_pitch_lod - (int)width_lod * (int)get_pixel_size( imageInfo->format ) );
log_error( "First few values: \n" );
log_error( " Input: " );
uint32_t *s = (uint32_t *)sourcePtr;
uint32_t *d = (uint32_t *)destPtr;
for( int q = 0; q < 12; q++ )
log_error( "%08x ", s[ q ] );
log_error( "\nOutput: " );
for( int q = 0; q < 12; q++ )
log_error( "%08x ", d[ q ] );
log_error( "\n" );
int outX, outY;
int offset = (int)get_pixel_size( imageInfo->format ) * (int)( width_lod - 16 );
if( offset < 0 )
offset = 0;
int foundCount = debug_find_vector_in_image( (char*)imageValues + imgValMipLevelOffset, imageInfo, destPtr + offset, get_pixel_size( imageInfo->format ), &outX, &outY, NULL );
if( foundCount > 0 )
{
int returnedOffset = ( (int)y * (int)width_lod + offset / (int)get_pixel_size( imageInfo->format ) ) - ( outY * (int)width_lod + outX );
if( memcmp( sourcePtr + returnedOffset * get_pixel_size( imageInfo->format ), destPtr, get_pixel_size( imageInfo->format ) * 8 ) == 0 )
log_error( " Values appear to be offsetted by %d\n", returnedOffset );
else
log_error( " Calculated offset is %d but unable to verify\n", returnedOffset );
}
else
{
log_error( " Unable to determine offset\n" );
}
return -1;
}
sourcePtr += row_pitch_lod;
destPtr += scanlineSize;
}
imgValMipLevelOffset += width_lod * height_lod * get_pixel_size( imageInfo->format );
}
return 0;
}
int test_read_image_set_2D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
imageInfo.format = format;
imageInfo.depth = imageInfo.slicePitch = 0;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int ret = test_read_image_2D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[idx][0];
imageInfo.height = sizes[idx][1];
imageInfo.rowPitch = imageInfo.width * pixelSize;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.height);
if( gDebugTrace )
log_info( " at max size %d,%d\n", (int)maxWidth, (int)maxHeight );
if( test_read_image_2D( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
size = compute_mipmapped_image_size( imageInfo );
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
}
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4;
}
} while( size > maxAllocSize || ( size / 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
int ret = test_read_image_2D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,272 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern cl_command_queue queue;
extern cl_context context;
int test_read_image_2D_array( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error;
clMemWrapper image;
// Create some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if( gDebugTrace )
{
log_info( " - Creating %s image %d by %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize );
if( gTestMipmaps )
log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels );
}
// Construct testing sources
if(!gTestMipmaps)
{
image = create_image_2d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( error ) );
return -1;
}
}
else
{
cl_image_desc image_desc = {0};
image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_array_size = imageInfo->arraySize;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %d x %d x %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) );
return error;
}
}
if( gDebugTrace )
log_info( " - Writing image...\n" );
size_t origin[ 4 ] = { 0, 0, 0, 0 };
size_t region[ 3 ] = { 0, 0, 0 };
size_t fullImageSize;
if( gTestMipmaps )
{
fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo );
}
else
{
fullImageSize = imageInfo->arraySize * imageInfo->slicePitch;
}
BufferOwningPtr<char> resultValues(malloc(fullImageSize));
size_t imgValMipLevelOffset = 0;
for(size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
float lod_float = (float) lod;
origin[3] = lod;
size_t width_lod, height_lod, depth_lod, row_pitch_lod, slice_pitch_lod;
width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1;
height_lod = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1;
row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch;
slice_pitch_lod = gTestMipmaps ? (row_pitch_lod * height_lod): imageInfo->slicePitch;
region[0] = width_lod;
region[1] = height_lod;
region[2] = imageInfo->arraySize;
if ( gDebugTrace && gTestMipmaps) {
log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod);
}
error = clEnqueueWriteImage(queue, image, CL_FALSE,
origin, region, ( gEnablePitch ? row_pitch_lod : 0 ), ( gEnablePitch ? slice_pitch_lod : 0 ),
(char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL);
if (error != CL_SUCCESS) {
log_error( "ERROR: Unable to write to 2D image array of size %d x %d x %d\n", (int)width_lod, (int)height_lod, (int)imageInfo->arraySize );
return -1;
}
// To verify, we just read the results right back and see whether they match the input
if( gDebugTrace )
log_info( " - Initing result array...\n" );
// Note: we read back without any pitch, to verify pitch actually WORKED
size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format );
size_t pageSize = scanlineSize * height_lod;
size_t imageSize = pageSize * imageInfo->arraySize;
memset( resultValues, 0xff, imageSize );
if( gDebugTrace )
log_info( " - Reading results...\n" );
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read image values" );
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = (char *)imageValues + imgValMipLevelOffset;
char *destPtr = resultValues;
for( size_t z = 0; z < imageInfo->arraySize; z++ )
{
for( size_t y = 0; y < height_lod; y++ )
{
if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 )
{
log_error( "ERROR: Scanline %d,%d did not verify for image size %d,%d,%d pitch %d,%d\n", (int)y, (int)z, (int)width_lod, (int)height_lod, (int)imageInfo->arraySize, (int)row_pitch_lod, (int)slice_pitch_lod );
return -1;
}
sourcePtr += row_pitch_lod;
destPtr += scanlineSize;
}
sourcePtr += slice_pitch_lod - ( row_pitch_lod * height_lod );
destPtr += pageSize - scanlineSize * height_lod;
}
imgValMipLevelOffset += width_lod * height_lod * imageInfo->arraySize * get_pixel_size( imageInfo->format );
}
return 0;
}
int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize );
int ret = test_read_image_2D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
// Try a specific set of maximum sizes
imageInfo.width = sizes[idx][0];
imageInfo.height = sizes[idx][1];
imageInfo.arraySize = sizes[idx][2];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize);
if( test_read_image_2D_array( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, 0), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size = compute_mipmapped_image_size( imageInfo ) * 4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
size_t extraHeight = (int)random_log_in_range( 0, 8, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
}
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize );
int ret = test_read_image_2D_array( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,276 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern cl_command_queue queue;
extern cl_context context;
int test_read_image_3D( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error;
clMemWrapper image;
// Create some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if( gDebugTrace )
{
log_info( " - Creating %s image %d by %d by %d...\n", gTestMipmaps?"mipmapped":"", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth );
if( gTestMipmaps )
log_info( " with %llu mip levels\n", (unsigned long long) imageInfo->num_mip_levels );
}
// Construct testing sources
if(!gTestMipmaps)
{
image = create_image_3d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 2D image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( error ) );
return -1;
}
}
else
{
cl_image_desc image_desc = {0};
image_desc.image_type = CL_MEM_OBJECT_IMAGE3D;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_depth = imageInfo->depth;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %d x %d x %d (pitch %d, %d ) (%s)",(int)imageInfo->num_mip_levels, (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) );
return error;
}
}
if( gDebugTrace )
log_info( " - Writing image...\n" );
size_t origin[ 4 ] = { 0, 0, 0, 0 };
size_t region[ 3 ] = { 0, 0, 0 };
size_t fullImageSize;
if( gTestMipmaps )
{
fullImageSize = (size_t)compute_mipmapped_image_size( *imageInfo );
}
else
{
fullImageSize = imageInfo->depth * imageInfo->slicePitch;
}
BufferOwningPtr<char> resultValues(malloc(fullImageSize));
size_t imgValMipLevelOffset = 0;
for(size_t lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
float lod_float = (float) lod;
origin[3] = lod;
size_t width_lod, height_lod, depth_lod, row_pitch_lod, slice_pitch_lod;
width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1;
height_lod = (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1;
depth_lod = (imageInfo->depth >> lod) ? (imageInfo->depth >> lod) : 1;
row_pitch_lod = gTestMipmaps ? (width_lod * get_pixel_size( imageInfo->format )): imageInfo->rowPitch;
slice_pitch_lod = gTestMipmaps ? (row_pitch_lod * height_lod): imageInfo->slicePitch;
region[0] = width_lod;
region[1] = height_lod;
region[2] = depth_lod;
if ( gDebugTrace && gTestMipmaps) {
log_info(" - Working at mipLevel :%llu\n", (unsigned long long)lod);
}
error = clEnqueueWriteImage(queue, image, CL_FALSE,
origin, region, ( gEnablePitch ? imageInfo->rowPitch : 0 ), ( gEnablePitch ? imageInfo->slicePitch : 0 ),
(char*)imageValues + imgValMipLevelOffset, 0, NULL, NULL);
if (error != CL_SUCCESS) {
log_error( "ERROR: Unable to write to %s 3D image of size %d x %d x %d\n", gTestMipmaps?"mipmapped":"", (int)width_lod, (int)height_lod, (int)depth_lod );
return -1;
}
// To verify, we just read the results right back and see whether they match the input
if( gDebugTrace ) {
log_info( " - Initing result array...\n" );
}
// Note: we read back without any pitch, to verify pitch actually WORKED
size_t scanlineSize = width_lod * get_pixel_size( imageInfo->format );
size_t pageSize = scanlineSize * height_lod;
size_t imageSize = pageSize * depth_lod;
memset( resultValues, 0xff, imageSize );
if( gDebugTrace )
log_info( " - Reading results...\n" );
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read image values" );
// Verify scanline by scanline, since the pitches are different
char *sourcePtr = (char *)imageValues + imgValMipLevelOffset;
char *destPtr = resultValues;
for( size_t z = 0; z < depth_lod; z++ )
{
for( size_t y = 0; y < height_lod; y++ )
{
if( memcmp( sourcePtr, destPtr, scanlineSize ) != 0 )
{
if(gTestMipmaps)
{
log_error("At mip level %llu\n",(unsigned long long) lod);
}
log_error( "ERROR: Scanline %d,%d did not verify for image size %d,%d,%d pitch %d,%d\n", (int)y, (int)z, (int)width_lod, (int)height_lod, (int)depth_lod, (int)row_pitch_lod, (int)slice_pitch_lod );
return -1;
}
sourcePtr += row_pitch_lod;
destPtr += scanlineSize;
}
sourcePtr += slice_pitch_lod - ( row_pitch_lod * height_lod );
destPtr += pageSize - scanlineSize * height_lod;
}
imgValMipLevelOffset += width_lod * height_lod * depth_lod * get_pixel_size( imageInfo->format );
}
return 0;
}
int test_read_image_set_3D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ )
{
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed);
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth );
int ret = test_read_image_3D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
// Try a specific set of maximum sizes
imageInfo.width = sizes[idx][0];
imageInfo.height = sizes[idx][1];
imageInfo.depth = sizes[idx][2];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
if (gTestMipmaps)
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed);
log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth);
if( test_read_image_3D( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed );
if (gTestMipmaps)
{
imageInfo.num_mip_levels = (cl_uint) random_log_in_range(2, (int)compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth), seed);
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size = compute_mipmapped_image_size( imageInfo );
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
size_t extraHeight = (int)random_log_in_range( 0, 8, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
}
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth );
int ret = test_read_image_3D( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,22 @@
set(MODULE_NAME KERNEL_IMAGE_METHODS)
set(${MODULE_NAME}_SOURCES
main.cpp
test_1D.cpp
test_1D_array.cpp
test_2D.cpp
test_2D_array.cpp
test_loops.cpp
test_3D.cpp
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/testHarness.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,18 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_kernel_image_methods
: main.cpp
test_2D.cpp
test_3D.cpp
test_loops.cpp
;
install dist
: test_kernel_image_methods
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/kernel_image_methods
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/kernel_image_methods
;

View File

@@ -0,0 +1,51 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_1D.cpp \
test_1D_array.cpp \
test_2D.cpp \
test_2D_array.cpp \
test_loops.cpp \
test_3D.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.c \
../../../test_common/harness/mt19937.c \
../../../test_common/harness/typeWrappers.cpp
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_kernel_image_methods
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = c++
CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%)
CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%)
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,277 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
bool gDebugTrace = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false;
int gTypesToTest = 0;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
static cl_device_id device;
extern int test_image_set( cl_device_id device, cl_mem_object_type imageType );
static void printUsage( const char *execName );
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
clCommandQueueWrapper queue;
clContextWrapper context;
int test_1D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D );
}
int test_2D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D );
}
int test_3D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE3D );
}
int test_1DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY );
}
int test_2DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY );
}
basefn basefn_list[] = {
test_1D,
test_2D,
test_3D,
test_1DArray,
test_2DArray,
};
const char *basefn_names[] = {
"1D",
"2D",
"3D",
"1DArray",
"2DArray",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_channel_type chanType;
bool randomize = false;
test_start();
checkDeviceTypeOverride( &gDeviceType );
const char ** argList = (const char **)calloc( argc, sizeof( char*) );
if( NULL == argList )
{
log_error( "Failed to allocate memory for argList array.\n" );
return 1;
}
argList[0] = argv[0];
size_t argCount = 1;
// Parse arguments
for( int i = 1; i < argc; i++ )
{
if( strcmp( argv[i], "cpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if( strcmp( argv[i], "gpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if( strcmp( argv[i], "accelerator" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if( strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if( strcmp( argv[i], "debug_trace" ) == 0 )
gDebugTrace = true;
else if( strcmp( argv[i], "small_images" ) == 0 )
gTestSmallImages = true;
else if( strcmp( argv[i], "max_images" ) == 0 )
gTestMaxImages = true;
else if( strcmp( argv[i], "randomize" ) == 0 )
randomize = true;
else if( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if( ( chanType = get_channel_type_from_name( argv[i] ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else
{
argList[argCount] = argv[i];
argCount++;
}
}
// Seed the random # generators
if( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
log_info( "Random seed: %u.\n", gRandomSeed );
gReSeed = 1;
}
// Get our device
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
unsigned int num_devices;
error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices);
if( error )
{
print_error( error, "Unable to get number of devices" );
test_finish();
return -1;
}
uint32_t gDeviceIndex = 0;
const char* device_index_env = getenv("CL_DEVICE_INDEX");
if (device_index_env) {
if (device_index_env) {
gDeviceIndex = atoi(device_index_env);
}
if (gDeviceIndex >= num_devices) {
vlog("Specified CL_DEVICE_INDEX=%d out of range, using index 0.\n", gDeviceIndex);
gDeviceIndex = 0;
}
}
cl_device_id *gDeviceList = (cl_device_id *)malloc( num_devices * sizeof( cl_device_id ) );
error = clGetDeviceIDs(platform, gDeviceType, num_devices, gDeviceList, NULL);
if( error )
{
print_error( error, "Unable to get devices" );
free( gDeviceList );
test_finish();
return -1;
}
device = gDeviceList[gDeviceIndex];
free( gDeviceList );
log_info( "Using " );
if( printDeviceHeader( device ) != CL_SUCCESS )
{
test_finish();
return -1;
}
// Check for image support
if (checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
{
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if ( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if( gTestSmallImages )
log_info( "Note: Using small test images\n" );
int ret = parseAndCallCommandLineTests( argCount, argList, NULL, num_fns, basefn_list, basefn_names, true, 0, 0 );
// Clean up
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.");
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d sub-tests.\n", gTestCount, gTestCount);
else
log_info("PASSED sub-test.\n");
} else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d sub-tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED sub-test.\n");
}
free(argList);
test_finish();
return ret;
}
static void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if( p != NULL )
execName = p + 1;
log_info( "Usage: %s [options] [test_names]\n", execName );
log_info( "Options:\n" );
log_info( "\tdebug_trace - Enables additional debug info logging\n" );
log_info( "\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
log_info( "\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
log_info( "\trandomize - Uses random seed\n" );
log_info( "\n" );
log_info( "Test names:\n" );
for( int i = 0; i < num_fns; i++ )
{
log_info( "\t%s\n", basefn_names[i] );
}
}

View File

@@ -0,0 +1,237 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern clCommandQueueWrapper queue;
extern clContextWrapper context;
typedef struct image_kernel_data
{
cl_int width;
cl_int channelType;
cl_int channelOrder;
cl_int expectedChannelType;
cl_int expectedChannelOrder;
};
static const char *methodTest1DImageKernelPattern =
"typedef struct {\n"
" int width;\n"
" int channelType;\n"
" int channelOrder;\n"
" int expectedChannelType;\n"
" int expectedChannelOrder;\n"
" } image_kernel_data;\n"
"__kernel void sample_kernel( read_only image1d_t input, __global image_kernel_data *outData )\n"
"{\n"
" outData->width = get_image_width( input );\n"
" outData->channelType = get_image_channel_data_type( input );\n"
" outData->channelOrder = get_image_channel_order( input );\n"
"\n"
" outData->expectedChannelType = %s;\n"
" outData->expectedChannelOrder = %s;\n"
"}";
static int test_get_1Dimage_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error = 0;
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper image, outDataBuffer;
char programSrc[ 10240 ];
image_kernel_data outKernelData;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
// Construct testing source
if( gDebugTrace )
log_info( " - Creating 1D image %d ...\n", (int)imageInfo->width );
image = create_image_1d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, 0, NULL, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 1D image of size %d (%s)", (int)imageInfo->width, IGetErrorString( error ) );
return -1;
}
char channelTypeConstantString[256] = {0};
char channelOrderConstantString[256] = {0};
const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type );
const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order );
if(channelTypeName && strlen(channelTypeName))
sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_*
if(channelOrderName && strlen(channelOrderName))
sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_*
// Create a program to run against
sprintf( programSrc, methodTest1DImageKernelPattern,
channelTypeConstantString, channelOrderConstantString);
//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_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
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" );
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( outKernelData.width != (cl_int)imageInfo->width )
{
log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width );
error = -1;
}
if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType )
{
log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ),
(int)outKernelData.expectedChannelType, (int)outKernelData.channelType );
error = -1;
}
if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder )
{
log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ),
(int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder );
error = -1;
}
if( clFinish(queue) != CL_SUCCESS )
{
log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__);
error = -1;
}
return error;
}
int test_get_image_info_1D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = imageInfo.slicePitch = 0;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if( gDebugTrace )
log_info( " at size %d\n", (int)imageInfo.width );
int ret = test_get_1Dimage_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info( "Testing %d\n", (int)sizes[ idx ][ 0 ]);
if( gDebugTrace )
log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] );
if( test_get_1Dimage_info_single( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.height * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
int ret = test_get_1Dimage_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,255 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern clCommandQueueWrapper queue;
extern clContextWrapper context;
typedef struct image_kernel_data
{
cl_int width;
cl_int arraySize;
cl_int channelType;
cl_int channelOrder;
cl_int expectedChannelType;
cl_int expectedChannelOrder;
};
static const char *methodTestKernelPattern =
"typedef struct {\n"
" int width;\n"
" int arraySize;\n"
" int channelType;\n"
" int channelOrder;\n"
" int expectedChannelType;\n"
" int expectedChannelOrder;\n"
" } image_kernel_data;\n"
"__kernel void sample_kernel( read_only image1d_array_t input, __global image_kernel_data *outData )\n"
"{\n"
" outData->width = get_image_width( input );\n"
" outData->arraySize = get_image_array_size( input );\n"
" outData->channelType = get_image_channel_data_type( input );\n"
" outData->channelOrder = get_image_channel_order( input );\n"
"\n"
" outData->expectedChannelType = %s;\n"
" outData->expectedChannelOrder = %s;\n"
"}";
int test_get_1Dimage_array_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error = 0;
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper image, outDataBuffer;
char programSrc[ 10240 ];
image_kernel_data outKernelData;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
// Construct testing source
if( gDebugTrace )
log_info( " - Creating 1D image array %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize );
image = create_image_1d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->arraySize, 0, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 1D image array of size %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->arraySize, IGetErrorString( error ) );
return -1;
}
char channelTypeConstantString[256] = {0};
char channelOrderConstantString[256] = {0};
const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type );
const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order );
if(channelTypeName && strlen(channelTypeName))
sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_*
if(channelOrderName && strlen(channelOrderName))
sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_*
// Create a program to run against
sprintf( programSrc, methodTestKernelPattern,
channelTypeConstantString, channelOrderConstantString);
//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_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
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" );
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( outKernelData.width != (cl_int)imageInfo->width )
{
log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width );
error = -1;
}
if( outKernelData.arraySize != (cl_int)imageInfo->arraySize )
{
log_error( "ERROR: Returned array size did not validate (expected %d, got %d)\n", (int)imageInfo->arraySize, (int)outKernelData.arraySize );
error = -1;
}
if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType )
{
log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ),
(int)outKernelData.expectedChannelType, (int)outKernelData.channelType );
error = -1;
}
if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder )
{
log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ),
(int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder );
error = -1;
}
if( clFinish(queue) != CL_SUCCESS )
{
log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__);
error = -1;
}
return error;
}
int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = imageInfo.slicePitch = 0;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
for( imageInfo.arraySize = 1; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize );
int ret = test_get_1Dimage_array_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ]);
if( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
if( test_get_1Dimage_array_info_single( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
imageInfo.slicePitch = imageInfo.rowPitch;
size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.arraySize * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
int ret = test_get_1Dimage_array_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,295 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern clCommandQueueWrapper queue;
extern clContextWrapper context;
typedef struct image_kernel_data
{
cl_int width;
cl_int height;
cl_int depth;
cl_int widthDim;
cl_int heightDim;
cl_int depthDim;
cl_int channelType;
cl_int channelOrder;
cl_int expectedChannelType;
cl_int expectedChannelOrder;
};
static const char *methodTestKernelPattern =
"typedef struct {\n"
" int width;\n"
" int height;\n"
" int depth;\n"
" int widthDim;\n"
" int heightDim;\n"
" int depthDim;\n"
" int channelType;\n"
" int channelOrder;\n"
" int expectedChannelType;\n"
" int expectedChannelOrder;\n"
" } image_kernel_data;\n"
"__kernel void sample_kernel( read_only image%dd%s_t input, __global image_kernel_data *outData )\n"
"{\n"
" outData->width = get_image_width( input );\n"
" outData->height = get_image_height( input );\n"
"%s\n"
" int%d dim = get_image_dim( input );\n"
" outData->widthDim = dim.x;\n"
" outData->heightDim = dim.y;\n"
"%s\n"
" outData->channelType = get_image_channel_data_type( input );\n"
" outData->channelOrder = get_image_channel_order( input );\n"
"\n"
" outData->expectedChannelType = %s;\n"
" outData->expectedChannelOrder = %s;\n"
"}";
static const char *depthKernelLine = " outData->depth = get_image_depth( input );\n";
static const char *depthDimKernelLine = " outData->depthDim = dim.z;\n";
int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error = 0;
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper image, outDataBuffer;
char programSrc[ 10240 ];
image_kernel_data outKernelData;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
// Construct testing source
if( gDebugTrace )
log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height );
if( imageInfo->depth != 0 )
image = create_image_3d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, NULL, &error );
else
image = create_image_2d( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create image of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, IGetErrorString( error ) );
return -1;
}
char channelTypeConstantString[256] = {0};
char channelOrderConstantString[256] = {0};
const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type );
const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order );
if(channelTypeName && strlen(channelTypeName))
sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_*
if(channelOrderName && strlen(channelOrderName))
sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_*
// Create a program to run against
sprintf( programSrc, methodTestKernelPattern,
( imageInfo->depth != 0 ) ? 3 : 2,
(imageInfo->format->image_channel_order == CL_DEPTH) ? "_depth" : "",
( imageInfo->depth != 0 ) ? depthKernelLine : "",
( imageInfo->depth != 0 ) ? 4 : 2,
( imageInfo->depth != 0 ) ? depthDimKernelLine : "",
channelTypeConstantString, channelOrderConstantString);
//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_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
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" );
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( outKernelData.width != (cl_int)imageInfo->width )
{
log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width );
error = -1;
}
if( outKernelData.height != (cl_int)imageInfo->height )
{
log_error( "ERROR: Returned height did not validate (expected %d, got %d)\n", (int)imageInfo->height, (int)outKernelData.height );
error = -1;
}
if( ( imageInfo->depth != 0 ) && ( outKernelData.depth != (cl_int)imageInfo->depth ) )
{
log_error( "ERROR: Returned depth did not validate (expected %d, got %d)\n", (int)imageInfo->depth, (int)outKernelData.depth );
error = -1;
}
if( outKernelData.widthDim != (cl_int)imageInfo->width )
{
log_error( "ERROR: Returned width from get_image_dim did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.widthDim );
error = -1;
}
if( outKernelData.heightDim != (cl_int)imageInfo->height )
{
log_error( "ERROR: Returned height from get_image_dim did not validate (expected %d, got %d)\n", (int)imageInfo->height, (int)outKernelData.heightDim );
error = -1;
}
if( ( imageInfo->depth != 0 ) && ( outKernelData.depthDim != (cl_int)imageInfo->depth ) )
{
log_error( "ERROR: Returned depth from get_image_dim did not validate (expected %d, got %d)\n", (int)imageInfo->depth, (int)outKernelData.depthDim );
error = -1;
}
if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType )
{
log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ),
(int)outKernelData.expectedChannelType, (int)outKernelData.channelType );
error = -1;
}
if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder )
{
log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ),
(int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder );
error = -1;
}
if( clFinish(queue) != CL_SUCCESS )
{
log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__);
error = -1;
}
return error;
}
int test_get_image_info_2D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
imageInfo.format = format;
imageInfo.depth = imageInfo.slicePitch = 0;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int ret = test_get_image_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info( "Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ]);
if( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
if( test_get_image_info_single( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size = (cl_ulong)imageInfo.rowPitch * (cl_ulong)imageInfo.height * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
int ret = test_get_image_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,272 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern clCommandQueueWrapper queue;
extern clContextWrapper context;
typedef struct image_kernel_data
{
cl_int width;
cl_int height;
cl_int arraySize;
cl_int channelType;
cl_int channelOrder;
cl_int expectedChannelType;
cl_int expectedChannelOrder;
};
static const char *methodTestKernelPattern =
"typedef struct {\n"
" int width;\n"
" int height;\n"
" int arraySize;\n"
" int channelType;\n"
" int channelOrder;\n"
" int expectedChannelType;\n"
" int expectedChannelOrder;\n"
" } image_kernel_data;\n"
"__kernel void sample_kernel( read_only %s input, __global image_kernel_data *outData )\n"
"{\n"
" outData->width = get_image_width( input );\n"
" outData->height = get_image_height( input );\n"
" outData->arraySize = get_image_array_size( input );\n"
" outData->channelType = get_image_channel_data_type( input );\n"
" outData->channelOrder = get_image_channel_order( input );\n"
"\n"
" outData->expectedChannelType = %s;\n"
" outData->expectedChannelOrder = %s;\n"
"}";
int test_get_2Dimage_array_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d )
{
int error = 0;
clProgramWrapper program;
clKernelWrapper kernel;
clMemWrapper image, outDataBuffer;
char programSrc[ 10240 ];
image_kernel_data outKernelData;
// Generate some data to test against
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
// Construct testing source
if( gDebugTrace )
log_info( " - Creating 2D image array %d by %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize );
image = create_image_2d_array( context, (cl_mem_flags)(CL_MEM_READ_ONLY), imageInfo->format, imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, NULL, &error );
if( image == NULL )
{
log_error( "ERROR: Unable to create 2D image array of size %d x %d x %d (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, IGetErrorString( error ) );
return -1;
}
char channelTypeConstantString[256] = {0};
char channelOrderConstantString[256] = {0};
const char* channelTypeName = GetChannelTypeName( imageInfo->format->image_channel_data_type );
const char* channelOrderName = GetChannelOrderName( imageInfo->format->image_channel_order );
if(channelTypeName && strlen(channelTypeName))
sprintf(channelTypeConstantString, "CLK_%s", &channelTypeName[3]); // replace CL_* with CLK_*
if(channelOrderName && strlen(channelOrderName))
sprintf(channelOrderConstantString, "CLK_%s", &channelOrderName[3]); // replace CL_* with CLK_*
// Create a program to run against
sprintf( programSrc, methodTestKernelPattern,
(imageInfo->format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t" ,
channelTypeConstantString, channelOrderConstantString);
//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_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
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" );
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( outKernelData.width != (cl_int)imageInfo->width )
{
log_error( "ERROR: Returned width did not validate (expected %d, got %d)\n", (int)imageInfo->width, (int)outKernelData.width );
error = -1;
}
if( outKernelData.height != (cl_int)imageInfo->height )
{
log_error( "ERROR: Returned height did not validate (expected %d, got %d)\n", (int)imageInfo->height, (int)outKernelData.height );
error = -1;
}
if( outKernelData.arraySize != (cl_int)imageInfo->arraySize )
{
log_error( "ERROR: Returned array size did not validate (expected %d, got %d)\n", (int)imageInfo->arraySize, (int)outKernelData.arraySize );
error = -1;
}
if( outKernelData.channelType != (cl_int)outKernelData.expectedChannelType )
{
log_error( "ERROR: Returned channel type did not validate (expected %s (%d), got %d)\n", GetChannelTypeName( imageInfo->format->image_channel_data_type ),
(int)outKernelData.expectedChannelType, (int)outKernelData.channelType );
error = -1;
}
if( outKernelData.channelOrder != (cl_int)outKernelData.expectedChannelOrder )
{
log_error( "ERROR: Returned channel order did not validate (expected %s (%d), got %d)\n", GetChannelOrderName( imageInfo->format->image_channel_order ),
(int)outKernelData.expectedChannelOrder, (int)outKernelData.channelOrder );
error = -1;
}
if( clFinish(queue) != CL_SUCCESS )
{
log_error( "ERROR: CL Finished failed in %s \n", __FUNCTION__);
error = -1;
}
return error;
}
int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize );
int ret = test_get_2Dimage_array_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( test_get_2Dimage_array_info_single( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size_t extraHeight = (int)random_log_in_range( 0, 8, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize );
int ret = test_get_2Dimage_array_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,131 @@
//
// 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"
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages;
extern int test_get_image_info_single( cl_device_id device, image_descriptor *imageInfo, MTdata d );
int test_get_image_info_3D( cl_device_id device, cl_image_format *format )
{
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
RandomSeed seed( gRandomSeed );
size_t pixelSize;
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
imageInfo.format = format;
pixelSize = get_pixel_size( imageInfo.format );
int error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ )
{
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth );
int ret = test_get_image_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.depth = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
log_info( "Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
if( test_get_image_info_single( device, &imageInfo, seed ) )
return -1;
}
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth;
do {
extraWidth++;
imageInfo.rowPitch += extraWidth;
} while ((imageInfo.rowPitch % pixelSize) != 0);
size_t extraHeight = (int)random_log_in_range( 0, 8, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4;
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth );
int ret = test_get_image_info_single( device, &imageInfo, seed );
if( ret )
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,219 @@
//
// 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"
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern int gTypesToTest;
extern int gNormalizedModeToUse;
extern cl_channel_type gChannelTypeToUse;
extern bool gDebugTrace;
extern int test_get_image_info_1D( cl_device_id device, cl_image_format *format );
extern int test_get_image_info_2D( cl_device_id device, cl_image_format *format );
extern int test_get_image_info_3D( cl_device_id device, cl_image_format *format );
extern int test_get_image_info_1D_array( cl_device_id device, cl_image_format *format );
extern int test_get_image_info_2D_array( cl_device_id device, cl_image_format *format );
static const char *str_1d_image = "1D";
static const char *str_2d_image = "2D";
static const char *str_3d_image = "3D";
static const char *str_1d_image_array = "1D array";
static const char *str_2d_image_array = "2D array";
static const char *convert_image_type_to_string(cl_mem_object_type imageType)
{
const char *p;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
p = str_1d_image;
break;
case CL_MEM_OBJECT_IMAGE2D:
p = str_2d_image;
break;
case CL_MEM_OBJECT_IMAGE3D:
p = str_3d_image;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
p = str_1d_image_array;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
p = str_2d_image_array;
break;
}
return p;
}
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if( filterFlags[ j ] )
filterFlags[ j ] = false;
// Have we already discarded this via the command line?
if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
// We don't filter by channel type
if( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags )
{
extern clContextWrapper context;
int error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
imageType, 0, NULL, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, (cl_mem_flags)flags,
imageType, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_image_type( cl_device_id device, cl_mem_object_type imageType, cl_mem_flags flags )
{
log_info( "Running %s %s-only tests...\n", convert_image_type_to_string(imageType), flags == CL_MEM_READ_ONLY ? "read" : "write" );
int ret = 0;
// Grab the list of supported image formats for integer reads
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
if( get_format_list( device, imageType, formatList, numFormats, flags ) )
return -1;
filterFlags = new bool[ numFormats ];
if( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
memset( filterFlags, 0, sizeof( bool ) * numFormats );
filter_formats( formatList, filterFlags, numFormats, 0 );
// Run the format list
for( unsigned int i = 0; i < numFormats; i++ )
{
int test_return = 0;
if( filterFlags[i] )
{
log_info( "NOT RUNNING: " );
print_header( &formatList[ i ], false );
continue;
}
print_header( &formatList[ i ], false );
gTestCount++;
switch (imageType) {
case CL_MEM_OBJECT_IMAGE1D:
test_return = test_get_image_info_1D( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE2D:
test_return = test_get_image_info_2D( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE3D:
test_return = test_get_image_info_3D( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
test_return = test_get_image_info_1D_array( device, &formatList[ i ] );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
test_return = test_get_image_info_2D_array( device, &formatList[ i ] );
break;
}
if (test_return) {
gTestFailure++;
log_error( "FAILED: " );
print_header( &formatList[ i ], true );
log_info( "\n" );
}
ret += test_return;
}
delete filterFlags;
delete formatList;
return ret;
}
int test_image_set( cl_device_id device, cl_mem_object_type imageType )
{
int version_check;
if ((version_check = check_opencl_version(device,1,2))) {
switch (imageType) {
case CL_MEM_OBJECT_IMAGE1D:
test_missing_feature(version_check, "image_1D");
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
test_missing_feature(version_check, "image_1D_array");
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
test_missing_feature(version_check, "image_2D_array");
}
}
int ret = 0;
ret += test_image_type( device, imageType, CL_MEM_READ_ONLY );
ret += test_image_type( device, imageType, CL_MEM_WRITE_ONLY );
return ret;
}

View File

@@ -0,0 +1,28 @@
set(MODULE_NAME IMAGE_STREAMS)
set(${MODULE_NAME}_SOURCES
main.cpp
test_iterations.cpp
test_loops.cpp
test_read_1D.cpp
test_read_1D_array.cpp
test_read_2D_array.cpp
test_read_3D.cpp
test_write_image.cpp
test_write_1D.cpp
test_write_1D_array.cpp
test_write_2D_array.cpp
test_write_3D.cpp
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/testHarness.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,19 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_image_streams
: main.cpp
test_iterations.cpp
test_loops.cpp
test_read_3D.cpp
test_write_image.cpp
;
install dist
: test_image_streams
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/kernel_read_write
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/kernel_read_write
;

View File

@@ -0,0 +1,56 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_iterations.cpp \
test_loops.cpp \
test_write_image.cpp \
test_read_1D.cpp \
test_read_3D.cpp \
test_read_1D_array.cpp \
test_read_2D_array.cpp \
test_write_1D.cpp \
test_write_3D.cpp \
test_write_1D_array.cpp \
test_write_2D_array.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.c \
../../../test_common/harness/mt19937.c \
../../../test_common/harness/typeWrappers.cpp
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_image_streams
INCLUDE = -I../../test_common/harness
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = 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,651 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
#include "../../../test_common/harness/fpcontrol.h"
#include <vector>
#if defined(__PPC__)
// Global varaiable used to hold the FPU control register state. The FPSCR register can not
// be used because not all Power implementations retain or observed the NI (non-IEEE
// mode) bit.
__thread fpu_control_t fpu_control = 0;
#endif
bool gDebugTrace = false, gExtraValidateInfo = false, gDisableOffsets = false, gTestSmallImages = false, gTestMaxImages = false, gTestRounding = false, gTestImage2DFromBuffer = 0, gTestMipmaps = false;
cl_filter_mode gFilterModeToUse = (cl_filter_mode)-1;
// Default is CL_MEM_USE_HOST_PTR for the test
cl_mem_flags gMemFlagsToUse = CL_MEM_USE_HOST_PTR;
bool gUseKernelSamplers = false;
int gTypesToTest = 0;
cl_addressing_mode gAddressModeToUse = (cl_addressing_mode)-1;
int gNormalizedModeToUse = 7;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
cl_channel_order gChannelOrderToUse = (cl_channel_order)-1;
bool gEnablePitch = false;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
int gtestTypesToRun = 0;
cl_command_queue queue;
cl_context context;
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if( p != NULL )
execName = p + 1;
log_info( "Usage: %s [read] [write] [CL_FILTER_LINEAR|CL_FILTER_NEAREST] [no_offsets] [debug_trace] [small_images]\n", execName );
log_info( "Where:\n" );
log_info( "\n" );
log_info( "\tThe following flags specify what kinds of operations to test. They can be combined; if none are specified, all are tested:\n" );
log_info( "\t\tread - Tests reading from an image\n" );
log_info( "\t\twrite - Tests writing to an image (can be specified with read to run both; default is both)\n" );
log_info( "\n" );
log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" );
log_info( "\t\tint - Test integer I/O (read_imagei, write_imagei)\n" );
log_info( "\t\tuint - Test unsigned integer I/O (read_imageui, write_imageui)\n" );
log_info( "\t\tfloat - Test float I/O (read_imagef, write_imagef)\n" );
log_info( "\n" );
log_info( "\tCL_FILTER_LINEAR - Only tests formats with CL_FILTER_LINEAR filtering\n" );
log_info( "\tCL_FILTER_NEAREST - Only tests formats with CL_FILTER_NEAREST filtering\n" );
log_info( "\n" );
log_info( "\tNORMALIZED - Only tests formats with NORMALIZED coordinates\n" );
log_info( "\tUNNORMALIZED - Only tests formats with UNNORMALIZED coordinates\n" );
log_info( "\n" );
log_info( "\tCL_ADDRESS_CLAMP - Only tests formats with CL_ADDRESS_CLAMP addressing\n" );
log_info( "\tCL_ADDRESS_CLAMP_TO_EDGE - Only tests formats with CL_ADDRESS_CLAMP_TO_EDGE addressing\n" );
log_info( "\tCL_ADDRESS_REPEAT - Only tests formats with CL_ADDRESS_REPEAT addressing\n" );
log_info( "\tCL_ADDRESS_MIRRORED_REPEAT - Only tests formats with CL_ADDRESS_MIRRORED_REPEAT addressing\n" );
log_info( "\n" );
log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" );
log_info( "\n" );
log_info( "\t1D - Only test 1D images\n" );
log_info( "\t2D - Only test 2D images\n" );
log_info( "\t3D - Only test 3D images\n" );
log_info( "\t1Darray - Only test 1D image arrays\n" );
log_info( "\t2Darray - Only test 2D image arrays\n" );
log_info( "\n" );
log_info( "\tlocal_samplers - Use samplers declared in the kernel functions instead of passed in as arguments\n" );
log_info( "\n" );
log_info( "\tThe following specify to use the specific flag to allocate images to use in the tests:\n" );
log_info( "\t\tCL_MEM_COPY_HOST_PTR\n" );
log_info( "\t\tCL_MEM_USE_HOST_PTR (default)\n" );
log_info( "\t\tCL_MEM_ALLOC_HOST_PTR\n" );
log_info( "\t\tNO_HOST_PTR - Specifies to use none of the above flags\n" );
log_info( "\n" );
log_info( "\tThe following modify the types of images tested:\n" );
log_info( "\t\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
log_info( "\t\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
log_info( "\t\trounding - Runs every format through a single image filled with every possible value for that image format, to verify rounding works properly\n" );
log_info( "\n" );
log_info( "\tno_offsets - Disables offsets when testing reads (can be good for diagnosing address repeating/clamping problems)\n" );
log_info( "\tdebug_trace - Enables additional debug info logging\n" );
log_info( "\textra_validate - Enables additional validation failure debug information\n" );
log_info( "\tuse_pitches - Enables row and slice pitches\n" );
log_info( "\ttest_mipmaps - Enables mipmapped images\n");
}
extern int test_image_set( cl_device_id device, test_format_set_fn formatTestFn, cl_mem_object_type imageType );
/** read_write images only support sampler-less read buildt-ins which require special settings
* for some global parameters. This pair of functions temporarily overwrite those global parameters
* and then recover them after completing a read_write test.
*/
static void overwrite_global_params_for_read_write_test( bool *tTestMipmaps,
bool *tDisableOffsets,
bool *tNormalizedModeToUse,
cl_filter_mode *tFilterModeToUse)
{
log_info("Overwrite global settings for read_write image tests. The overwritten values:\n");
log_info("gTestMipmaps = false, gDisableOffsets = true, gNormalizedModeToUse = false, gFilterModeToUse = CL_FILTER_NEAREST\n" );
// mipmap images only support sampler read built-in while read_write images only support
// sampler-less read built-in. Hence we cannot test mipmap for read_write image.
*tTestMipmaps = gTestMipmaps;
gTestMipmaps = false;
// Read_write images are read by sampler-less read which does not handle out-of-bound read
// It's application responsibility to make sure that the read happens in-bound
// Therefore we should not enable offset in testing read_write images because it will cause out-of-bound
*tDisableOffsets = gDisableOffsets;
gDisableOffsets = true;
// The sampler-less read image functions behave exactly as the corresponding read image functions
*tNormalizedModeToUse = gNormalizedModeToUse;
gNormalizedModeToUse = false;
*tFilterModeToUse = gFilterModeToUse;
gFilterModeToUse = CL_FILTER_NEAREST;
}
/** Recover the global settings overwritten for read_write tests. This is necessary because
* there may be other tests (i.e. read or write) are called together with read_write test.
*/
static void recover_global_params_from_read_write_test(bool tTestMipmaps,
bool tDisableOffsets,
bool tNormalizedModeToUse,
cl_filter_mode tFilterModeToUse)
{
gTestMipmaps = tTestMipmaps;
gDisableOffsets = tDisableOffsets;
gNormalizedModeToUse = tNormalizedModeToUse;
gFilterModeToUse = tFilterModeToUse;
}
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_device_id device;
cl_channel_type chanType;
cl_channel_order chanOrder;
char str[ 128 ];
int testTypesToRun = 0;
int testMethods = 0;
bool randomize = false;
bool tTestMipMaps = false;
bool tDisableOffsets = false;
bool tNormalizedModeToUse = false;
cl_filter_mode tFilterModeToUse = (cl_filter_mode)-1;
test_start();
//Check CL_DEVICE_TYPE environment variable
checkDeviceTypeOverride( &gDeviceType );
// Parse arguments
for( int i = 1; i < argc; i++ )
{
strncpy( str, argv[ i ], sizeof( str ) - 1 );
if( strcmp( str, "cpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if( strcmp( str, "gpu" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if( strcmp( str, "accelerator" ) == 0 || strcmp( str, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if( strcmp( str, "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if( strcmp( str, "debug_trace" ) == 0 )
gDebugTrace = true;
else if( strcmp( str, "CL_FILTER_NEAREST" ) == 0 || strcmp( str, "NEAREST" ) == 0 )
gFilterModeToUse = CL_FILTER_NEAREST;
else if( strcmp( str, "CL_FILTER_LINEAR" ) == 0 || strcmp( str, "LINEAR" ) == 0 )
gFilterModeToUse = CL_FILTER_LINEAR;
else if( strcmp( str, "CL_ADDRESS_NONE" ) == 0 )
gAddressModeToUse = CL_ADDRESS_NONE;
else if( strcmp( str, "CL_ADDRESS_CLAMP" ) == 0 )
gAddressModeToUse = CL_ADDRESS_CLAMP;
else if( strcmp( str, "CL_ADDRESS_CLAMP_TO_EDGE" ) == 0 )
gAddressModeToUse = CL_ADDRESS_CLAMP_TO_EDGE;
else if( strcmp( str, "CL_ADDRESS_REPEAT" ) == 0 )
gAddressModeToUse = CL_ADDRESS_REPEAT;
else if( strcmp( str, "CL_ADDRESS_MIRRORED_REPEAT" ) == 0 )
gAddressModeToUse = CL_ADDRESS_MIRRORED_REPEAT;
else if( strcmp( str, "NORMALIZED" ) == 0 )
gNormalizedModeToUse = true;
else if( strcmp( str, "UNNORMALIZED" ) == 0 )
gNormalizedModeToUse = false;
else if( strcmp( str, "no_offsets" ) == 0 )
gDisableOffsets = true;
else if( strcmp( str, "small_images" ) == 0 )
gTestSmallImages = true;
else if( strcmp( str, "max_images" ) == 0 )
gTestMaxImages = true;
else if( strcmp( str, "use_pitches" ) == 0 )
gEnablePitch = true;
else if( strcmp( str, "rounding" ) == 0 )
gTestRounding = true;
else if( strcmp( str, "extra_validate" ) == 0 )
gExtraValidateInfo = true;
else if( strcmp( str, "test_mipmaps" ) == 0 ) {
// 2.0 Spec does not allow using mem flags, unnormalized coordinates with mipmapped images
gTestMipmaps = true;
gMemFlagsToUse = 0;
gNormalizedModeToUse = true;
}
else if( strcmp( str, "read" ) == 0 )
testTypesToRun |= kReadTests;
else if( strcmp( str, "write" ) == 0 )
testTypesToRun |= kWriteTests;
else if( strcmp( str, "read_write" ) == 0 )
{
testTypesToRun |= kReadWriteTests;
}
else if( strcmp( str, "local_samplers" ) == 0 )
gUseKernelSamplers = true;
else if( strcmp( str, "int" ) == 0 )
gTypesToTest |= kTestInt;
else if( strcmp( str, "uint" ) == 0 )
gTypesToTest |= kTestUInt;
else if( strcmp( str, "float" ) == 0 )
gTypesToTest |= kTestFloat;
else if( strcmp( str, "randomize" ) == 0 )
randomize = true;
else if ( strcmp( str, "1D" ) == 0 )
testMethods |= k1D;
else if( strcmp( str, "2D" ) == 0 )
testMethods |= k2D;
else if( strcmp( str, "3D" ) == 0 )
testMethods |= k3D;
else if( strcmp( str, "1Darray" ) == 0 )
testMethods |= k1DArray;
else if( strcmp( str, "2Darray" ) == 0 )
testMethods |= k2DArray;
else if( strcmp( str, "CL_MEM_COPY_HOST_PTR" ) == 0 || strcmp( str, "COPY_HOST_PTR" ) == 0 )
gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
else if( strcmp( str, "CL_MEM_USE_HOST_PTR" ) == 0 || strcmp( str, "USE_HOST_PTR" ) == 0 )
gMemFlagsToUse = CL_MEM_USE_HOST_PTR;
else if( strcmp( str, "CL_MEM_ALLOC_HOST_PTR" ) == 0 || strcmp( str, "ALLOC_HOST_PTR" ) == 0 )
gMemFlagsToUse = CL_MEM_ALLOC_HOST_PTR;
else if( strcmp( str, "NO_HOST_PTR" ) == 0 )
gMemFlagsToUse = 0;
else if( strcmp( str, "help" ) == 0 || strcmp( str, "?" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if( ( chanType = get_channel_type_from_name( str ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else if( ( chanOrder = get_channel_order_from_name( str ) ) != (cl_channel_order)-1 )
gChannelOrderToUse = chanOrder;
else
{
log_error( "ERROR: Unknown argument %d: %s. Exiting....\n", i, str );
return -1;
}
}
if (testMethods == 0)
testMethods = k1D | k2D | k3D | k1DArray | k2DArray;
if( testTypesToRun == 0 )
testTypesToRun = kAllTests;
if( gTypesToTest == 0 )
gTypesToTest = kTestAllTypes;
#if defined( __APPLE__ )
#if defined( __i386__ ) || defined( __x86_64__ )
#define kHasSSE3 0x00000008
#define kHasSupplementalSSE3 0x00000100
#define kHasSSE4_1 0x00000400
#define kHasSSE4_2 0x00000800
/* check our environment for a hint to disable SSE variants */
{
const char *env = getenv( "CL_MAX_SSE" );
if( env )
{
extern int _cpu_capabilities;
int mask = 0;
if( 0 == strcmp( env, "SSE4.1" ) )
mask = kHasSSE4_2;
else if( 0 == strcmp( env, "SSSE3" ) )
mask = kHasSSE4_2 | kHasSSE4_1;
else if( 0 == strcmp( env, "SSE3" ) )
mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3;
else if( 0 == strcmp( env, "SSE2" ) )
mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3;
log_info( "*** Environment: CL_MAX_SSE = %s ***\n", env );
_cpu_capabilities &= ~mask;
}
}
#endif
#endif
// Seed the random # generators
if( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
gReSeed = 1;
log_info( "Random seed: %u\n", gRandomSeed );
}
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
cl_uint num_devices = 0;
error = clGetDeviceIDs(platform, gDeviceType, 0, NULL, &num_devices );
if( error )
{
print_error( error, "Unable to get the number of devices" );
test_finish();
return -1;
}
std::vector<cl_device_id> devices(num_devices);
error = clGetDeviceIDs(platform, gDeviceType, num_devices, &devices[0], NULL );
if( error )
{
print_error( error, "Unable to get specified device type" );
test_finish();
return -1;
}
int device_index = 0;
char* device_index_str = getenv("CL_DEVICE_INDEX");
if (device_index_str && ((device_index = atoi(device_index_str))) >= num_devices) {
log_error("CL_DEVICE_INDEX=%d is greater than the number of devices %d\n",device_index,num_devices);
test_finish();
return -1;
}
device = devices[device_index];
// Get the device type so we know if it is a GPU even if default is passed in.
error = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(gDeviceType), &gDeviceType, NULL);
if( error )
{
print_error( error, "Unable to get device type" );
test_finish();
return -1;
}
if( printDeviceHeader( device ) != CL_SUCCESS )
{
test_finish();
return -1;
}
// Check for image support
if(checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) {
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if( gTestSmallImages )
log_info( "Note: Using small test images\n" );
// On most platforms which support denorm, default is FTZ off. However,
// on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm.
// This creates issues in result verification. Since spec allows the implementation to either flush or
// not flush denorms to zero, an implementation may choose not to flush i.e. return denorm result whereas
// reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side
// where reference is being computed to make sure we get non-flushed reference result. If implementation
// returns flushed result, we correctly take care of that in verification code.
FPU_mode_type oldMode;
DisableFTZ(&oldMode);
// Run the test now
int ret = 0;
if (testMethods & k1D)
{
if (testTypesToRun & kReadTests)
{
gtestTypesToRun = kReadTests;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D );
}
if (testTypesToRun & kWriteTests)
{
gtestTypesToRun = kWriteTests;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D );
}
if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps)
{
gtestTypesToRun = kReadWriteTests;
overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse);
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D );
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D );
recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse);
}
}
if (testMethods & k2D)
{
if (testTypesToRun & kReadTests)
{
gtestTypesToRun = kReadTests;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D );
if (is_extension_available(device, "cl_khr_image2d_from_buffer"))
{
log_info("Testing read_image{f | i | ui} for 2D image from buffer\n");
// NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages, gTestRounding and gTestMipmaps must be false
if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false)
{
cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
gTestImage2DFromBuffer = true;
// disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D );
gTestImage2DFromBuffer = false;
gMemFlagsToUse = saved_gMemFlagsToUse;
}
}
}
if (testTypesToRun & kWriteTests)
{
gtestTypesToRun = kWriteTests;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D );
if (is_extension_available(device, "cl_khr_image2d_from_buffer"))
{
log_info("Testing write_image{f | i | ui} for 2D image from buffer\n");
// NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages,gTestRounding and gTestMipmaps must be false
if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false)
{
bool saved_gEnablePitch = gEnablePitch;
cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
gEnablePitch = true;
// disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
gTestImage2DFromBuffer = true;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D );
gTestImage2DFromBuffer = false;
gMemFlagsToUse = saved_gMemFlagsToUse;
gEnablePitch = saved_gEnablePitch;
}
}
}
if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps)
{
gtestTypesToRun = kReadWriteTests;
overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse);
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D );
if (is_extension_available(device, "cl_khr_image2d_from_buffer"))
{
log_info("Testing read_image{f | i | ui} for 2D image from buffer\n");
// NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages, gTestRounding and gTestMipmaps must be false
if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false)
{
cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
gTestImage2DFromBuffer = true;
// disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D );
gTestImage2DFromBuffer = false;
gMemFlagsToUse = saved_gMemFlagsToUse;
}
}
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D );
if (is_extension_available(device, "cl_khr_image2d_from_buffer"))
{
log_info("Testing write_image{f | i | ui} for 2D image from buffer\n");
// NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages,gTestRounding and gTestMipmaps must be false
if (gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false)
{
bool saved_gEnablePitch = gEnablePitch;
cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
gEnablePitch = true;
// disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
gTestImage2DFromBuffer = true;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D );
gTestImage2DFromBuffer = false;
gMemFlagsToUse = saved_gMemFlagsToUse;
gEnablePitch = saved_gEnablePitch;
}
}
recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse);
}
}
if (testMethods & k3D)
{
if (testTypesToRun & kReadTests)
{
gtestTypesToRun = kReadTests;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE3D );
}
if (testTypesToRun & kWriteTests)
{
gtestTypesToRun = kWriteTests;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE3D );
}
if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps)
{
gtestTypesToRun = kReadWriteTests;
overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse);
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE3D );
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE3D );
recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse);
}
}
if (testMethods & k1DArray)
{
if (testTypesToRun & kReadTests)
{
gtestTypesToRun = kReadTests;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY );
}
if (testTypesToRun & kWriteTests)
{
gtestTypesToRun = kWriteTests;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY );
}
if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps)
{
gtestTypesToRun = kReadWriteTests;
overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse);
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY );
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE1D_ARRAY );
recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse);
}
}
if (testMethods & k2DArray)
{
if (testTypesToRun & kReadTests)
{
gtestTypesToRun = kReadTests;
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY );
}
if (testTypesToRun & kWriteTests)
{
gtestTypesToRun = kWriteTests;
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY );
}
if ((testTypesToRun & kReadWriteTests) && !gTestMipmaps)
{
gtestTypesToRun = kReadWriteTests;
overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse);
ret += test_image_set( device, test_read_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY );
ret += test_image_set( device, test_write_image_formats, CL_MEM_OBJECT_IMAGE2D_ARRAY );
recover_global_params_from_read_write_test(tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse);
}
}
// Restore FP state before leaving
RestoreFPState(&oldMode);
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.");
clReleaseContext(context);
clReleaseCommandQueue(queue);
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d tests.\n", gTestCount, gTestCount);
else
log_info("PASSED test.\n");
} else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED test.\n");
}
// Clean up
test_finish();
if (gTestFailure > 0)
return gTestFailure;
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,466 @@
//
// 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"
extern cl_context context;
extern cl_filter_mode gFilterModeToUse;
extern cl_addressing_mode gAddressModeToUse;
extern int gTypesToTest;
extern int gNormalizedModeToUse;
extern cl_channel_type gChannelTypeToUse;
extern cl_channel_order gChannelOrderToUse;
extern bool gDebugTrace;
extern bool gTestMipmaps;
extern int gtestTypesToRun;
extern int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
bool floatCoords, ExplicitType outputType );
extern int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
bool floatCoords, ExplicitType outputType );
extern int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
bool floatCoords, ExplicitType outputType );
extern int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
bool floatCoords, ExplicitType outputType );
extern int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
bool floatCoords, ExplicitType outputType );
static const char *str_1d_image = "1D";
static const char *str_2d_image = "2D";
static const char *str_3d_image = "3D";
static const char *str_1d_image_array = "1D array";
static const char *str_2d_image_array = "2D array";
static const char *convert_image_type_to_string(cl_mem_object_type imageType)
{
const char *p;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
p = str_1d_image;
break;
case CL_MEM_OBJECT_IMAGE2D:
p = str_2d_image;
break;
case CL_MEM_OBJECT_IMAGE3D:
p = str_3d_image;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
p = str_1d_image_array;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
p = str_2d_image_array;
break;
}
return p;
}
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if( filterFlags[ j ] )
filterFlags[ j ] = false;
// skip mipmap tests for CL_DEPTH formats (re# Khronos Bug 13762)
if(gTestMipmaps && (formatList[ j ].image_channel_order == CL_DEPTH))
{
log_info("Skip mipmap tests for CL_DEPTH format\n");
filterFlags[ j ] = true;
continue;
}
// Have we already discarded the channel type via the command line?
if( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Have we already discarded the channel order via the command line?
if( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
if ( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags )
{
int error;
cl_image_format tempList[ 128 ];
error = clGetSupportedImageFormats( context, flags,
imageType, 128, tempList, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, flags,
imageType, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_read_image_type( cl_device_id device, cl_image_format *format, bool floatCoords,
image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
int ret = 0;
cl_addressing_mode *addressModes = NULL;
// The sampler-less read image functions behave exactly as the corresponding read image functions
// described in section 6.13.14.2 that take integer coordinates and a sampler with filter mode set to
// CLK_FILTER_NEAREST, normalized coordinates set to CLK_NORMALIZED_COORDS_FALSE and addressing mode to CLK_ADDRESS_NONE
cl_addressing_mode addressModes_rw[] = { CL_ADDRESS_NONE, (cl_addressing_mode)-1 };
cl_addressing_mode addressModes_ro[] = { /* CL_ADDRESS_CLAMP_NONE,*/ CL_ADDRESS_CLAMP_TO_EDGE, CL_ADDRESS_CLAMP, CL_ADDRESS_REPEAT, CL_ADDRESS_MIRRORED_REPEAT, (cl_addressing_mode)-1 };
if(gtestTypesToRun & kReadWriteTests)
{
addressModes = addressModes_rw;
}
else
{
addressModes = addressModes_ro;
}
#if defined( __APPLE__ )
// According to the OpenCL specification, we do not guarantee the precision
// of operations for linear filtering on the GPU. We do not test linear
// filtering for the CL_RGB CL_UNORM_INT_101010 image format; however, we
// test it internally for a set of other image formats.
if ((gDeviceType == CL_DEVICE_TYPE_GPU) &&
(imageSampler->filter_mode == CL_FILTER_LINEAR) &&
(format->image_channel_order == CL_RGB) &&
(format->image_channel_data_type == CL_UNORM_INT_101010))
{
log_info("--- Skipping CL_RGB CL_UNORM_INT_101010 format with CL_FILTER_LINEAR on GPU.\n");
return 0;
}
#endif
for( int adMode = 0; addressModes[ adMode ] != (cl_addressing_mode)-1; adMode++ )
{
imageSampler->addressing_mode = addressModes[ adMode ];
if( (addressModes[ adMode ] == CL_ADDRESS_REPEAT || addressModes[ adMode ] == CL_ADDRESS_MIRRORED_REPEAT) && !( imageSampler->normalized_coords ) )
continue; // Repeat doesn't make sense for non-normalized coords
// Use this run if we were told to only run a certain filter mode
if( gAddressModeToUse != (cl_addressing_mode)-1 && imageSampler->addressing_mode != gAddressModeToUse )
continue;
/*
Remove redundant check to see if workaround still necessary
// Check added in because this case was leaking through causing a crash on CPU
if( ! imageSampler->normalized_coords && imageSampler->addressing_mode == CL_ADDRESS_REPEAT )
continue; //repeat mode requires normalized coordinates
*/
print_read_header( format, imageSampler, false );
gTestCount++;
int retCode = 0;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
retCode = test_read_image_set_1D( device, format, imageSampler, floatCoords, outputType );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
retCode = test_read_image_set_1D_array( device, format, imageSampler, floatCoords, outputType );
break;
case CL_MEM_OBJECT_IMAGE2D:
retCode = test_read_image_set_2D( device, format, imageSampler, floatCoords, outputType );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
retCode = test_read_image_set_2D_array( device, format, imageSampler, floatCoords, outputType );
break;
case CL_MEM_OBJECT_IMAGE3D:
retCode = test_read_image_set_3D( device, format, imageSampler, floatCoords, outputType );
break;
}
if( retCode != 0 )
{
gTestFailure++;
log_error( "FAILED: " );
print_read_header( format, imageSampler, true );
log_info( "\n" );
}
ret |= retCode;
}
return ret;
}
int test_read_image_formats( cl_device_id device, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
int ret = 0;
bool flipFlop[2] = { false, true };
int normalizedIdx, floatCoordIdx;
// Use this run if we were told to only run a certain filter mode
if( gFilterModeToUse != (cl_filter_mode)-1 && imageSampler->filter_mode != gFilterModeToUse )
return 0;
// Test normalized/non-normalized
for( normalizedIdx = 0; normalizedIdx < 2; normalizedIdx++ )
{
imageSampler->normalized_coords = flipFlop[ normalizedIdx ];
if( gNormalizedModeToUse != 7 && gNormalizedModeToUse != (int)imageSampler->normalized_coords )
continue;
for( floatCoordIdx = 0; floatCoordIdx < 2; floatCoordIdx++ )
{
// Checks added in because this case was leaking through causing a crash on CPU
if( !flipFlop[ floatCoordIdx ] )
if( imageSampler->filter_mode != CL_FILTER_NEAREST || // integer coords can only be used with nearest
flipFlop[ normalizedIdx ]) // Normalized integer coords makes no sense (they'd all be zero)
continue;
if( flipFlop[ floatCoordIdx ] && (gtestTypesToRun & kReadWriteTests))
// sampler-less read in read_write tests run only integer coord
continue;
log_info( "read_image (%s coords, %s results) *****************************\n",
flipFlop[ floatCoordIdx ] ? ( imageSampler->normalized_coords ? "normalized float" : "unnormalized float" ) : "integer",
get_explicit_type_name( outputType ) );
for( unsigned int i = 0; i < numFormats; i++ )
{
if( filterFlags[i] )
continue;
cl_image_format &imageFormat = formatList[ i ];
ret |= test_read_image_type( device, &imageFormat, flipFlop[ floatCoordIdx ], imageSampler, outputType, imageType );
}
}
}
return ret;
}
int test_image_set( cl_device_id device, test_format_set_fn formatTestFn, cl_mem_object_type imageType )
{
int ret = 0;
static int printedFormatList = -1;
if ( ( 0 == is_extension_available( device, "cl_khr_3d_image_writes" )) && (imageType == CL_MEM_OBJECT_IMAGE3D) && (formatTestFn == test_write_image_formats) )
{
gTestFailure++;
log_error( "-----------------------------------------------------\n" );
log_error( "FAILED: test writing CL_MEM_OBJECT_IMAGE3D images\n" );
log_error( "This device does not support the mandated extension cl_khr_3d_image_writes.\n");
log_error( "-----------------------------------------------------\n\n" );
return -1;
}
if ( gTestMipmaps )
{
if ( 0 == is_extension_available( device, "cl_khr_mipmap_image" ))
{
log_info( "-----------------------------------------------------\n" );
log_info( "This device does not support cl_khr_mipmap_image.\nSkipping mipmapped image test. \n" );
log_info( "-----------------------------------------------------\n\n" );
return 0;
}
if ( ( 0 == is_extension_available( device, "cl_khr_mipmap_image_writes" )) && (formatTestFn == test_write_image_formats))
{
log_info( "-----------------------------------------------------\n" );
log_info( "This device does not support cl_khr_mipmap_image_writes.\nSkipping mipmapped image write test. \n" );
log_info( "-----------------------------------------------------\n\n" );
return 0;
}
}
int version_check = check_opencl_version(device,1,2);
if (version_check != 0) {
switch (imageType) {
case CL_MEM_OBJECT_IMAGE1D:
test_missing_feature(version_check, "image_1D");
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
test_missing_feature(version_check, "image_1D_array");
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
test_missing_feature(version_check, "image_2D_array");
}
}
// Grab the list of supported image formats for integer reads
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
// This flag is only for querying the list of supported formats
// The flag for creating image will be set explicitly in test functions
cl_mem_flags flags;
const char *flagNames;
if( formatTestFn == test_read_image_formats )
{
if(gtestTypesToRun & kReadTests)
{
flags = CL_MEM_READ_ONLY;
flagNames = "read";
}
else
{
flags = CL_MEM_KERNEL_READ_AND_WRITE;
flagNames = "read_write";
}
}
else
{
if(gtestTypesToRun & kWriteTests)
{
flags = CL_MEM_WRITE_ONLY;
flagNames = "write";
}
else
{
flags = CL_MEM_KERNEL_READ_AND_WRITE;
flagNames = "read_write";
}
}
if( get_format_list( device, imageType, formatList, numFormats, flags ) )
return -1;
BufferOwningPtr<cl_image_format> formatListBuf(formatList);
filterFlags = new bool[ numFormats ];
if( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
BufferOwningPtr<bool> filterFlagsBuf(filterFlags);
memset( filterFlags, 0, sizeof( bool ) * numFormats );
// First time through, we'll go ahead and print the formats supported, regardless of type
int test = imageType | (formatTestFn == test_read_image_formats ? (1 << 16) : (1 << 17));
if( printedFormatList != test )
{
log_info( "---- Supported %s %s formats for this device ---- \n", convert_image_type_to_string(imageType), flagNames );
for( unsigned int f = 0; f < numFormats; f++ )
{
if ( IsChannelOrderSupported( formatList[ f ].image_channel_order ) && IsChannelTypeSupported( formatList[ f ].image_channel_data_type ) )
log_info( " %-7s %-24s %d\n", GetChannelOrderName( formatList[ f ].image_channel_order ),
GetChannelTypeName( formatList[ f ].image_channel_data_type ),
(int)get_format_channel_count( &formatList[ f ] ) );
}
log_info( "------------------------------------------- \n" );
printedFormatList = test;
}
image_sampler_data imageSampler;
/////// float tests ///////
if( gTypesToTest & kTestFloat )
{
cl_channel_type floatFormats[] = { CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010,
#ifdef OBSOLETE_FORAMT
CL_UNORM_SHORT_565_REV, CL_UNORM_SHORT_555_REV, CL_UNORM_INT_8888, CL_UNORM_INT_8888_REV, CL_UNORM_INT_101010_REV,
#endif
#ifdef CL_SFIXED14_APPLE
CL_SFIXED14_APPLE,
#endif
CL_UNORM_INT8, CL_SNORM_INT8,
CL_UNORM_INT16, CL_SNORM_INT16, CL_FLOAT, CL_HALF_FLOAT, (cl_channel_type)-1 };
if( filter_formats( formatList, filterFlags, numFormats, floatFormats ) == 0 )
{
log_info( "No formats supported for float type\n" );
}
else
{
imageSampler.filter_mode = CL_FILTER_NEAREST;
ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kFloat, imageType );
imageSampler.filter_mode = CL_FILTER_LINEAR;
ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kFloat, imageType );
}
}
/////// int tests ///////
if( gTypesToTest & kTestInt )
{
cl_channel_type intFormats[] = { CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, (cl_channel_type)-1 };
if( filter_formats( formatList, filterFlags, numFormats, intFormats ) == 0 )
{
log_info( "No formats supported for integer type\n" );
}
else
{
// Only filter mode we support on int is nearest
imageSampler.filter_mode = CL_FILTER_NEAREST;
ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kInt, imageType );
}
}
/////// uint tests ///////
if( gTypesToTest & kTestUInt )
{
cl_channel_type uintFormats[] = { CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, (cl_channel_type)-1 };
if( filter_formats( formatList, filterFlags, numFormats, uintFormats ) == 0 )
{
log_info( "No formats supported for unsigned int type\n" );
}
else
{
// Only filter mode we support on uint is nearest
imageSampler.filter_mode = CL_FILTER_NEAREST;
ret += formatTestFn( device, formatList, filterFlags, numFormats, &imageSampler, kUInt, imageType );
}
}
return ret;
}

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,696 @@
//
// 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(_WIN32)
#include <sys/mman.h>
#endif
#define MAX_ERR 0.005f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToSkip;
extern cl_mem_flags gMemFlagsToUse;
extern int gtestTypesToRun;
const char *readwrite1DKernelSourcePattern =
"__kernel void sample_kernel( __global %s4 *input, read_write image1d_t output %s)\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int offset = tidX;\n"
" write_image%s( output, tidX %s, input[ offset ]);\n"
"}";
const char *write1DKernelSourcePattern =
"__kernel void sample_kernel( __global %s4 *input, write_only image1d_t output %s)\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int offset = tidX;\n"
" write_image%s( output, tidX %s, input[ offset ]);\n"
"}";
int test_write_image_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, ExplicitType inputType, MTdata d )
{
int totalErrors = 0;
size_t num_flags = 0;
const cl_mem_flags *mem_flag_types = NULL;
const char * *mem_flag_names = NULL;
const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE };
const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" };
const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE};
const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"};
if(gtestTypesToRun & kWriteTests)
{
mem_flag_types = write_only_mem_flag_types;
mem_flag_names = write_only_mem_flag_names;
num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] );
}
else
{
mem_flag_types = read_write_mem_flag_types;
mem_flag_names = read_write_mem_flag_names;
num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] );
}
for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ )
{
int error;
size_t threads[2];
bool verifyRounding = false;
int totalErrors = 0;
int forceCorrectlyRoundedWrites = 0;
#if defined( __APPLE__ )
// Require Apple's CPU implementation to be correctly rounded, not just within 0.6
cl_device_type type = 0;
if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL )))
{
log_error("Error: Could not get device type for Apple device! (%d) \n", error );
return 1;
}
if( type == CL_DEVICE_TYPE_CPU )
forceCorrectlyRoundedWrites = 1;
#endif
if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
BufferOwningPtr<char> maxImageUseHostPtrBackingStore, imageValues;
create_random_image_data( inputType, imageInfo, imageValues, d );
if(!gTestMipmaps)
{
if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT && imageInfo->format->image_channel_data_type != CL_HALF_FLOAT )
{
/* Pilot data for sRGB images */
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// We want to generate ints (mostly) in range of the target format which should be [0,255]
// However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that
// it can test some out-of-range data points
const unsigned int test_range_ext = 16;
int formatMin = 0 - test_range_ext;
int formatMax = 255 + test_range_ext;
int pixel_value = 0;
float *inputValues = NULL;
// First, fill with arbitrary floats
{
inputValues = (float *)(char*)imageValues;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
{
pixel_value = random_in_range( formatMin, (int)formatMax, d );
inputValues[ i ] = (float)(pixel_value/255.0f);
}
}
// Throw a few extra test values in there
inputValues = (float *)(char*)imageValues;
size_t i = 0;
// Piloting some debug inputs.
inputValues[ i++ ] = -0.5f;
inputValues[ i++ ] = 0.5f;
inputValues[ i++ ] = 2.f;
inputValues[ i++ ] = 0.5f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
}
}
else
{
// First, fill with arbitrary floats
{
float *inputValues = (float *)(char*)imageValues;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
inputValues[ i ] = get_random_float( -0.1f, 1.1f, d );
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = -0.0000000000009f;
inputValues[ i++ ] = 1.f;
inputValues[ i++ ] = -1.f;
inputValues[ i++ ] = 2.f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
verifyRounding = true;
}
}
}
else if( inputType == kUInt )
{
unsigned int *inputValues = (unsigned int*)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = 0;
inputValues[ i++ ] = 65535;
inputValues[ i++ ] = 7271820;
inputValues[ i++ ] = 0;
}
}
// Construct testing sources
clProtectedImage protImage;
clMemWrapper unprotImage;
cl_mem image;
if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR )
{
// clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian)
// Do not use protected images for max image size test since it rounds the row size to a page size
if (gTestMaxImages) {
create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d );
unprotImage = create_image_1d( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format,
imageInfo->width, 0,
maxImageUseHostPtrBackingStore, NULL, &error );
} else {
error = protImage.Create( context, mem_flag_types[mem_flag_index], imageInfo->format, imageInfo->width );
}
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 1D image of size %ld pitch %ld (%s, %s)\n", imageInfo->width,
imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
if (gTestMaxImages)
image = (cl_mem)unprotImage;
else
image = (cl_mem)protImage;
}
else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none
{
// Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise
// it works just as if no flag is specified, so we just do the same thing either way
// Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data
if( gTestMipmaps )
{
cl_image_desc image_desc = {0};
image_desc.image_type = imageInfo->type;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image_desc.image_width = imageInfo->width;
image_desc.image_array_size = imageInfo->arraySize;
unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ),
imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level 1D image of size %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width,
IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
else
{
unprotImage = create_image_1d( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format,
imageInfo->width, 0,
imageValues, NULL, &error );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 1D image of size %ld pitch %ld (%s, %s)\n", imageInfo->width,
imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
image = unprotImage;
}
error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image );
test_error( error, "Unable to set kernel arguments" );
size_t width_lod = imageInfo->width, nextLevelOffset = 0;
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, 1, 1 };
size_t resultSize;
for( int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
if(gTestMipmaps)
{
error = clSetKernelArg( kernel, 2, sizeof( int ), &lod );
}
clMemWrapper inputStream;
char *imagePtrOffset = imageValues + nextLevelOffset;
inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ),
get_explicit_type_size( inputType ) * 4 * width_lod, imagePtrOffset, &error );
test_error( error, "Unable to create input buffer" );
// Set arguments
error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream );
test_error( error, "Unable to set kernel arguments" );
// Run the kernel
threads[0] = (size_t)width_lod;
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
// Get results
if( gTestMipmaps )
resultSize = width_lod * get_pixel_size( imageInfo->format );
else
resultSize = imageInfo->rowPitch;
clProtectedArray PA(resultSize);
char *resultValues = (char *)((void *)PA);
if( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) );
origin[ 1 ] = lod;
region[ 0 ] = width_lod;
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if( gDebugTrace )
log_info( " results read\n" );
// Validate results element by element
char *imagePtr = imageValues + nextLevelOffset;
int numTries = 5;
{
char *resultPtr = (char *)resultValues;
for( size_t x = 0, i = 0; x < width_lod; x++, i++ )
{
char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each
// Convert this pixel
if( inputType == kFloat )
pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer );
else if( inputType == kInt )
pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer );
else // if( inputType == kUInt )
pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer );
// Compare against the results
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// Compare sRGB-mapped values
cl_float expected[4] = {0};
cl_float* input_values = (float*)imagePtr;
cl_uchar *actual = (cl_uchar*)resultPtr;
float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR;
float err[4] = {0.0f};
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if(j < 3)
{
expected[j] = sRGBmap(input_values[j]);
}
else // there is no sRGB conversion for alpha component if it exists
{
expected[j] = NORMALIZE(input_values[j], 255.0f);
}
err[j] = fabsf( expected[ j ] - actual[ j ] );
}
if ((err[0] > max_err) ||
(err[1] > max_err) ||
(err[2] > max_err) ||
(err[3] > 0)) // there is no conversion for alpha so the error should be zero
{
log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]);
log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3));
log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_FLOAT )
{
// Compare floats
float *expected = (float *)resultBuffer;
float *actual = (float *)resultPtr;
float err = 0.f;
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] );
err /= (float)get_format_channel_count( imageInfo->format );
if( err > MAX_ERR )
{
unsigned int *e = (unsigned int *)expected;
unsigned int *a = (unsigned int *)actual;
log_error( "ERROR: Sample %ld (%ld) did not validate! (%s)\n", i, x, mem_flag_names[mem_flag_index] );
log_error( " Error: %g\n", err );
log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] );
log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] );
totalErrors++;
if( ( --numTries ) == 0 )
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
{
// Compare half floats
if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 )
{
cl_ushort *e = (cl_ushort *)resultBuffer;
cl_ushort *a = (cl_ushort *)resultPtr;
int err_cnt = 0;
//Fix up cases where we have NaNs
for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if( is_half_nan( e[j] ) && is_half_nan(a[j]) )
continue;
if( e[j] != a[j] )
err_cnt++;
}
if( err_cnt )
{
totalErrors++;
log_error( "ERROR: Sample %ld (%ld) did not validate! (%s)\n", i, x, mem_flag_names[mem_flag_index] );
log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] );
log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] );
if( inputType == kFloat )
{
float *p = (float *)(char *)imagePtr;
log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
}
if( ( --numTries ) == 0 )
return 1;
}
}
}
else
{
// Exact result passes every time
if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 )
{
// result is inexact. Calculate error
int failure = 1;
float errors[4] = {NAN, NAN, NAN, NAN};
pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors );
// We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats
if( 0 == forceCorrectlyRoundedWrites &&
(
imageInfo->format->image_channel_data_type == CL_UNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT16 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT16
))
{
if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) &&
! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) )
failure = 0;
}
if( failure )
{
totalErrors++;
// Is it our special rounding test?
if( verifyRounding && i >= 1 && i <= 2 )
{
// Try to guess what the rounding mode of the device really is based on what it returned
const char *deviceRounding = "unknown";
unsigned int deviceResults[8];
read_image_pixel<unsigned int>( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod);
read_image_pixel<unsigned int>( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod );
if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 )
deviceRounding = "truncate";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to nearest";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to even";
log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] );
log_error( " Actual values rounded by device: %x %x %x %x %x %x %x %x\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ],
deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] );
log_error( " Rounding mode of device appears to be %s\n", deviceRounding );
return 1;
}
log_error( "ERROR: Sample %d (%d) did not validate!\n", (int)i, (int)x );
switch(imageInfo->format->image_channel_data_type)
{
case CL_UNORM_INT8:
case CL_SNORM_INT8:
case CL_UNSIGNED_INT8:
case CL_SIGNED_INT8:
log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] );
log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNORM_INT16:
case CL_SNORM_INT16:
case CL_UNSIGNED_INT16:
case CL_SIGNED_INT16:
#ifdef CL_SFIXED14_APPLE
case CL_SFIXED14_APPLE:
#endif
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_HALF_FLOAT:
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNSIGNED_INT32:
case CL_SIGNED_INT32:
log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] );
log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] );
break;
case CL_FLOAT:
log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] );
log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
}
float *v = (float *)(char *)imagePtr;
log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] );
if( ( --numTries ) == 0 )
return 1;
}
}
}
imagePtr += get_explicit_type_size( inputType ) * 4;
resultPtr += get_pixel_size( imageInfo->format );
}
}
{
nextLevelOffset += width_lod * get_pixel_size( imageInfo->format );
width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1;
}
}
}
// All done!
return totalErrors;
}
int test_write_image_1D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
clProgramWrapper program;
clKernelWrapper kernel;
const char *KernelSourcePattern = NULL;
int error;
// Get our operating parameters
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
size_t pixelSize;
image_descriptor imageInfo = { 0x0 };
imageInfo.format = format;
imageInfo.slicePitch = imageInfo.arraySize = 0;
imageInfo.height = imageInfo.depth = 1;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if( inputType == kInt )
readFormat = "i";
else if( inputType == kUInt )
readFormat = "ui";
else // kFloat
readFormat = "f";
// Construct the source
if(gtestTypesToRun & kWriteTests)
{
KernelSourcePattern = write1DKernelSourcePattern;
}
else
{
KernelSourcePattern = readwrite1DKernelSourcePattern;
}
sprintf( programSrc,
KernelSourcePattern,
get_explicit_type_name( inputType ),
gTestMipmaps ? ", int lod" : "",
readFormat,
gTestMipmaps ? ", lod" :"" );
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if(gTestMipmaps)
imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d);
if( gDebugTrace )
log_info( " at size %d\n", (int)imageInfo.width );
int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format, CL_TRUE);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
if(gTestMipmaps)
imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d);
log_info("Testing %d\n", (int)imageInfo.width);
int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
else if( gTestRounding )
{
size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 );
imageInfo.width = typeRange / 256;
imageInfo.rowPitch = imageInfo.width * pixelSize;
int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, d );
if( gTestMipmaps)
{
imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d);
size = (cl_ulong) compute_mipmapped_image_size(imageInfo) * 4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.rowPitch += extraWidth * pixelSize;
}
size = (size_t)imageInfo.rowPitch * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
{
log_info( " at size %d (pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
if( gTestMipmaps )
log_info( " and %d mip levels\n", (int)imageInfo.num_mip_levels );
}
int retCode = test_write_image_1D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,723 @@
//
// 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(_WIN32)
#include <sys/mman.h>
#endif
#define MAX_ERR 0.005f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToSkip;
extern cl_mem_flags gMemFlagsToUse;
extern int gtestTypesToRun;
const char *readwrite1DArrayKernelSourcePattern =
"__kernel void sample_kernel( __global %s4 *input, read_write image1d_array_t output %s)\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
"%s"
" write_image%s( output, (int2)( tidX, tidY )%s, input[ offset ]);\n"
"}";
const char *write1DArrayKernelSourcePattern =
"__kernel void sample_kernel( __global %s4 *input, write_only image1d_array_t output %s)\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
"%s"
" write_image%s( output, (int2)( tidX, tidY ) %s, input[ offset ]);\n"
"}";
const char *offset1DArraySource =
" int offset = tidY*get_image_width(output) + tidX;\n";
const char *offset1DArrayLodSource =
" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n"
" int offset = tidY*width_lod + tidX;\n";
int test_write_image_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, ExplicitType inputType, MTdata d )
{
int totalErrors = 0;
size_t num_flags = 0;
const cl_mem_flags *mem_flag_types = NULL;
const char * *mem_flag_names = NULL;
const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE };
const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" };
const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE};
const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"};
if(gtestTypesToRun & kWriteTests)
{
mem_flag_types = write_only_mem_flag_types;
mem_flag_names = write_only_mem_flag_names;
num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] );
}
else
{
mem_flag_types = read_write_mem_flag_types;
mem_flag_names = read_write_mem_flag_names;
num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] );
}
size_t pixelSize = get_pixel_size( imageInfo->format );
for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ )
{
int error;
size_t threads[2];
bool verifyRounding = false;
int totalErrors = 0;
int forceCorrectlyRoundedWrites = 0;
#if defined( __APPLE__ )
// Require Apple's CPU implementation to be correctly rounded, not just within 0.6
cl_device_type type = 0;
if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL )))
{
log_error("Error: Could not get device type for Apple device! (%d) \n", error );
return 1;
}
if( type == CL_DEVICE_TYPE_CPU )
forceCorrectlyRoundedWrites = 1;
#endif
if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
BufferOwningPtr<char> maxImageUseHostPtrBackingStore, imageValues;
create_random_image_data( inputType, imageInfo, imageValues, d );
if(!gTestMipmaps)
{
if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT && imageInfo->format->image_channel_data_type != CL_HALF_FLOAT )
{
/* Pilot data for sRGB images */
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// We want to generate ints (mostly) in range of the target format which should be [0,255]
// However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that
// it can test some out-of-range data points
const unsigned int test_range_ext = 16;
int formatMin = 0 - test_range_ext;
int formatMax = 255 + test_range_ext;
int pixel_value = 0;
// First, fill with arbitrary floats
for( size_t y = 0; y < imageInfo->arraySize; y++ )
{
float *inputValues = (float *)(char*)imageValues + y * imageInfo->width * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
{
pixel_value = random_in_range( formatMin, (int)formatMax, d );
inputValues[ i ] = (float)(pixel_value/255.0f);
}
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
// Piloting some debug inputs.
inputValues[ i++ ] = -0.5f;
inputValues[ i++ ] = 0.5f;
inputValues[ i++ ] = 2.f;
inputValues[ i++ ] = 0.5f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
}
}
else
{
// First, fill with arbitrary floats
for( size_t y = 0; y < imageInfo->arraySize; y++ )
{
float *inputValues = (float *)(char*)imageValues + y * imageInfo->width * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
inputValues[ i ] = get_random_float( -0.1f, 1.1f, d );
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = -0.0000000000009f;
inputValues[ i++ ] = 1.f;
inputValues[ i++ ] = -1.f;
inputValues[ i++ ] = 2.f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
verifyRounding = true;
}
}
}
else if( inputType == kUInt )
{
unsigned int *inputValues = (unsigned int*)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = 0;
inputValues[ i++ ] = 65535;
inputValues[ i++ ] = 7271820;
inputValues[ i++ ] = 0;
}
}
// Construct testing sources
clProtectedImage protImage;
clMemWrapper unprotImage;
cl_mem image;
if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR )
{
// clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian)
// Do not use protected images for max image size test since it rounds the row size to a page size
if (gTestMaxImages) {
create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d );
unprotImage = create_image_1d_array( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format,
imageInfo->width, imageInfo->arraySize, 0, 0,
maxImageUseHostPtrBackingStore, &error );
} else {
error = protImage.Create( context, (cl_mem_object_type)CL_MEM_OBJECT_IMAGE1D_ARRAY, mem_flag_types[mem_flag_index], imageInfo->format, imageInfo->width, 1, 1, imageInfo->arraySize );
}
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 1D image array of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->arraySize,
imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
if (gTestMaxImages)
image = (cl_mem)unprotImage;
else
image = (cl_mem)protImage;
}
else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none
{
// Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise
// it works just as if no flag is specified, so we just do the same thing either way
// Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data
if( gTestMipmaps )
{
cl_image_desc image_desc = {0};
image_desc.image_type = imageInfo->type;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image_desc.image_width = imageInfo->width;
image_desc.image_array_size = imageInfo->arraySize;
unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ),
imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level 1D image array of size %ld x %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->arraySize,
IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
else
{
unprotImage = create_image_1d_array( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format,
imageInfo->width, imageInfo->arraySize, 0, 0,
imageValues, &error );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 1D image array of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->arraySize,
imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
image = unprotImage;
}
error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image );
test_error( error, "Unable to set kernel arguments" );
size_t width_lod = imageInfo->width, nextLevelOffset = 0;
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, imageInfo->arraySize, 1 };
size_t resultSize;
for( int lod = 0; (gTestMipmaps && lod < imageInfo->num_mip_levels) || (!gTestMipmaps && lod < 1); lod++)
{
if(gTestMipmaps)
{
error = clSetKernelArg( kernel, 2, sizeof( int ), &lod );
}
// Run the kernel
threads[0] = (size_t)width_lod;
threads[1] = (size_t)imageInfo->arraySize;
clMemWrapper inputStream;
char *imagePtrOffset = imageValues + nextLevelOffset;
inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ),
get_explicit_type_size( inputType ) * 4 * width_lod * imageInfo->arraySize, imagePtrOffset, &error );
test_error( error, "Unable to create input buffer" );
// Set arguments
error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream );
test_error( error, "Unable to set kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
// Get results
if( gTestMipmaps )
resultSize = width_lod * get_pixel_size(imageInfo->format) * imageInfo->arraySize;
else
resultSize = imageInfo->rowPitch * imageInfo->arraySize;
clProtectedArray PA(resultSize);
char *resultValues = (char *)((void *)PA);
if( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) );
origin[2] = lod;
region[0] = width_lod;
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region,
gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if( gDebugTrace )
log_info( " results read\n" );
// Validate results element by element
char *imagePtr = imageValues + nextLevelOffset;
int numTries = 5;
for( size_t y = 0, i = 0; y < imageInfo->arraySize; y++ )
{
char *resultPtr;
if( gTestMipmaps )
resultPtr = (char *)resultValues + y * width_lod * pixelSize;
else
resultPtr = (char*)resultValues + y * imageInfo->rowPitch;
for( size_t x = 0; x < width_lod; x++, i++ )
{
char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each
// Convert this pixel
if( inputType == kFloat )
pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer );
else if( inputType == kInt )
pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer );
else // if( inputType == kUInt )
pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer );
// Compare against the results
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// Compare sRGB-mapped values
cl_float expected[4] = {0};
cl_float* input_values = (float*)imagePtr;
cl_uchar *actual = (cl_uchar*)resultPtr;
float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR;
float err[4] = {0.0f};
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if(j < 3)
{
expected[j] = sRGBmap(input_values[j]);
}
else // there is no sRGB conversion for alpha component if it exists
{
expected[j] = NORMALIZE(input_values[j], 255.0f);
}
err[j] = fabsf( expected[ j ] - actual[ j ] );
}
if ((err[0] > max_err) ||
(err[1] > max_err) ||
(err[2] > max_err) ||
(err[3] > 0)) // there is no conversion for alpha so the error should be zero
{
log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]);
log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3));
log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_FLOAT )
{
// Compare floats
float *expected = (float *)resultBuffer;
float *actual = (float *)resultPtr;
float err = 0.f;
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] );
err /= (float)get_format_channel_count( imageInfo->format );
if( err > MAX_ERR )
{
unsigned int *e = (unsigned int *)expected;
unsigned int *a = (unsigned int *)actual;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
log_error( " Error: %g\n", err );
log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] );
log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] );
totalErrors++;
if( ( --numTries ) == 0 )
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
{
// Compare half floats
if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 )
{
cl_ushort *e = (cl_ushort *)resultBuffer;
cl_ushort *a = (cl_ushort *)resultPtr;
int err_cnt = 0;
//Fix up cases where we have NaNs
for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if( is_half_nan( e[j] ) && is_half_nan(a[j]) )
continue;
if( e[j] != a[j] )
err_cnt++;
}
if( err_cnt )
{
totalErrors++;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] );
log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] );
if( inputType == kFloat )
{
float *p = (float *)(char *)imagePtr;
log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
}
if( ( --numTries ) == 0 )
return 1;
}
}
}
else
{
// Exact result passes every time
if( memcmp( resultBuffer, resultPtr, pixelSize ) != 0 )
{
// result is inexact. Calculate error
int failure = 1;
float errors[4] = {NAN, NAN, NAN, NAN};
pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors );
// We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats
if( 0 == forceCorrectlyRoundedWrites &&
(
imageInfo->format->image_channel_data_type == CL_UNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT16 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT16
))
{
if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) &&
! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) )
failure = 0;
}
if( failure )
{
totalErrors++;
// Is it our special rounding test?
if( verifyRounding && i >= 1 && i <= 2 )
{
// Try to guess what the rounding mode of the device really is based on what it returned
const char *deviceRounding = "unknown";
unsigned int deviceResults[8];
read_image_pixel<unsigned int>( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod );
read_image_pixel<unsigned int>( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod );
if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 )
deviceRounding = "truncate";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to nearest";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to even";
log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] );
log_error( " Actual values rounded by device: %x %x %x %x %x %x %x %x\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ],
deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] );
log_error( " Rounding mode of device appears to be %s\n", deviceRounding );
return 1;
}
log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y );
switch(imageInfo->format->image_channel_data_type)
{
case CL_UNORM_INT8:
case CL_SNORM_INT8:
case CL_UNSIGNED_INT8:
case CL_SIGNED_INT8:
log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] );
log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNORM_INT16:
case CL_SNORM_INT16:
case CL_UNSIGNED_INT16:
case CL_SIGNED_INT16:
#ifdef CL_SFIXED14_APPLE
case CL_SFIXED14_APPLE:
#endif
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_HALF_FLOAT:
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNSIGNED_INT32:
case CL_SIGNED_INT32:
log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] );
log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] );
break;
case CL_FLOAT:
log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] );
log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
}
float *v = (float *)(char *)imagePtr;
log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] );
if( ( --numTries ) == 0 )
return 1;
}
}
}
imagePtr += get_explicit_type_size( inputType ) * 4;
resultPtr += pixelSize;
}
}
{
nextLevelOffset += width_lod * imageInfo->arraySize * get_pixel_size(imageInfo->format);
width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1;
}
}
}
// All done!
return totalErrors;
}
int test_write_image_1D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
clProgramWrapper program;
clKernelWrapper kernel;
const char *KernelSourcePattern = NULL;
int error;
// Get our operating parameters
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
size_t pixelSize;
image_descriptor imageInfo = { 0x0 };
imageInfo.format = format;
imageInfo.slicePitch = 0;
imageInfo.height = imageInfo.depth = 1;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if( inputType == kInt )
readFormat = "i";
else if( inputType == kUInt )
readFormat = "ui";
else // kFloat
readFormat = "f";
if(gtestTypesToRun & kWriteTests)
{
KernelSourcePattern = write1DArrayKernelSourcePattern;
}
else
{
KernelSourcePattern = readwrite1DArrayKernelSourcePattern;
}
// Construct the source
// Construct the source
sprintf( programSrc,
KernelSourcePattern,
get_explicit_type_name( inputType ),
gTestMipmaps ? ", int lod" : "",
gTestMipmaps ? offset1DArrayLodSource : offset1DArraySource,
readFormat,
gTestMipmaps ? ", lod" :"" );
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if(gTestMipmaps)
imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d);
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize );
int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format, CL_TRUE);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
if(gTestMipmaps)
imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d);
log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.arraySize);
int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
else if( gTestRounding )
{
size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 );
imageInfo.arraySize = typeRange / 256;
imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.arraySize );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, d );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, d );
if( gTestMipmaps)
{
imageInfo.num_mip_levels = (size_t)random_in_range(2, (compute_max_mip_levels(imageInfo.width, 0, 0)-1), d);
size = (cl_ulong) compute_mipmapped_image_size(imageInfo) * 4;
}
else
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.rowPitch += extraWidth * pixelSize;
}
imageInfo.slicePitch = imageInfo.rowPitch;
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
int retCode = test_write_image_1D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,771 @@
//
// 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(_WIN32)
#include <sys/mman.h>
#endif
#define MAX_ERR 0.005f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToSkip;
extern cl_mem_flags gMemFlagsToUse;
extern int gtestTypesToRun;
extern int verify_write_results( size_t &i, int &numTries, int &totalErrors, char *&imagePtr, void *resultValues, size_t y, size_t z,
ExplicitType inputType, image_descriptor *imageInfo, bool verifyRounding );
// Utility function to clamp down image sizes for certain tests to avoid
// using too much memory.
static size_t reduceImageSizeRange(size_t maxDimSize) {
size_t DimSize = maxDimSize/32;
if (DimSize < (size_t) 16)
return 16;
else if (DimSize > (size_t) 128)
return 128;
else
return DimSize;
}
static size_t reduceImageDepth(size_t maxDepth) {
size_t Depth = maxDepth/32;
if (Depth < (size_t) 8)
return 8;
else if (Depth > (size_t) 32)
return 32;
else
return Depth;
}
const char *write2DArrayKernelSourcePattern =
"__kernel void sample_kernel( __global %s%s *input, write_only %s output %s)\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
"%s"
" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ]);\n"
"}";
const char *readwrite2DArrayKernelSourcePattern =
"__kernel void sample_kernel( __global %s%s *input, read_write %s output %s)\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
"%s"
" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ] );\n"
"}";
const char *offset2DArrayKernelSource =
" int offset = tidZ*get_image_width(output)*get_image_height(output) + tidY*get_image_width(output) + tidX;\n";
const char *offset2DArrayLodKernelSource =
" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n"
" int height_lod = ( get_image_height(output) >> lod ) ? ( get_image_height(output) >> lod ) : 1;\n"
" int offset = tidZ*width_lod*height_lod + tidY*width_lod + tidX;\n";
int test_write_image_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, ExplicitType inputType, MTdata d )
{
int totalErrors = 0;
size_t num_flags = 0;
const cl_mem_flags *mem_flag_types = NULL;
const char * *mem_flag_names = NULL;
const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE };
const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" };
const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE};
const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"};
if(gtestTypesToRun & kWriteTests)
{
mem_flag_types = write_only_mem_flag_types;
mem_flag_names = write_only_mem_flag_names;
num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] );
}
else
{
mem_flag_types = read_write_mem_flag_types;
mem_flag_names = read_write_mem_flag_names;
num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] );
}
size_t pixelSize = get_pixel_size( imageInfo->format );
for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ )
{
int error;
size_t threads[3];
bool verifyRounding = false;
int totalErrors = 0;
int forceCorrectlyRoundedWrites = 0;
#if defined( __APPLE__ )
// Require Apple's CPU implementation to be correctly rounded, not just within 0.6
cl_device_type type = 0;
if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL )))
{
log_error("Error: Could not get device type for Apple device! (%d) \n", error );
return 1;
}
if( type == CL_DEVICE_TYPE_CPU )
forceCorrectlyRoundedWrites = 1;
#endif
if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
BufferOwningPtr<char> maxImageUseHostPtrBackingStore, imageValues;
create_random_image_data( inputType, imageInfo, imageValues, d );
if(!gTestMipmaps)
{
if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT )
{
/* Pilot data for sRGB images */
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// We want to generate ints (mostly) in range of the target format which should be [0,255]
// However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that
// it can test some out-of-range data points
const unsigned int test_range_ext = 16;
int formatMin = 0 - test_range_ext;
int formatMax = 255 + test_range_ext;
int pixel_value = 0;
// First, fill with arbitrary floats
for( size_t z = 0; z < imageInfo->arraySize; z++ )
{
for( size_t y = 0; y < imageInfo->height; y++ )
{
float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
{
pixel_value = random_in_range( formatMin, (int)formatMax, d );
inputValues[ i ] = (float)(pixel_value/255.0f);
}
}
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
// Piloting some debug inputs.
inputValues[ i++ ] = -0.5f;
inputValues[ i++ ] = 0.5f;
inputValues[ i++ ] = 2.f;
inputValues[ i++ ] = 0.5f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
}
}
else
{
// First, fill with arbitrary floats
for( size_t z = 0; z < imageInfo->arraySize; z++ )
{
for( size_t y = 0; y < imageInfo->height; y++ )
{
float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
inputValues[ i ] = get_random_float( -0.1f, 1.1f, d );
}
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = -0.0000000000009f;
inputValues[ i++ ] = 1.f;
inputValues[ i++ ] = -1.f;
inputValues[ i++ ] = 2.f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
verifyRounding = true;
}
}
}
else if( inputType == kUInt )
{
unsigned int *inputValues = (unsigned int*)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = 0;
inputValues[ i++ ] = 65535;
inputValues[ i++ ] = 7271820;
inputValues[ i++ ] = 0;
}
}
// Construct testing sources
clProtectedImage protImage;
clMemWrapper unprotImage;
cl_mem image;
if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR )
{
create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d );
unprotImage = create_image_2d_array( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format,
imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0,
maxImageUseHostPtrBackingStore, &error );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 2D image array of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->arraySize, imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
image = (cl_mem)unprotImage;
}
else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none
{
// Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise
// it works just as if no flag is specified, so we just do the same thing either way
// Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data
if( gTestMipmaps )
{
cl_image_desc image_desc = {0};
image_desc.image_type = imageInfo->type;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_array_size = imageInfo->arraySize;
unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ),
imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level 2D image array of size %ld x %ld x %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->height, imageInfo->arraySize,
IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
else
{
unprotImage = create_image_2d_array( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format,
imageInfo->width, imageInfo->height, imageInfo->arraySize, 0, 0, imageValues, &error );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 2D image array of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->arraySize, imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
}
image = unprotImage;
}
error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image );
test_error( error, "Unable to set kernel arguments" );
size_t width_lod = imageInfo->width, height_lod = imageInfo->height, nextLevelOffset = 0;
size_t origin[ 4 ] = { 0, 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, imageInfo->height, imageInfo->arraySize };
size_t resultSize;
int num_lod_loops = (gTestMipmaps)? imageInfo->num_mip_levels : 1;
for( int lod = 0; lod < num_lod_loops; lod++)
{
if(gTestMipmaps)
{
error = clSetKernelArg( kernel, 2, sizeof( int ), &lod );
}
// Run the kernel
threads[0] = (size_t)width_lod;
threads[1] = (size_t)height_lod;
threads[2] = (size_t)imageInfo->arraySize;
clMemWrapper inputStream;
char *imagePtrOffset = imageValues + nextLevelOffset;
inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ),
get_explicit_type_size( inputType ) * 4 * width_lod * height_lod * imageInfo->arraySize, imagePtrOffset, &error );
test_error( error, "Unable to create input buffer" );
// Set arguments
error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream );
test_error( error, "Unable to set kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
// Get results
if( gTestMipmaps )
resultSize = width_lod * height_lod *imageInfo->arraySize * pixelSize;
else
resultSize = imageInfo->slicePitch *imageInfo->arraySize;
clProtectedArray PA(resultSize);
char *resultValues = (char *)((void *)PA);
if( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) );
origin[3] = lod;
region[0] = width_lod;
region[1] = height_lod;
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if( gDebugTrace )
log_info( " results read\n" );
// Validate results element by element
char *imagePtr = imageValues + nextLevelOffset;
int numTries = 5;
for( size_t z = 0, i = 0; z < imageInfo->arraySize; z++ )
{
for( size_t y = 0; y < height_lod; y++ )
{
char *resultPtr;
if( gTestMipmaps )
resultPtr = (char *)resultValues + y * width_lod * pixelSize + z * width_lod * height_lod * pixelSize;
else
resultPtr = (char*)resultValues + y * imageInfo->rowPitch + z * imageInfo->slicePitch;
for( size_t x = 0; x < width_lod; x++, i++ )
{
char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each
// Convert this pixel
if( inputType == kFloat )
pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer );
else if( inputType == kInt )
pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer );
else // if( inputType == kUInt )
pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer );
// Compare against the results
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// Compare sRGB-mapped values
cl_float expected[4] = {0};
cl_float* input_values = (float*)imagePtr;
cl_uchar *actual = (cl_uchar*)resultPtr;
float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR;
float err[4] = {0.0f};
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if(j < 3)
{
expected[j] = sRGBmap(input_values[j]);
}
else // there is no sRGB conversion for alpha component if it exists
{
expected[j] = NORMALIZE(input_values[j], 255.0f);
}
err[j] = fabsf( expected[ j ] - actual[ j ] );
}
if ((err[0] > max_err) ||
(err[1] > max_err) ||
(err[2] > max_err) ||
(err[3] > 0)) // there is no conversion for alpha so the error should be zero
{
log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]);
log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3));
log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_FLOAT )
{
// Compare floats
float *expected = (float *)resultBuffer;
float *actual = (float *)resultPtr;
float err = 0.f;
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] );
err /= (float)get_format_channel_count( imageInfo->format );
if( err > MAX_ERR )
{
unsigned int *e = (unsigned int *)expected;
unsigned int *a = (unsigned int *)actual;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
log_error( " Error: %g\n", err );
log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] );
log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] );
totalErrors++;
if( ( --numTries ) == 0 )
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
{
// Compare half floats
if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 )
{
cl_ushort *e = (cl_ushort *)resultBuffer;
cl_ushort *a = (cl_ushort *)resultPtr;
int err_cnt = 0;
//Fix up cases where we have NaNs
for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if( is_half_nan( e[j] ) && is_half_nan(a[j]) )
continue;
if( e[j] != a[j] )
err_cnt++;
}
if( err_cnt )
{
totalErrors++;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
unsigned short *e = (unsigned short *)resultBuffer;
unsigned short *a = (unsigned short *)resultPtr;
log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] );
log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] );
if( inputType == kFloat )
{
float *p = (float *)(char *)imagePtr;
log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
}
if( ( --numTries ) == 0 )
return 1;
}
}
}
else
{
// Exact result passes every time
if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 )
{
// result is inexact. Calculate error
int failure = 1;
float errors[4] = {NAN, NAN, NAN, NAN};
pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors );
// We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats
if( 0 == forceCorrectlyRoundedWrites &&
(
imageInfo->format->image_channel_data_type == CL_UNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT16 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT16
))
{
if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) &&
! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) )
failure = 0;
}
if( failure )
{
totalErrors++;
// Is it our special rounding test?
if( verifyRounding && i >= 1 && i <= 2 )
{
// Try to guess what the rounding mode of the device really is based on what it returned
const char *deviceRounding = "unknown";
unsigned int deviceResults[8];
read_image_pixel<unsigned int>( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod);
read_image_pixel<unsigned int>( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod );
if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 )
deviceRounding = "truncate";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to nearest";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to even";
log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] );
log_error( " Actual values rounded by device: %d %d %d %d %d %d %d %d\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ],
deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] );
log_error( " Rounding mode of device appears to be %s\n", deviceRounding );
return 1;
}
log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y );
switch(imageInfo->format->image_channel_data_type)
{
case CL_UNORM_INT8:
case CL_SNORM_INT8:
case CL_UNSIGNED_INT8:
case CL_SIGNED_INT8:
log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] );
log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNORM_INT16:
case CL_SNORM_INT16:
case CL_UNSIGNED_INT16:
case CL_SIGNED_INT16:
#ifdef CL_SFIXED14_APPLE
case CL_SFIXED14_APPLE:
#endif
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_HALF_FLOAT:
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNSIGNED_INT32:
case CL_SIGNED_INT32:
log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] );
log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] );
break;
case CL_FLOAT:
log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] );
log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
}
float *v = (float *)(char *)imagePtr;
log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] );
if( ( --numTries ) == 0 )
return 1;
}
}
}
imagePtr += get_explicit_type_size( inputType ) * (( imageInfo->format->image_channel_order == CL_DEPTH ) ? 1 : 4);
resultPtr += get_pixel_size( imageInfo->format );
}
}
}
{
nextLevelOffset += width_lod*height_lod*imageInfo->arraySize*pixelSize;
width_lod = (width_lod >> 1) ? (width_lod >> 1) : 1;
height_lod = (height_lod >> 1) ? (height_lod >> 1) : 1;
}
}
}
// All done!
return totalErrors;
}
int test_write_image_2D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
clProgramWrapper program;
clKernelWrapper kernel;
const char *KernelSourcePattern = NULL;
int error;
// Get our operating parameters
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0x0 };
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
imageInfo.depth = 1;
imageInfo.slicePitch = 0;
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if( inputType == kInt )
readFormat = "i";
else if( inputType == kUInt )
readFormat = "ui";
else // kFloat
readFormat = "f";
if(gtestTypesToRun & kWriteTests)
{
KernelSourcePattern = write2DArrayKernelSourcePattern;
}
else
{
KernelSourcePattern = readwrite2DArrayKernelSourcePattern;
}
// Construct the source
// Construct the source
sprintf( programSrc,
KernelSourcePattern,
get_explicit_type_name( inputType ),
(format->image_channel_order == CL_DEPTH) ? "" : "4",
(format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t",
gTestMipmaps ? " , int lod" : "",
gTestMipmaps ? offset2DArrayLodKernelSource : offset2DArrayKernelSource,
readFormat,
gTestMipmaps ? ", lod" : "" );
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
for( imageInfo.arraySize = 2; imageInfo.arraySize < 7; imageInfo.arraySize++ )
{
if( gTestMipmaps )
imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d);
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize );
int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format, CL_TRUE);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
if( gTestMipmaps )
imageInfo.num_mip_levels = (size_t) random_in_range(2, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d);
log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize);
int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
else if( gTestRounding )
{
size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 );
imageInfo.height = typeRange / 256;
imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height );
imageInfo.arraySize = 2;
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
int maxWidthRange = (int) reduceImageSizeRange(maxWidth);
int maxHeighthRange = (int) reduceImageSizeRange(maxHeight);
int maxArraySizeRange = (int) reduceImageDepth(maxArraySize);
cl_ulong size, buffSize;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, maxWidthRange, d );
imageInfo.height = (size_t)random_log_in_range( 16, maxHeighthRange, d );
imageInfo.arraySize = (size_t)random_log_in_range( 8, maxArraySizeRange, d );
if(gTestMipmaps)
{
imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, 0) - 1), d);
//Need to take into account the input buffer size, otherwise we will end up with input buffer that is exceeding MaxAlloc
size = 4 * compute_mipmapped_image_size(imageInfo);
buffSize = size * get_explicit_type_size( inputType );
}
else
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.slicePitch += extraWidth * imageInfo.rowPitch;
}
// Image size and buffer size may differ due to different pixel size.
// See creation of buffer at line ~153.
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4;
buffSize = (cl_ulong)imageInfo.width * (cl_ulong)imageInfo.height * imageInfo.arraySize * get_explicit_type_size(inputType) * 4;
}
} while( size > maxAllocSize || buffSize > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %ld,%ld,%ld (pitch %ld, slice %ld) out of %ld,%ld,%ld\n", imageInfo.width, imageInfo.height, imageInfo.arraySize,
imageInfo.rowPitch, imageInfo.slicePitch, maxWidth, maxHeight, maxArraySize );
int retCode = test_write_image_2D_array( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,768 @@
//
// 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(_WIN32)
#include <sys/mman.h>
#endif
#define MAX_ERR 0.005f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestMipmaps;
extern cl_filter_mode gFilterModeToSkip;
extern cl_mem_flags gMemFlagsToUse;
extern int gtestTypesToRun;
extern int verify_write_results( size_t &i, int &numTries, int &totalErrors, char *&imagePtr, void *resultValues, size_t y, size_t z,
ExplicitType inputType, image_descriptor *imageInfo, bool verifyRounding );
// Utility function to clamp down image sizes for certain tests to avoid
// using too much memory.
static size_t reduceImageSizeRange(size_t maxDimSize, MTdata& seed) {
size_t DimSize = random_log_in_range(8, (int) maxDimSize/32, seed);
if (DimSize > (size_t) 128)
return 128;
else
return DimSize;
}
static size_t reduceImageDepth(size_t maxDimSize, MTdata& seed) {
size_t DimSize = random_log_in_range(8, (int) maxDimSize/32, seed);
if (DimSize > (size_t) 32)
return 32;
else
return DimSize;
}
const char *write3DKernelSourcePattern =
"%s"
"__kernel void sample_kernel( __global %s4 *input, write_only image3d_t output %s )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
"%s"
" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ]);\n"
"}";
const char *readwrite3DKernelSourcePattern =
"%s"
"__kernel void sample_kernel( __global %s4 *input, read_write image3d_t output %s )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
"%s"
" write_image%s( output, (int4)( tidX, tidY, tidZ, 0 ) %s, input[ offset ]);\n"
"}";
const char *khr3DWritesPragma =
"#pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable\n";
const char *offset3DSource=
" int offset = tidZ*get_image_width(output)*get_image_height(output) + tidY*get_image_width(output) + tidX;\n";
const char *offset3DLodSource =
" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n"
" int height_lod = ( get_image_height(output) >> lod ) ? ( get_image_height(output) >> lod ) : 1;\n"
" int offset = tidZ*width_lod*height_lod + tidY*width_lod + tidX;\n";
int test_write_image_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, ExplicitType inputType, MTdata d )
{
int totalErrors = 0;
size_t num_flags = 0;
const cl_mem_flags *mem_flag_types = NULL;
const char * *mem_flag_names = NULL;
const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE };
const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" };
const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE};
const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"};
if(gtestTypesToRun & kWriteTests)
{
mem_flag_types = write_only_mem_flag_types;
mem_flag_names = write_only_mem_flag_names;
num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] );
}
else
{
mem_flag_types = read_write_mem_flag_types;
mem_flag_names = read_write_mem_flag_names;
num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] );
}
size_t pixelSize = get_pixel_size( imageInfo->format );
for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ )
{
int error;
size_t threads[3];
bool verifyRounding = false;
int totalErrors = 0;
int forceCorrectlyRoundedWrites = 0;
#if defined( __APPLE__ )
// Require Apple's CPU implementation to be correctly rounded, not just within 0.6
cl_device_type type = 0;
if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL )))
{
log_error("Error: Could not get device type for Apple device! (%d) \n", error );
return 1;
}
if( type == CL_DEVICE_TYPE_CPU )
forceCorrectlyRoundedWrites = 1;
#endif
if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
BufferOwningPtr<char> maxImageUseHostPtrBackingStore, imageValues;
create_random_image_data( inputType, imageInfo, imageValues, d );
if(!gTestMipmaps)
{
if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT )
{
/* Pilot data for sRGB images */
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// We want to generate ints (mostly) in range of the target format which should be [0,255]
// However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that
// it can test some out-of-range data points
const unsigned int test_range_ext = 16;
int formatMin = 0 - test_range_ext;
int formatMax = 255 + test_range_ext;
int pixel_value = 0;
// First, fill with arbitrary floats
for( size_t z = 0; z < imageInfo->depth; z++ )
{
for( size_t y = 0; y < imageInfo->height; y++ )
{
float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
{
pixel_value = random_in_range( formatMin, (int)formatMax, d );
inputValues[ i ] = (float)(pixel_value/255.0f);
}
}
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
// Piloting some debug inputs.
inputValues[ i++ ] = -0.5f;
inputValues[ i++ ] = 0.5f;
inputValues[ i++ ] = 2.f;
inputValues[ i++ ] = 0.5f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
}
}
else
{
// First, fill with arbitrary floats
for( size_t z = 0; z < imageInfo->depth; z++ )
{
for( size_t y = 0; y < imageInfo->height; y++ )
{
float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4 + imageInfo->height * imageInfo->width * z * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
inputValues[ i ] = get_random_float( -0.1f, 1.1f, d );
}
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = -0.0000000000009f;
inputValues[ i++ ] = 1.f;
inputValues[ i++ ] = -1.f;
inputValues[ i++ ] = 2.f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
verifyRounding = true;
}
}
}
else if( inputType == kUInt )
{
unsigned int *inputValues = (unsigned int*)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = 0;
inputValues[ i++ ] = 65535;
inputValues[ i++ ] = 7271820;
inputValues[ i++ ] = 0;
}
}
// Construct testing sources
clProtectedImage protImage;
clMemWrapper unprotImage;
cl_mem image;
if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR )
{
create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d );
unprotImage = create_image_3d( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format,
imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0,
maxImageUseHostPtrBackingStore, &error );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 3D image of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->depth, imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
image = (cl_mem)unprotImage;
}
else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none
{
// Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise
// it works just as if no flag is specified, so we just do the same thing either way
// Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data
if(gTestMipmaps)
{
cl_image_desc image_desc = {0};
image_desc.image_type = imageInfo->type;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_depth = imageInfo->depth;
unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ),
imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level mipmapped 3D image of size %ld x %ld *%ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->height, imageInfo->depth,
IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
else
{
unprotImage = create_image_3d( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format,
imageInfo->width, imageInfo->height, imageInfo->depth, 0, 0, imageValues, &error );
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 3D image of size %ld x %ld x %ld pitch %ld (%s)\n", imageInfo->width, imageInfo->height, imageInfo->depth, imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
}
image = unprotImage;
}
error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image );
test_error( error, "Unable to set kernel arguments" );
size_t width_lod = imageInfo->width;
size_t height_lod = imageInfo->height;
size_t depth_lod = imageInfo->depth;
size_t nextLevelOffset = 0;
size_t origin[ 4 ] = { 0, 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, imageInfo->height, imageInfo->depth };
int num_lod_loops = (gTestMipmaps)? imageInfo->num_mip_levels : 1;
for( int lod = 0; lod < num_lod_loops; lod++)
{
if(gTestMipmaps)
{
error = clSetKernelArg( kernel, 2, sizeof( int ), &lod );
}
// Run the kernel
threads[0] = (size_t)width_lod;
threads[1] = (size_t)height_lod;
threads[2] = (size_t)depth_lod;
clMemWrapper inputStream;
char *imagePtrOffset = imageValues + nextLevelOffset;
inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ),
get_explicit_type_size( inputType ) * 4 * width_lod * height_lod * depth_lod, imagePtrOffset, &error );
test_error( error, "Unable to create input buffer" );
// Set arguments
error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream );
test_error( error, "Unable to set kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
// Get results
size_t resultSize;
if(gTestMipmaps)
resultSize = width_lod * height_lod * depth_lod * pixelSize;
else
resultSize = imageInfo->slicePitch *imageInfo->depth;
clProtectedArray PA(resultSize);
char *resultValues = (char *)((void *)PA);
if( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) );
origin[3] = lod;
region[0] = width_lod;
region[1] = height_lod;
region[2] = depth_lod;
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, gEnablePitch ? imageInfo->slicePitch : 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if( gDebugTrace )
log_info( " results read\n" );
// Validate results element by element
char *imagePtr = (char*)imageValues + nextLevelOffset;
int numTries = 5;
for( size_t z = 0, i = 0; z < depth_lod; z++ )
{
for( size_t y = 0; y < height_lod; y++ )
{
char *resultPtr;
if( gTestMipmaps )
resultPtr = (char *)resultValues + y * width_lod * pixelSize + z * width_lod * height_lod * pixelSize;
else
resultPtr = (char *)resultValues + y * imageInfo->rowPitch + z * imageInfo->slicePitch;
for( size_t x = 0; x < width_lod; x++, i++ )
{
char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each
// Convert this pixel
if( inputType == kFloat )
pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer );
else if( inputType == kInt )
pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer );
else // if( inputType == kUInt )
pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer );
// Compare against the results
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// Compare sRGB-mapped values
cl_float expected[4] = {0};
cl_float* input_values = (float*)imagePtr;
cl_uchar *actual = (cl_uchar*)resultPtr;
float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR;
float err[4] = {0.0f};
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if(j < 3)
{
expected[j] = sRGBmap(input_values[j]);
}
else // there is no sRGB conversion for alpha component if it exists
{
expected[j] = NORMALIZE(input_values[j], 255.0f);
}
err[j] = fabsf( expected[ j ] - actual[ j ] );
}
if ((err[0] > max_err) ||
(err[1] > max_err) ||
(err[2] > max_err) ||
(err[3] > FLT_EPSILON)) // there is no conversion for alpha
{
log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]);
log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3));
log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_FLOAT )
{
// Compare floats
float *expected = (float *)resultBuffer;
float *actual = (float *)resultPtr;
float err = 0.f;
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] );
err /= (float)get_format_channel_count( imageInfo->format );
if( err > MAX_ERR )
{
unsigned int *e = (unsigned int *)expected;
unsigned int *a = (unsigned int *)actual;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
log_error( " Error: %g\n", err );
log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] );
log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] );
totalErrors++;
if( ( --numTries ) == 0 )
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
{
// Compare half floats
if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 )
{
cl_ushort *e = (cl_ushort *)resultBuffer;
cl_ushort *a = (cl_ushort *)resultPtr;
int err_cnt = 0;
//Fix up cases where we have NaNs
for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if( is_half_nan( e[j] ) && is_half_nan(a[j]) )
continue;
if( e[j] != a[j] )
err_cnt++;
}
if( err_cnt )
{
totalErrors++;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
unsigned short *e = (unsigned short *)resultBuffer;
unsigned short *a = (unsigned short *)resultPtr;
log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] );
log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] );
if( inputType == kFloat )
{
float *p = (float *)(char *)imagePtr;
log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
}
if( ( --numTries ) == 0 )
return 1;
}
}
}
else
{
// Exact result passes every time
if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 )
{
// result is inexact. Calculate error
int failure = 1;
float errors[4] = {NAN, NAN, NAN, NAN};
pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors );
// We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats
if( 0 == forceCorrectlyRoundedWrites &&
(
imageInfo->format->image_channel_data_type == CL_UNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT16 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT16
))
{
if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) &&
! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) )
failure = 0;
}
if( failure )
{
totalErrors++;
// Is it our special rounding test?
if( verifyRounding && i >= 1 && i <= 2 )
{
// Try to guess what the rounding mode of the device really is based on what it returned
const char *deviceRounding = "unknown";
unsigned int deviceResults[8];
read_image_pixel<unsigned int>( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod );
read_image_pixel<unsigned int>( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod );
if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 )
deviceRounding = "truncate";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to nearest";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to even";
log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] );
log_error( " Actual values rounded by device: %d %d %d %d %d %d %d %d\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ],
deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] );
log_error( " Rounding mode of device appears to be %s\n", deviceRounding );
return 1;
}
log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y );
switch(imageInfo->format->image_channel_data_type)
{
case CL_UNORM_INT8:
case CL_SNORM_INT8:
case CL_UNSIGNED_INT8:
case CL_SIGNED_INT8:
log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] );
log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNORM_INT16:
case CL_SNORM_INT16:
case CL_UNSIGNED_INT16:
case CL_SIGNED_INT16:
#ifdef CL_SFIXED14_APPLE
case CL_SFIXED14_APPLE:
#endif
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_HALF_FLOAT:
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNSIGNED_INT32:
case CL_SIGNED_INT32:
log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] );
log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] );
break;
case CL_FLOAT:
log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] );
log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
}
float *v = (float *)(char *)imagePtr;
log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] );
if( ( --numTries ) == 0 )
return 1;
}
}
}
imagePtr += get_explicit_type_size( inputType ) * 4;
resultPtr += get_pixel_size( imageInfo->format );
}
}
}
{
nextLevelOffset += width_lod * height_lod * depth_lod * pixelSize;
width_lod = ( width_lod >> 1 ) ? ( width_lod >> 1 ) : 1;
height_lod = ( height_lod >> 1 ) ? ( height_lod >> 1 ) : 1;
depth_lod = ( depth_lod >> 1 ) ? ( depth_lod >> 1 ) : 1;
}
}
}
// All done!
return totalErrors;
}
int test_write_image_3D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
clProgramWrapper program;
clKernelWrapper kernel;
const char *KernelSourcePattern = NULL;
int error;
// Get our operating parameters
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0x0 };
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if( inputType == kInt )
readFormat = "i";
else if( inputType == kUInt )
readFormat = "ui";
else // kFloat
readFormat = "f";
if(gtestTypesToRun & kWriteTests)
{
KernelSourcePattern = write3DKernelSourcePattern;
}
else
{
KernelSourcePattern = readwrite3DKernelSourcePattern;
}
// Construct the source
sprintf( programSrc,
KernelSourcePattern,
gTestMipmaps ? "" : khr3DWritesPragma,
get_explicit_type_name( inputType ),
gTestMipmaps ? ", int lod" : "",
gTestMipmaps ? offset3DLodSource : offset3DSource,
readFormat,
gTestMipmaps ? ", lod" : "" );
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
for( imageInfo.depth = 2; imageInfo.depth < 7; imageInfo.depth++ )
{
if (gTestMipmaps)
imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth) - 1), d);
if( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth );
int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format, CL_TRUE);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.depth = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
if (gTestMipmaps)
imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth) - 1), d);
log_info("Testing %d x %d x %d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth);
int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
else if( gTestRounding )
{
size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 );
imageInfo.height = typeRange / 256;
imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height );
imageInfo.depth = 1;
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
else
{
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = reduceImageSizeRange(maxWidth, d );
imageInfo.height = reduceImageSizeRange(maxHeight, d );
imageInfo.depth = reduceImageDepth(maxDepth, d );
if(gTestMipmaps)
{
imageInfo.num_mip_levels = (size_t) random_in_range(2,(compute_max_mip_levels(imageInfo.width, imageInfo.height, imageInfo.depth) - 1), d);
//Need to take into account the input buffer size, otherwise we will end up with input buffer that is exceeding MaxAlloc
size = 4 * compute_mipmapped_image_size(imageInfo) * get_explicit_type_size( inputType );
}
else
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format );
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.slicePitch += extraWidth * imageInfo.rowPitch;
}
size = (size_t)imageInfo.slicePitch * (size_t)imageInfo.depth * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %ld,%ld,%ld (pitch %ld, slice %ld) out of %ld,%ld,%ld\n", imageInfo.width, imageInfo.height, imageInfo.depth,
imageInfo.rowPitch, imageInfo.slicePitch, maxWidth, maxHeight, maxDepth );
int retCode = test_write_image_3D( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,887 @@
//
// 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(_WIN32)
#include <sys/mman.h>
#endif
#define MAX_ERR 0.005f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gDisableOffsets, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding, gTestImage2DFromBuffer, gTestMipmaps;
extern cl_filter_mode gFilterModeToSkip;
extern cl_mem_flags gMemFlagsToUse;
extern int gtestTypesToRun;
extern int test_write_image_1D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d );
extern int test_write_image_3D_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d );
extern int test_write_image_1D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d );
extern int test_write_image_2D_array_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d );
const char *writeKernelSourcePattern =
"__kernel void sample_kernel( __global %s%s *input, write_only %s output %s)\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
"%s"
" write_image%s( output, (int2)( tidX, tidY ) %s, input[ offset ]);\n"
"}";
const char *read_writeKernelSourcePattern =
"__kernel void sample_kernel( __global %s%s *input, read_write %s output %s)\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
"%s"
" write_image%s( output, (int2)( tidX, tidY )%s, input[ offset ] );\n"
"}";
const char *offset2DKernelSource =
" int offset = tidY*get_image_width(output) + tidX;\n";
const char *offset2DLodKernelSource =
" int width_lod = ( get_image_width(output) >> lod ) ? ( get_image_width(output) >> lod ) : 1;\n"
" int offset = tidY * width_lod + tidX;\n";
int test_write_image( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, ExplicitType inputType, MTdata d )
{
int totalErrors = 0;
size_t num_flags = 0;
const cl_mem_flags *mem_flag_types = NULL;
const char * *mem_flag_names = NULL;
const cl_mem_flags write_only_mem_flag_types[2] = { CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE };
const char * write_only_mem_flag_names[2] = { "CL_MEM_WRITE_ONLY", "CL_MEM_READ_WRITE" };
const cl_mem_flags read_write_mem_flag_types[1] = { CL_MEM_READ_WRITE};
const char * read_write_mem_flag_names[1] = { "CL_MEM_READ_WRITE"};
if(gtestTypesToRun & kWriteTests)
{
mem_flag_types = write_only_mem_flag_types;
mem_flag_names = write_only_mem_flag_names;
num_flags = sizeof( write_only_mem_flag_types ) / sizeof( write_only_mem_flag_types[0] );
}
else
{
mem_flag_types = read_write_mem_flag_types;
mem_flag_names = read_write_mem_flag_names;
num_flags = sizeof( read_write_mem_flag_types ) / sizeof( read_write_mem_flag_types[0] );
}
size_t pixelSize = get_pixel_size( imageInfo->format );
int channel_scale = (imageInfo->format->image_channel_order == CL_DEPTH) ? 1 : 4;
for( size_t mem_flag_index = 0; mem_flag_index < num_flags; mem_flag_index++ )
{
int error;
size_t threads[2];
bool verifyRounding = false;
int totalErrors = 0;
int forceCorrectlyRoundedWrites = 0;
#if defined( __APPLE__ )
// Require Apple's CPU implementation to be correctly rounded, not just within 0.6
cl_device_type type = 0;
if( (error = clGetDeviceInfo( device, CL_DEVICE_TYPE, sizeof( type), &type, NULL )))
{
log_error("Error: Could not get device type for Apple device! (%d) \n", error );
return 1;
}
if( type == CL_DEVICE_TYPE_CPU )
forceCorrectlyRoundedWrites = 1;
#endif
if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
if( DetectFloatToHalfRoundingMode(queue) )
return 1;
BufferOwningPtr<char> maxImageUseHostPtrBackingStore, imageValues, imageBufferValues;
create_random_image_data( inputType, imageInfo, imageValues, d, gTestImage2DFromBuffer );
if(!gTestMipmaps)
{
if( inputType == kFloat && imageInfo->format->image_channel_data_type != CL_FLOAT && imageInfo->format->image_channel_data_type != CL_HALF_FLOAT )
{
/* Pilot data for sRGB images */
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// We want to generate ints (mostly) in range of the target format which should be [0,255]
// However the range chosen here is [-test_range_ext, 255 + test_range_ext] so that
// it can test some out-of-range data points
const unsigned int test_range_ext = 16;
int formatMin = 0 - test_range_ext;
int formatMax = 255 + test_range_ext;
int pixel_value = 0;
// First, fill with arbitrary floats
for( size_t y = 0; y < imageInfo->height; y++ )
{
float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * 4;
for( size_t i = 0; i < imageInfo->width * 4; i++ )
{
pixel_value = random_in_range( formatMin, (int)formatMax, d );
inputValues[ i ] = (float)(pixel_value/255.0f);
}
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
// Piloting some debug inputs.
inputValues[ i++ ] = -0.5f;
inputValues[ i++ ] = 0.5f;
inputValues[ i++ ] = 2.0f;
inputValues[ i++ ] = 0.5f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
}
}
else
{
// First, fill with arbitrary floats
for( size_t y = 0; y < imageInfo->height; y++ )
{
float *inputValues = (float *)(char*)imageValues + imageInfo->width * y * channel_scale;
for( size_t i = 0; i < imageInfo->width * channel_scale; i++ )
inputValues[ i ] = get_random_float( -0.1f, 1.1f, d );
}
// Throw a few extra test values in there
float *inputValues = (float *)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = -0.0000000000009f;
inputValues[ i++ ] = 1.f;
inputValues[ i++ ] = -1.f;
inputValues[ i++ ] = 2.f;
// Also fill in the first few vectors with some deliberate tests to determine the rounding mode
// is correct
if( imageInfo->width > 12 )
{
float formatMax = (float)get_format_max_int( imageInfo->format );
inputValues[ i++ ] = 4.0f / formatMax;
inputValues[ i++ ] = 4.3f / formatMax;
inputValues[ i++ ] = 4.5f / formatMax;
inputValues[ i++ ] = 4.7f / formatMax;
inputValues[ i++ ] = 5.0f / formatMax;
inputValues[ i++ ] = 5.3f / formatMax;
inputValues[ i++ ] = 5.5f / formatMax;
inputValues[ i++ ] = 5.7f / formatMax;
verifyRounding = true;
}
}
}
else if( inputType == kUInt )
{
unsigned int *inputValues = (unsigned int*)(char*)imageValues;
size_t i = 0;
inputValues[ i++ ] = 0;
inputValues[ i++ ] = 65535;
inputValues[ i++ ] = 7271820;
inputValues[ i++ ] = 0;
}
}
// Construct testing sources
clProtectedImage protImage;
clMemWrapper unprotImage;
cl_mem image;
cl_mem imageBuffer;
if( gMemFlagsToUse == CL_MEM_USE_HOST_PTR )
{
if (gTestImage2DFromBuffer)
{
imageBuffer = clCreateBuffer( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR,
imageInfo->rowPitch * imageInfo->height, maxImageUseHostPtrBackingStore, &error);
test_error( error, "Unable to create buffer" );
unprotImage = create_image_2d_buffer( context, mem_flag_types[mem_flag_index], imageInfo->format,
imageInfo->width, imageInfo->height, imageInfo->rowPitch,
imageBuffer, &error );
}
else
{
// clProtectedImage uses USE_HOST_PTR, so just rely on that for the testing (via Ian)
// Do not use protected images for max image size test since it rounds the row size to a page size
if (gTestMaxImages) {
create_random_image_data( inputType, imageInfo, maxImageUseHostPtrBackingStore, d );
unprotImage = create_image_2d( context, mem_flag_types[mem_flag_index] | CL_MEM_USE_HOST_PTR, imageInfo->format,
imageInfo->width, imageInfo->height, 0,
maxImageUseHostPtrBackingStore, &error );
} else {
error = protImage.Create( context, mem_flag_types[mem_flag_index], imageInfo->format, imageInfo->width, imageInfo->height );
}
}
if( error != CL_SUCCESS )
{
if (gTestImage2DFromBuffer) {
clReleaseMemObject(imageBuffer);
if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) {
log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" );
return 0;
}
}
log_error( "ERROR: Unable to create 2D image of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->height,
imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
if (gTestMaxImages || gTestImage2DFromBuffer)
image = (cl_mem)unprotImage;
else
image = (cl_mem)protImage;
}
else // Either CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR or none
{
if( gTestMipmaps )
{
cl_image_desc image_desc = {0};
image_desc.image_type = imageInfo->type;
image_desc.num_mip_levels = imageInfo->num_mip_levels;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
unprotImage = clCreateImage( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ),
imageInfo->format, &image_desc, NULL, &error);
if( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create %d level 2D image of size %ld x %ld (%s, %s)\n", imageInfo->num_mip_levels, imageInfo->width, imageInfo->height,
IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
}
else if (gTestImage2DFromBuffer)
{
generate_random_image_data( imageInfo, imageBufferValues, d );
imageBuffer = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR,
imageInfo->rowPitch * imageInfo->height, imageBufferValues, &error);
test_error( error, "Unable to create buffer" );
unprotImage = create_image_2d_buffer( context, mem_flag_types[mem_flag_index], imageInfo->format,
imageInfo->width, imageInfo->height, imageInfo->rowPitch,
imageBuffer, &error );
}
else
{
// Note: if ALLOC_HOST_PTR is used, the driver allocates memory that can be accessed by the host, but otherwise
// it works just as if no flag is specified, so we just do the same thing either way
// Note: if the flags is really CL_MEM_COPY_HOST_PTR, we want to remove it, because we don't want to copy any incoming data
unprotImage = create_image_2d( context, mem_flag_types[mem_flag_index] | ( gMemFlagsToUse & ~(CL_MEM_COPY_HOST_PTR) ), imageInfo->format,
imageInfo->width, imageInfo->height, 0,
imageValues, &error );
}
if( error != CL_SUCCESS )
{
if (gTestImage2DFromBuffer) {
clReleaseMemObject(imageBuffer);
if (error == CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) {
log_info( "Format not supported for cl_khr_image2d_from_buffer skipping...\n" );
return 0;
}
}
log_error( "ERROR: Unable to create 2D image of size %ld x %ld pitch %ld (%s, %s)\n", imageInfo->width, imageInfo->height,
imageInfo->rowPitch, IGetErrorString( error ), mem_flag_names[mem_flag_index] );
return error;
}
image = unprotImage;
}
error = clSetKernelArg( kernel, 1, sizeof( cl_mem ), &image );
test_error( error, "Unable to set kernel arguments" );
size_t width_lod = imageInfo->width, height_lod = imageInfo->height, nextLevelOffset = 0;
size_t origin[ 3 ] = { 0, 0, 0 };
size_t region[ 3 ] = { imageInfo->width, imageInfo->height, 1 };
size_t resultSize;
int num_lod_loops = (gTestMipmaps)? imageInfo->num_mip_levels : 1;
for( int lod = 0; lod < num_lod_loops; lod++)
{
if(gTestMipmaps)
{
error = clSetKernelArg( kernel, 2, sizeof( int ), &lod );
}
// Run the kernel
threads[0] = (size_t)width_lod;
threads[1] = (size_t)height_lod;
clMemWrapper inputStream;
char *imagePtrOffset = imageValues + nextLevelOffset;
inputStream = clCreateBuffer( context, (cl_mem_flags)( CL_MEM_COPY_HOST_PTR ),
get_explicit_type_size( inputType ) * channel_scale * width_lod * height_lod, imagePtrOffset, &error );
test_error( error, "Unable to create input buffer" );
// Set arguments
error = clSetKernelArg( kernel, 0, sizeof( cl_mem ), &inputStream );
test_error( error, "Unable to set kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
// Get results
if( gTestMipmaps )
resultSize = width_lod * height_lod * get_pixel_size(imageInfo->format);
else
resultSize = imageInfo->rowPitch * imageInfo->height;
clProtectedArray PA(resultSize);
char *resultValues = (char *)((void *)PA);
if( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( resultSize / 1024 ) );
origin[2] = lod;
region[0] = width_lod;
region[1] = height_lod;
error = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, gEnablePitch ? imageInfo->rowPitch : 0, 0, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if( gDebugTrace )
log_info( " results read\n" );
// Validate results element by element
char *imagePtr = (char*)imageValues + nextLevelOffset;
int numTries = 5;
for( size_t y = 0, i = 0; y < height_lod; y++ )
{
char *resultPtr;
if( gTestMipmaps )
resultPtr = (char *)resultValues + y * width_lod * pixelSize;
else
resultPtr = (char*)resultValues + y * imageInfo->rowPitch;
for( size_t x = 0; x < width_lod; x++, i++ )
{
char resultBuffer[ 16 ]; // Largest format would be 4 channels * 4 bytes (32 bits) each
// Convert this pixel
if( inputType == kFloat )
pack_image_pixel( (float *)imagePtr, imageInfo->format, resultBuffer );
else if( inputType == kInt )
pack_image_pixel( (int *)imagePtr, imageInfo->format, resultBuffer );
else // if( inputType == kUInt )
pack_image_pixel( (unsigned int *)imagePtr, imageInfo->format, resultBuffer );
// Compare against the results
if(is_sRGBA_order(imageInfo->format->image_channel_order))
{
// Compare sRGB-mapped values
cl_float expected[4] = {0};
cl_float* input_values = (float*)imagePtr;
cl_uchar *actual = (cl_uchar*)resultPtr;
float max_err = MAX_lRGB_TO_sRGB_CONVERSION_ERROR;
float err[4] = {0.0f};
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if(j < 3)
{
expected[j] = sRGBmap(input_values[j]);
}
else // there is no sRGB conversion for alpha component if it exists
{
expected[j] = NORMALIZE(input_values[j], 255.0f);
}
err[j] = fabsf( expected[ j ] - actual[ j ] );
}
if ((err[0] > max_err) ||
(err[1] > max_err) ||
(err[2] > max_err) ||
(err[3] > 0)) // there is no conversion for alpha so the error should be zero
{
log_error( " Error: %g %g %g %g\n", err[0], err[1], err[2], err[3]);
log_error( " Input: %g %g %g %g\n", *((float *)imagePtr), *((float *)imagePtr + 1), *((float *)imagePtr + 2), *((float *)imagePtr + 3));
log_error( " Expected: %g %g %g %g\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Actual: %d %d %d %d\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_FLOAT )
{
// Compare floats
float *expected = (float *)resultBuffer;
float *actual = (float *)resultPtr;
float err = 0.f;
for( unsigned int j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
err += ( expected[ j ] != 0 ) ? fabsf( ( expected[ j ] - actual[ j ] ) / expected[ j ] ) : fabsf( expected[ j ] - actual[ j ] );
err /= (float)get_format_channel_count( imageInfo->format );
if( err > MAX_ERR )
{
unsigned int *e = (unsigned int *)expected;
unsigned int *a = (unsigned int *)actual;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
log_error( " Error: %g\n", err );
log_error( " Expected: %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
log_error( " Expected: %08x %08x %08x %08x\n", e[ 0 ], e[ 1 ], e[ 2 ], e[ 3 ] );
log_error( " Actual: %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
log_error( " Actual: %08x %08x %08x %08x\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ] );
totalErrors++;
if( ( --numTries ) == 0 )
return 1;
}
}
else if( imageInfo->format->image_channel_data_type == CL_HALF_FLOAT )
{
// Compare half floats
if( memcmp( resultBuffer, resultPtr, 2 * get_format_channel_count( imageInfo->format ) ) != 0 )
{
cl_ushort *e = (cl_ushort *)resultBuffer;
cl_ushort *a = (cl_ushort *)resultPtr;
int err_cnt = 0;
//Fix up cases where we have NaNs
for( size_t j = 0; j < get_format_channel_count( imageInfo->format ); j++ )
{
if( is_half_nan( e[j] ) && is_half_nan(a[j]) )
continue;
if( e[j] != a[j] )
err_cnt++;
}
if( err_cnt )
{
totalErrors++;
log_error( "ERROR: Sample %ld (%ld,%ld) did not validate! (%s)\n", i, x, y, mem_flag_names[mem_flag_index] );
log_error( " Expected: 0x%04x 0x%04x 0x%04x 0x%04x\n", e[0], e[1], e[2], e[3] );
log_error( " Actual: 0x%04x 0x%04x 0x%04x 0x%04x\n", a[0], a[1], a[2], a[3] );
if( inputType == kFloat )
{
float *p = (float *)(char *)imagePtr;
log_error( " Source: %a %a %a %a\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
log_error( " : %12.24f %12.24f %12.24f %12.24f\n", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
}
if( ( --numTries ) == 0 )
return 1;
}
}
}
else
{
// Exact result passes every time
if( memcmp( resultBuffer, resultPtr, get_pixel_size( imageInfo->format ) ) != 0 )
{
// result is inexact. Calculate error
int failure = 1;
float errors[4] = {NAN, NAN, NAN, NAN};
pack_image_pixel_error( (float *)imagePtr, imageInfo->format, resultBuffer, errors );
// We are allowed 0.6 absolute error vs. infinitely precise for some normalized formats
if( 0 == forceCorrectlyRoundedWrites &&
(
imageInfo->format->image_channel_data_type == CL_UNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT_101010 ||
imageInfo->format->image_channel_data_type == CL_UNORM_INT16 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT8 ||
imageInfo->format->image_channel_data_type == CL_SNORM_INT16
))
{
if( ! (fabsf( errors[0] ) > 0.6f) && ! (fabsf( errors[1] ) > 0.6f) &&
! (fabsf( errors[2] ) > 0.6f) && ! (fabsf( errors[3] ) > 0.6f) )
failure = 0;
}
if( failure )
{
totalErrors++;
// Is it our special rounding test?
if( verifyRounding && i >= 1 && i <= 2 )
{
// Try to guess what the rounding mode of the device really is based on what it returned
const char *deviceRounding = "unknown";
unsigned int deviceResults[8];
read_image_pixel<unsigned int>( resultPtr, imageInfo, 0, 0, 0, deviceResults, lod );
read_image_pixel<unsigned int>( resultPtr, imageInfo, 1, 0, 0, &deviceResults[ 4 ], lod );
if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 4 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 5 && deviceResults[ 7 ] == 5 )
deviceRounding = "truncate";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 5 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to nearest";
else if( deviceResults[ 0 ] == 4 && deviceResults[ 1 ] == 4 && deviceResults[ 2 ] == 4 && deviceResults[ 3 ] == 5 &&
deviceResults[ 4 ] == 5 && deviceResults[ 5 ] == 5 && deviceResults[ 6 ] == 6 && deviceResults[ 7 ] == 6 )
deviceRounding = "round to even";
log_error( "ERROR: Rounding mode sample (%ld) did not validate, probably due to the device's rounding mode being wrong (%s)\n", i, mem_flag_names[mem_flag_index] );
log_error( " Actual values rounded by device: %x %x %x %x %x %x %x %x\n", deviceResults[ 0 ], deviceResults[ 1 ], deviceResults[ 2 ], deviceResults[ 3 ],
deviceResults[ 4 ], deviceResults[ 5 ], deviceResults[ 6 ], deviceResults[ 7 ] );
log_error( " Rounding mode of device appears to be %s\n", deviceRounding );
return 1;
}
log_error( "ERROR: Sample %d (%d,%d) did not validate!\n", (int)i, (int)x, (int)y );
switch(imageInfo->format->image_channel_data_type)
{
case CL_UNORM_INT8:
case CL_SNORM_INT8:
case CL_UNSIGNED_INT8:
case CL_SIGNED_INT8:
case CL_UNORM_INT_101010:
log_error( " Expected: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultBuffer)[0], ((cl_uchar*)resultBuffer)[1], ((cl_uchar*)resultBuffer)[2], ((cl_uchar*)resultBuffer)[3] );
log_error( " Actual: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", ((cl_uchar*)resultPtr)[0], ((cl_uchar*)resultPtr)[1], ((cl_uchar*)resultPtr)[2], ((cl_uchar*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNORM_INT16:
case CL_SNORM_INT16:
case CL_UNSIGNED_INT16:
case CL_SIGNED_INT16:
#ifdef CL_SFIXED14_APPLE
case CL_SFIXED14_APPLE:
#endif
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Error: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_HALF_FLOAT:
log_error( " Expected: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultBuffer)[0], ((cl_ushort*)resultBuffer)[1], ((cl_ushort*)resultBuffer)[2], ((cl_ushort*)resultBuffer)[3] );
log_error( " Actual: 0x%4.4x 0x%4.4x 0x%4.4x 0x%4.4x\n", ((cl_ushort*)resultPtr)[0], ((cl_ushort*)resultPtr)[1], ((cl_ushort*)resultPtr)[2], ((cl_ushort*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
case CL_UNSIGNED_INT32:
case CL_SIGNED_INT32:
log_error( " Expected: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultBuffer)[0], ((cl_uint*)resultBuffer)[1], ((cl_uint*)resultBuffer)[2], ((cl_uint*)resultBuffer)[3] );
log_error( " Actual: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", ((cl_uint*)resultPtr)[0], ((cl_uint*)resultPtr)[1], ((cl_uint*)resultPtr)[2], ((cl_uint*)resultPtr)[3] );
break;
case CL_FLOAT:
log_error( " Expected: %a %a %a %a\n", ((cl_float*)resultBuffer)[0], ((cl_float*)resultBuffer)[1], ((cl_float*)resultBuffer)[2], ((cl_float*)resultBuffer)[3] );
log_error( " Actual: %a %a %a %a\n", ((cl_float*)resultPtr)[0], ((cl_float*)resultPtr)[1], ((cl_float*)resultPtr)[2], ((cl_float*)resultPtr)[3] );
log_error( " Ulps: %f %f %f %f\n", errors[0], errors[1], errors[2], errors[3] );
break;
}
float *v = (float *)(char *)imagePtr;
log_error( " src: %g %g %g %g\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " : %a %a %a %a\n", v[ 0 ], v[ 1], v[ 2 ], v[ 3 ] );
log_error( " src: %12.24f %12.24f %12.24f %12.24f\n", v[0 ], v[ 1], v[ 2 ], v[ 3 ] );
if( ( --numTries ) == 0 )
return 1;
}
}
}
imagePtr += get_explicit_type_size( inputType ) * channel_scale;
resultPtr += get_pixel_size( imageInfo->format );
}
}
{
nextLevelOffset += width_lod * height_lod * get_pixel_size( imageInfo->format);
width_lod = (width_lod >> 1) ?(width_lod >> 1) : 1;
height_lod = (height_lod >> 1) ?(height_lod >> 1) : 1;
}
}
if (gTestImage2DFromBuffer) clReleaseMemObject(imageBuffer);
}
// All done!
return totalErrors;
}
int test_write_image_set( cl_device_id device, cl_image_format *format, ExplicitType inputType, MTdata d )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
clProgramWrapper program;
clKernelWrapper kernel;
const char *KernelSourcePattern = NULL;
int error;
if (gTestImage2DFromBuffer)
{
if (format->image_channel_order == CL_RGB || format->image_channel_order == CL_RGBx)
{
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_SIGNED_INT8:
case CL_SIGNED_INT16:
case CL_SIGNED_INT32:
case CL_UNSIGNED_INT8:
case CL_UNSIGNED_INT16:
case CL_UNSIGNED_INT32:
log_info( "Skipping image format: %s %s\n", GetChannelOrderName( format->image_channel_order ),
GetChannelTypeName( format->image_channel_data_type ));
return 0;
default:
break;
}
}
}
// Get our operating parameters
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0x0 };
imageInfo.format = format;
imageInfo.slicePitch = imageInfo.arraySize = imageInfo.depth = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if( inputType == kInt )
readFormat = "i";
else if( inputType == kUInt )
readFormat = "ui";
else // kFloat
readFormat = "f";
if(gtestTypesToRun & kWriteTests)
{
KernelSourcePattern = writeKernelSourcePattern;
}
else
{
KernelSourcePattern = read_writeKernelSourcePattern;
}
// Construct the source
sprintf( programSrc,
KernelSourcePattern,
get_explicit_type_name( inputType ),
(format->image_channel_order == CL_DEPTH) ? "" : "4",
(format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t",
gTestMipmaps ? ", int lod" : "",
gTestMipmaps ? offset2DLodKernelSource : offset2DKernelSource,
readFormat,
gTestMipmaps ? ", lod" : "" );
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if( gTestSmallImages )
{
for( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
for( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
if( gTestMipmaps )
imageInfo.num_mip_levels = (size_t) random_in_range(1, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d);
if( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
}
else if( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format, CL_TRUE);
for( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
if( gTestMipmaps )
imageInfo.num_mip_levels = (size_t) random_in_range(1, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0)-1, d);
log_info("Testing %d x %d\n", (int)imageInfo.width, (int)imageInfo.height);
int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
else if( gTestRounding )
{
size_t typeRange = 1 << ( get_format_type_size( imageInfo.format ) * 8 );
imageInfo.height = typeRange / 256;
imageInfo.width = (size_t)( typeRange / (cl_ulong)imageInfo.height );
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
else
{
cl_uint imagePitchAlign = 0;
if (gTestImage2DFromBuffer)
{
#if defined(CL_DEVICE_IMAGE_PITCH_ALIGNMENT)
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, sizeof( cl_uint ), &imagePitchAlign, NULL );
if (!imagePitchAlign)
imagePitchAlign = 1;
#endif
test_error( error, "Unable to get CL_DEVICE_IMAGE_PITCH_ALIGNMENT from device" );
}
for( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, d );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, d );
if(gTestMipmaps)
{
imageInfo.num_mip_levels = (size_t) random_in_range(1, compute_max_mip_levels(imageInfo.width, imageInfo.height, 0) - 1, d);
size = 4 * compute_mipmapped_image_size(imageInfo);
}
else
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
if( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, d );
imageInfo.rowPitch += extraWidth * get_pixel_size( imageInfo.format );
}
// if we are creating a 2D image from a buffer, make sure that the rowpitch is aligned to CL_DEVICE_IMAGE_PITCH_ALIGNMENT_APPLE
if (gTestImage2DFromBuffer)
{
size_t pitch = imagePitchAlign * get_pixel_size( imageInfo.format );
imageInfo.rowPitch = ((imageInfo.rowPitch + pitch - 1) / pitch ) * pitch;
}
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4;
}
} while( size > maxAllocSize || ( size * 3 ) > memSize );
if( gDebugTrace )
log_info( " at size %d,%d (pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
int retCode = test_write_image( device, context, queue, kernel, &imageInfo, inputType, d );
if( retCode )
return retCode;
}
}
return 0;
}
int test_write_image_formats( cl_device_id device, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
image_sampler_data *imageSampler, ExplicitType inputType, cl_mem_object_type imageType )
{
if( imageSampler->filter_mode == CL_FILTER_LINEAR )
// No need to run for linear filters
return 0;
int ret = 0;
log_info( "write_image (%s input) *****************************\n", get_explicit_type_name( inputType ) );
RandomSeed seed( gRandomSeed );
for( unsigned int i = 0; i < numFormats; i++ )
{
cl_image_format &imageFormat = formatList[ i ];
if( filterFlags[ i ] )
continue;
if (is_sRGBA_order(imageFormat.image_channel_order))
{
if( !is_extension_available( device, "cl_khr_srgb_image_writes" ))
{
log_missing_feature( "-----------------------------------------------------\n" );
log_missing_feature( "WARNING!!! sRGB formats are shown in the supported write-format list.\n");
log_missing_feature( "However the extension cl_khr_srgb_image_writes is not available.\n");
log_missing_feature( "Please make sure the extension is officially supported by the device .\n");
log_missing_feature( "-----------------------------------------------------\n\n" );
continue;
}
}
gTestCount++;
print_write_header( &imageFormat, false );
int retCode;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
retCode = test_write_image_1D_set( device, &imageFormat, inputType, seed );
break;
case CL_MEM_OBJECT_IMAGE2D:
retCode = test_write_image_set( device, &imageFormat, inputType, seed );
break;
case CL_MEM_OBJECT_IMAGE3D:
retCode = test_write_image_3D_set( device, &imageFormat, inputType, seed );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
retCode = test_write_image_1D_array_set( device, &imageFormat, inputType, seed );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
retCode = test_write_image_2D_array_set( device, &imageFormat, inputType, seed );
break;
}
if( retCode != 0 )
{
gTestFailure++;
log_error( "FAILED: " );
print_write_header( &imageFormat, true );
log_info( "\n" );
}
ret += retCode;
}
return ret;
}

View File

@@ -0,0 +1,23 @@
set(MODULE_NAME SAMPLERLESS_READS)
set(${MODULE_NAME}_SOURCES
main.cpp
test_iterations.cpp
test_loops.cpp
test_read_1D.cpp
test_read_3D.cpp
test_read_1D_buffer.cpp
test_read_1D_array.cpp
test_read_2D_array.cpp
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/threadTesting.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/imageHelpers.cpp
../../../test_common/harness/mt19937.c
../../../test_common/harness/conversions.c
../../../test_common/harness/testHarness.c
../../../test_common/harness/typeWrappers.cpp
../../../test_common/harness/msvc9.c
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,19 @@
project
: requirements
# <toolset>gcc:<cflags>-xc++
# <toolset>msvc:<cflags>"/TP"
;
exe test_samplerless_reads
: main.cpp
test_iterations.cpp
test_loops.cpp
test_read_3D.cpp
;
install dist
: test_samplerless_reads
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/images/samplerlessReads
<variant>release:<location>$(DIST)/release/tests/test_conformance/images/samplerlessReads
;

View File

@@ -0,0 +1,52 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.cpp \
test_iterations.cpp \
test_loops.cpp \
test_read_1D.cpp \
test_read_1D_buffer.cpp \
test_read_1D_array.cpp \
test_read_2D_array.cpp \
test_read_3D.cpp \
../../../test_common/harness/errorHelpers.c \
../../../test_common/harness/threadTesting.c \
../../../test_common/harness/kernelHelpers.c \
../../../test_common/harness/imageHelpers.cpp \
../../../test_common/harness/conversions.c \
../../../test_common/harness/testHarness.c \
../../../test_common/harness/mt19937.c \
../../../test_common/harness/typeWrappers.cpp
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK =
HEADERS =
TARGET = test_samplerless_reads
INCLUDE = -I../../test_common/harness
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32 -Os
CC = c++
CXX = 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,317 @@
//
// 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(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "../testBase.h"
#include "../../../test_common/harness/fpcontrol.h"
#if defined(__PPC__)
// Global varaiable used to hold the FPU control register state. The FPSCR register can not
// be used because not all Power implementations retain or observed the NI (non-IEEE
// mode) bit.
__thread fpu_control_t fpu_control = 0;
#endif
bool gTestReadWrite = false;
bool gDebugTrace = false;
bool gTestMaxImages = false, gTestSmallImages = false, gTestRounding = false;
int gTypesToTest = 0;
cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
cl_channel_order gChannelOrderToUse = (cl_channel_order)-1;
bool gEnablePitch = false;
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
cl_command_queue queue;
cl_context context;
static cl_device_id device;
#define MAX_ALLOWED_STD_DEVIATION_IN_MB 8.0
static void printUsage( const char *execName );
extern int test_image_set( cl_device_id device, cl_mem_object_type imageType );
int test_1D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D ) +
test_image_set( device, CL_MEM_OBJECT_IMAGE1D_BUFFER );
}
int test_2D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D );
}
int test_3D(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE3D );
}
int test_1DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE1D_ARRAY );
}
int test_2DArray(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_image_set( device, CL_MEM_OBJECT_IMAGE2D_ARRAY );
}
basefn basefn_list[] = {
test_1D,
test_2D,
test_3D,
test_1DArray,
test_2DArray,
};
const char *basefn_names[] = {
"1D",
"2D",
"3D",
"1DArray",
"2DArray",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int main(int argc, const char *argv[])
{
cl_platform_id platform;
cl_channel_type chanType;
cl_channel_order chanOrder;
bool randomize = false;
test_start();
//Check CL_DEVICE_TYPE environment variable
checkDeviceTypeOverride( &gDeviceType );
const char ** argList = (const char **)calloc( argc, sizeof( char*) );
if( NULL == argList )
{
log_error( "Failed to allocate memory for argList array.\n" );
return 1;
}
argList[0] = argv[0];
size_t argCount = 1;
// Parse arguments
for ( int i = 1; i < argc; i++ )
{
if ( strcmp( argv[i], "cpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_CPU;
else if ( strcmp( argv[i], "gpu" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_GPU;
else if ( strcmp( argv[i], "accelerator" ) == 0 || strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
else if ( strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
gDeviceType = CL_DEVICE_TYPE_DEFAULT;
else if ( strcmp( argv[i], "debug_trace" ) == 0 )
gDebugTrace = true;
else if ( strcmp( argv[i], "read_write" ) == 0 )
gTestReadWrite = true;
else if ( strcmp( argv[i], "small_images" ) == 0 )
gTestSmallImages = true;
else if ( strcmp( argv[i], "max_images" ) == 0 )
gTestMaxImages = true;
else if ( strcmp( argv[i], "use_pitches" ) == 0 )
gEnablePitch = true;
else if ( strcmp( argv[i], "int" ) == 0 )
gTypesToTest |= kTestInt;
else if ( strcmp( argv[i], "uint" ) == 0 )
gTypesToTest |= kTestUInt;
else if ( strcmp( argv[i], "float" ) == 0 )
gTypesToTest |= kTestFloat;
else if ( strcmp( argv[i], "randomize" ) == 0 )
randomize = true;
else if ( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
{
printUsage( argv[ 0 ] );
return -1;
}
else if ( ( chanType = get_channel_type_from_name( argv[i] ) ) != (cl_channel_type)-1 )
gChannelTypeToUse = chanType;
else if ( ( chanOrder = get_channel_order_from_name( argv[i] ) ) != (cl_channel_order)-1 )
gChannelOrderToUse = chanOrder;
else
{
argList[argCount] = argv[i];
argCount++;
}
}
if ( gTypesToTest == 0 )
gTypesToTest = kTestAllTypes;
// Seed the random # generators
if ( randomize )
{
gRandomSeed = (cl_uint) time( NULL );
gReSeed = 1;
log_info( "Random seed: %u.\n", gRandomSeed );
}
int error;
// Get our platform
error = clGetPlatformIDs(1, &platform, NULL);
if ( error )
{
print_error( error, "Unable to get platform" );
test_finish();
return -1;
}
// Get our device
error = clGetDeviceIDs(platform, gDeviceType, 1, &device, NULL );
if ( error )
{
print_error( error, "Unable to get specified device" );
test_finish();
return -1;
}
// Get the device type so we know if it is a GPU even if default is passed in.
error = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(gDeviceType), &gDeviceType, NULL);
if ( error )
{
print_error( error, "Unable to get device type" );
test_finish();
return -1;
}
if ( printDeviceHeader( device ) != CL_SUCCESS )
{
test_finish();
return -1;
}
// Check for image support
if (checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED) {
log_info("Device does not support images. Skipping test.\n");
test_finish();
return 0;
}
// Create a context to test with
context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
if ( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing context" );
test_finish();
return -1;
}
// Create a queue against the context
queue = clCreateCommandQueueWithProperties( context, device, 0, &error );
if ( error != CL_SUCCESS )
{
print_error( error, "Unable to create testing command queue" );
test_finish();
return -1;
}
if ( gTestSmallImages )
log_info( "Note: Using small test images\n" );
// On most platforms which support denorm, default is FTZ off. However,
// on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm.
// This creates issues in result verification. Since spec allows the implementation to either flush or
// not flush denorms to zero, an implementation may choose not to flush i.e. return denorm result whereas
// reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side
// where reference is being computed to make sure we get non-flushed reference result. If implementation
// returns flushed result, we correctly take care of that in verification code.
FPU_mode_type oldMode;
DisableFTZ(&oldMode);
int ret = parseAndCallCommandLineTests( argCount, argList, NULL, num_fns, basefn_list, basefn_names, true, 0, 0 );
// Restore FP state before leaving
RestoreFPState(&oldMode);
error = clFinish(queue);
if (error)
print_error(error, "clFinish failed.");
clReleaseContext(context);
clReleaseCommandQueue(queue);
if (gTestFailure == 0) {
if (gTestCount > 1)
log_info("PASSED %d of %d sub-tests.\n", gTestCount, gTestCount);
else
log_info("PASSED sub-test.\n");
}
else if (gTestFailure > 0) {
if (gTestCount > 1)
log_error("FAILED %d of %d sub-tests.\n", gTestFailure, gTestCount);
else
log_error("FAILED sub-test.\n");
}
// Clean up
free(argList);
test_finish();
return ret;
}
static void printUsage( const char *execName )
{
const char *p = strrchr( execName, '/' );
if ( p != NULL )
execName = p + 1;
log_info( "Usage: %s [options] [test_names]\n", execName );
log_info( "Options:\n" );
log_info( "\n" );
log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" );
log_info( "\t\tint - Test integer I/O (read_imagei)\n" );
log_info( "\t\tuint - Test unsigned integer I/O (read_imageui)\n" );
log_info( "\t\tfloat - Test float I/O (read_imagef)\n" );
log_info( "\n" );
log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" );
log_info( "\n" );
log_info( "\tThe following modify the types of images tested:\n" );
log_info( "\t\read_write - Runs the tests with read_write images which allow a kernel do both read and write to the same image \n" );
log_info( "\t\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
log_info( "\t\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
log_info( "\n" );
log_info( "\tdebug_trace - Enables additional debug info logging\n" );
log_info( "\tuse_pitches - Enables row and slice pitches\n" );
log_info( "\n" );
log_info( "Test names:\n" );
for( int i = 0; i < num_fns; i++ )
{
log_info( "\t%s\n", basefn_names[i] );
}
}

View File

@@ -0,0 +1,337 @@
//
// 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 <float.h>
#if defined( __APPLE__ )
#include <signal.h>
#include <sys/signal.h>
#include <setjmp.h>
#endif
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_device_type gDeviceType;
extern bool gTestReadWrite;
#define MAX_TRIES 1
#define MAX_CLAMPED 1
const char *read2DKernelSourcePattern =
"__kernel void sample_kernel( read_only %s input, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
" int offset = tidY*get_image_width(input) + tidX;\n"
" int2 coords = (int2)(tidX, tidY);\n"
" %s clr = read_image%s( input, coords );\n"
" int4 test = (clr != read_image%s( input, sampler, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
const char *read_write2DKernelSourcePattern =
"__kernel void sample_kernel( read_only %s read_only_image, read_write %s read_write_image, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
" int offset = tidY*get_image_width(read_only_image) + tidX;\n"
" int2 coords = (int2)(tidX, tidY);\n"
" %s clr = read_image%s( read_only_image, sampler, coords );\n"
" write_image%s(read_write_image, coords, clr);\n"
" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n"
" int4 test = (clr != read_image%s( read_write_image, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
int test_read_image_2D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, image_sampler_data *imageSampler,
ExplicitType outputType, MTdata d )
{
int error;
size_t threads[2];
cl_sampler actualSampler;
// generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if ( gDebugTrace )
log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height );
// Construct testing sources
cl_mem read_only_image, read_write_image;
cl_image_desc image_desc;
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE2D;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 );
image_desc.num_mip_levels = 0;
read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format,
&image_desc, imageValues, &error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 2D read_only image of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
if(gTestReadWrite)
{
read_write_image = clCreateImage(context,
CL_MEM_READ_WRITE,
imageInfo->format,
&image_desc,
NULL,
&error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create 2D read_write image of size %d x %d pitch %d (%s)\n",
(int)imageInfo->width,
(int)imageInfo->height,
(int)imageInfo->rowPitch,
IGetErrorString( error ) );
return error;
}
}
if ( gDebugTrace )
log_info( " - Creating kernel arguments...\n" );
// Create sampler to use
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 };
actualSampler = clCreateSamplerWithProperties( context, properties, &error );
test_error( error, "Unable to create image sampler" );
// Create results buffer
cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->height * sizeof(cl_int), NULL, &error);
test_error( error, "Unable to create results buffer" );
size_t resultValuesSize = imageInfo->width * imageInfo->height * sizeof(cl_int);
BufferOwningPtr<int> resultValues(malloc( resultValuesSize ));
memset( resultValues, 0xff, resultValuesSize );
clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
// Set arguments
int idx = 0;
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image );
test_error( error, "Unable to set kernel arguments" );
if(gTestReadWrite)
{
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image );
test_error( error, "Unable to set kernel arguments" );
}
error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results );
test_error( error, "Unable to set kernel arguments" );
// Run the kernel
threads[0] = (size_t)imageInfo->width;
threads[1] = (size_t)imageInfo->height;
error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
if ( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * imageInfo->height * sizeof(cl_int) / 1024 ) );
error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if ( gDebugTrace )
log_info( " results read\n" );
// Check for non-zero comps
bool allZeroes = true;
for ( size_t ic = 0; ic < imageInfo->width * imageInfo->height; ++ic )
{
if ( resultValues[ic] ) {
allZeroes = false;
break;
}
}
if ( !allZeroes )
{
log_error( " Sampler-less reads differ from reads with sampler.\n" );
return -1;
}
clReleaseSampler(actualSampler);
clReleaseMemObject(results);
clReleaseMemObject(read_only_image);
if(gTestReadWrite)
{
clReleaseMemObject(read_write_image);
}
return 0;
}
int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
ExplicitType outputType )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
const char *dataType;
clProgramWrapper program;
clKernelWrapper kernel;
RandomSeed seed( gRandomSeed );
int error;
// Get our operating params
size_t maxWidth, maxHeight;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
size_t pixelSize;
imageInfo.format = format;
imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if ( outputType == kInt )
{
readFormat = "i";
dataType = "int4";
}
else if ( outputType == kUInt )
{
readFormat = "ui";
dataType = "uint4";
}
else // kFloat
{
readFormat = "f";
dataType = (format->image_channel_order == CL_DEPTH) ? "float" : "float4";
}
if(gTestReadWrite)
{
sprintf(programSrc,
read_write2DKernelSourcePattern,
(format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t",
(format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t",
dataType,
readFormat,
readFormat,
readFormat);
}
else
{
sprintf(programSrc,
read2DKernelSourcePattern,
(format->image_channel_order == CL_DEPTH) ? "image2d_depth_t" : "image2d_t",
dataType,
readFormat,
readFormat );
}
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.height );
int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info("Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ]);
if ( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ] );
int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
if ( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
}
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.height * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxHeight );
int retCode = test_read_image_2D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,305 @@
//
// 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"
extern cl_context context;
extern int gTypesToTest;
extern cl_channel_type gChannelTypeToUse;
extern cl_channel_order gChannelOrderToUse;
extern bool gDebugTrace;
extern bool gTestReadWrite;
extern int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_1D_buffer( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_2D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
static const char *str_1d_image = "1D";
static const char *str_2d_image = "2D";
static const char *str_3d_image = "3D";
static const char *str_1d_image_array = "1D array";
static const char *str_2d_image_array = "2D array";
static const char *str_1d_image_buffer = "1D image buffer";
static const char *convert_image_type_to_string(cl_mem_object_type imageType)
{
const char *p;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
p = str_1d_image;
break;
case CL_MEM_OBJECT_IMAGE2D:
p = str_2d_image;
break;
case CL_MEM_OBJECT_IMAGE3D:
p = str_3d_image;
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
p = str_1d_image_array;
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
p = str_2d_image_array;
break;
case CL_MEM_OBJECT_IMAGE1D_BUFFER:
p = str_1d_image_buffer;
}
return p;
}
int filter_formats( cl_image_format *formatList, bool *filterFlags, unsigned int formatCount, cl_channel_type *channelDataTypesToFilter )
{
int numSupported = 0;
for ( unsigned int j = 0; j < formatCount; j++ )
{
// If this format has been previously filtered, remove the filter
if ( filterFlags[ j ] )
filterFlags[ j ] = false;
// Have we already discarded the channel type via the command line?
if ( gChannelTypeToUse != (cl_channel_type)-1 && gChannelTypeToUse != formatList[ j ].image_channel_data_type )
{
filterFlags[ j ] = true;
continue;
}
// Have we already discarded the channel order via the command line?
if ( gChannelOrderToUse != (cl_channel_order)-1 && gChannelOrderToUse != formatList[ j ].image_channel_order )
{
filterFlags[ j ] = true;
continue;
}
// Is given format standard channel order and type given by spec. We don't want to test it if this is vendor extension
if( !IsChannelOrderSupported( formatList[ j ].image_channel_order ) || !IsChannelTypeSupported( formatList[ j ].image_channel_data_type ) )
{
filterFlags[ j ] = true;
continue;
}
// We don't filter by channel type
if( !channelDataTypesToFilter )
{
numSupported++;
continue;
}
// Is the format supported?
int i;
for ( i = 0; channelDataTypesToFilter[ i ] != (cl_channel_type)-1; i++ )
{
if ( formatList[ j ].image_channel_data_type == channelDataTypesToFilter[ i ] )
{
numSupported++;
break;
}
}
if ( channelDataTypesToFilter[ i ] == (cl_channel_type)-1 )
{
// Format is NOT supported, so mark it as such
filterFlags[ j ] = true;
}
}
return numSupported;
}
int get_format_list( cl_device_id device, cl_mem_object_type imageType, cl_image_format * &outFormatList, unsigned int &outFormatCount, cl_mem_flags flags )
{
int error;
cl_image_format tempList[ 128 ];
error = clGetSupportedImageFormats( context, flags,
imageType, 128, tempList, &outFormatCount );
test_error( error, "Unable to get count of supported image formats" );
outFormatList = new cl_image_format[ outFormatCount ];
error = clGetSupportedImageFormats( context, flags,
imageType, outFormatCount, outFormatList, NULL );
test_error( error, "Unable to get list of supported image formats" );
return 0;
}
int test_read_image_type( cl_device_id device, cl_image_format *format,
image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
int ret = 0;
imageSampler->addressing_mode = CL_ADDRESS_NONE;
print_read_header( format, imageSampler, false );
gTestCount++;
switch (imageType)
{
case CL_MEM_OBJECT_IMAGE1D:
ret = test_read_image_set_1D( device, format, imageSampler, outputType );
break;
case CL_MEM_OBJECT_IMAGE1D_BUFFER:
ret += test_read_image_set_1D_buffer( device, format, imageSampler, outputType );
break;
case CL_MEM_OBJECT_IMAGE2D:
ret = test_read_image_set_2D( device, format, imageSampler, outputType );
break;
case CL_MEM_OBJECT_IMAGE3D:
ret = test_read_image_set_3D( device, format, imageSampler, outputType );
break;
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
ret = test_read_image_set_1D_array( device, format, imageSampler, outputType );
break;
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
ret = test_read_image_set_2D_array( device, format, imageSampler, outputType );
break;
}
if ( ret != 0 )
{
gTestFailure++;
log_error( "FAILED: " );
print_read_header( format, imageSampler, true );
log_info( "\n" );
}
return ret;
}
int test_read_image_formats( cl_device_id device, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
int ret = 0;
imageSampler->normalized_coords = false;
log_info( "read_image (%s coords, %s results) *****************************\n",
"integer", get_explicit_type_name( outputType ) );
for ( unsigned int i = 0; i < numFormats; i++ )
{
if ( filterFlags[i] )
continue;
cl_image_format &imageFormat = formatList[ i ];
ret |= test_read_image_type( device, &imageFormat, imageSampler, outputType, imageType );
}
return ret;
}
int test_image_set( cl_device_id device, cl_mem_object_type imageType )
{
int ret = 0;
static int printedFormatList = -1;
// Grab the list of supported image formats
cl_image_format *formatList;
bool *filterFlags;
unsigned int numFormats;
// This flag is only for querying the list of supported formats
// The flag for creating image will be set explicitly in test functions
cl_mem_flags flags = (gTestReadWrite)? CL_MEM_KERNEL_READ_AND_WRITE : CL_MEM_READ_ONLY;
if ( get_format_list( device, imageType, formatList, numFormats, flags ) )
return -1;
filterFlags = new bool[ numFormats ];
if ( filterFlags == NULL )
{
log_error( "ERROR: Out of memory allocating filter flags list!\n" );
return -1;
}
memset( filterFlags, 0, sizeof( bool ) * numFormats );
// First time through, we'll go ahead and print the formats supported, regardless of type
if ( printedFormatList != (int)imageType )
{
log_info( "---- Supported %s read formats for this device ---- \n", convert_image_type_to_string(imageType) );
for ( unsigned int f = 0; f < numFormats; f++ )
log_info( " %-7s %-24s %d\n", GetChannelOrderName( formatList[ f ].image_channel_order ),
GetChannelTypeName( formatList[ f ].image_channel_data_type ),
(int)get_format_channel_count( &formatList[ f ] ) );
log_info( "------------------------------------------- \n" );
printedFormatList = imageType;
}
image_sampler_data imageSampler;
/////// float tests ///////
if ( gTypesToTest & kTestFloat )
{
cl_channel_type floatFormats[] = { CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010,
#ifdef OBSOLETE_FORAMT
CL_UNORM_SHORT_565_REV, CL_UNORM_SHORT_555_REV, CL_UNORM_INT_8888, CL_UNORM_INT_8888_REV, CL_UNORM_INT_101010_REV,
#endif
#ifdef CL_SFIXED14_APPLE
CL_SFIXED14_APPLE,
#endif
CL_UNORM_INT8, CL_SNORM_INT8,
CL_UNORM_INT16, CL_SNORM_INT16, CL_FLOAT, CL_HALF_FLOAT, (cl_channel_type)-1 };
if ( filter_formats( formatList, filterFlags, numFormats, floatFormats ) == 0 )
{
log_info( "No formats supported for float type\n" );
}
else
{
imageSampler.filter_mode = CL_FILTER_NEAREST;
ret += test_read_image_formats( device, formatList, filterFlags, numFormats, &imageSampler, kFloat, imageType );
}
}
/////// int tests ///////
if ( gTypesToTest & kTestInt )
{
cl_channel_type intFormats[] = { CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, (cl_channel_type)-1 };
if ( filter_formats( formatList, filterFlags, numFormats, intFormats ) == 0 )
{
log_info( "No formats supported for integer type\n" );
}
else
{
// Only filter mode we support on int is nearest
imageSampler.filter_mode = CL_FILTER_NEAREST;
ret += test_read_image_formats( device, formatList, filterFlags, numFormats, &imageSampler, kInt, imageType );
}
}
/////// uint tests ///////
if ( gTypesToTest & kTestUInt )
{
cl_channel_type uintFormats[] = { CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, (cl_channel_type)-1 };
if ( filter_formats( formatList, filterFlags, numFormats, uintFormats ) == 0 )
{
log_info( "No formats supported for unsigned int type\n" );
}
else
{
// Only filter mode we support on uint is nearest
imageSampler.filter_mode = CL_FILTER_NEAREST;
ret += test_read_image_formats( device, formatList, filterFlags, numFormats, &imageSampler, kUInt, imageType );
}
}
delete[] filterFlags;
delete[] formatList;
return ret;
}

View File

@@ -0,0 +1,332 @@
//
// 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 <float.h>
#if defined( __APPLE__ )
#include <signal.h>
#include <sys/signal.h>
#include <setjmp.h>
#endif
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_device_type gDeviceType;
extern bool gTestReadWrite;
#define MAX_TRIES 1
#define MAX_CLAMPED 1
const char *read1DKernelSourcePattern =
"__kernel void sample_kernel( read_only image1d_t input, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int offset = tidX;\n"
" %s clr = read_image%s( input, tidX );\n"
" int4 test = (clr != read_image%s( input, sampler, tidX ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
const char *read_write1DKernelSourcePattern =
"__kernel void sample_kernel( read_only image1d_t read_only_image, read_write image1d_t read_write_image, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int offset = tidX;\n"
" %s clr = read_image%s( read_only_image, sampler, tidX );\n"
" write_image%s(read_write_image, tidX, clr);\n"
" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n"
" int4 test = (clr != read_image%s(read_write_image, tidX));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
int test_read_image_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, image_sampler_data *imageSampler,
ExplicitType outputType, MTdata d )
{
int error;
size_t threads[2];
cl_sampler actualSampler;
// generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if ( gDebugTrace )
log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->height );
// Construct testing sources
cl_mem read_only_image, read_write_image;
cl_image_desc image_desc;
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE1D;
image_desc.image_width = imageInfo->width;
image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 );
image_desc.num_mip_levels = 0;
read_only_image = clCreateImage(context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
imageInfo->format,
&image_desc,
imageValues,
&error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_only 1D image of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
if(gTestReadWrite)
{
read_write_image = clCreateImage(context,
CL_MEM_READ_WRITE,
imageInfo->format,
&image_desc,
NULL,
&error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_write 1D image of size %d pitch %d (%s)\n",
(int)imageInfo->width,
(int)imageInfo->rowPitch,
IGetErrorString( error ) );
return error;
}
}
if ( gDebugTrace )
log_info( " - Creating kernel arguments...\n" );
// Create sampler to use
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 };
actualSampler = clCreateSamplerWithProperties( context, properties, &error );
test_error( error, "Unable to create image sampler" );
// Create results buffer
cl_mem results = clCreateBuffer( context, 0, imageInfo->width * sizeof(cl_int), NULL, &error);
test_error( error, "Unable to create results buffer" );
size_t resultValuesSize = imageInfo->width * sizeof(cl_int);
BufferOwningPtr<int> resultValues(malloc( resultValuesSize ));
memset( resultValues, 0xff, resultValuesSize );
clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
// Set arguments
int idx = 0;
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image );
test_error( error, "Unable to set kernel arguments" );
if(gTestReadWrite)
{
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image );
test_error( error, "Unable to set kernel arguments" );
}
error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results );
test_error( error, "Unable to set kernel arguments" );
// Run the kernel
threads[0] = (size_t)imageInfo->width;
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
if ( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * sizeof(cl_int) / 1024 ) );
error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if ( gDebugTrace )
log_info( " results read\n" );
// Check for non-zero comps
bool allZeroes = true;
for ( size_t ic = 0; ic < imageInfo->width; ++ic )
{
if ( resultValues[ic] ) {
allZeroes = false;
break;
}
}
if ( !allZeroes )
{
log_error( " Sampler-less reads differ from reads with sampler.\n" );
return -1;
}
clReleaseSampler(actualSampler);
clReleaseMemObject(results);
clReleaseMemObject(read_only_image);
if(gTestReadWrite)
{
clReleaseMemObject(read_write_image);
}
return 0;
}
int test_read_image_set_1D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
ExplicitType outputType )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
const char *dataType;
clProgramWrapper program;
clKernelWrapper kernel;
RandomSeed seed( gRandomSeed );
int error;
// Get our operating params
size_t maxWidth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
size_t pixelSize;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 1D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if ( outputType == kInt )
{
readFormat = "i";
dataType = "int4";
}
else if ( outputType == kUInt )
{
readFormat = "ui";
dataType = "uint4";
}
else // kFloat
{
readFormat = "f";
dataType = "float4";
}
if(gTestReadWrite)
{
sprintf( programSrc,
read_write1DKernelSourcePattern,
dataType,
readFormat,
readFormat,
readFormat);
}
else
{
sprintf( programSrc,
read1DKernelSourcePattern,
dataType,
readFormat,
readFormat );
}
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
{
if ( gDebugTrace )
log_info( " at size %d\n", (int)imageInfo.width );
int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info("Testing %d\n", (int)sizes[ idx ][ 0 ]);
if ( gDebugTrace )
log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] );
int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
if ( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
}
size = (size_t)imageInfo.rowPitch * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
int retCode = test_read_image_1D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,336 @@
//
// 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 <float.h>
#if defined( __APPLE__ )
#include <signal.h>
#include <sys/signal.h>
#include <setjmp.h>
#endif
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_device_type gDeviceType;
extern bool gTestReadWrite;
#define MAX_TRIES 1
#define MAX_CLAMPED 1
const char *read1DArrayKernelSourcePattern =
"__kernel void sample_kernel( read_only image1d_array_t input, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
" int offset = tidY*get_image_width(input) + tidX;\n"
" int2 coords = (int2)(tidX, tidY);\n"
" %s clr = read_image%s( input, coords );\n"
" int4 test = (clr != read_image%s( input, sampler, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
const char *read_write1DArrayKernelSourcePattern =
"__kernel void sample_kernel( read_only image1d_array_t read_only_image, read_write image1d_array_t read_write_image, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1);\n"
" int offset = tidY*get_image_width(read_only_image) + tidX;\n"
" int2 coords = (int2)(tidX, tidY);\n"
" %s clr = read_image%s( read_only_image, sampler, coords );\n"
" write_image%s(read_write_image, coords, clr);\n"
" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n"
" int4 test = (clr != read_image%s( read_write_image, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
int test_read_image_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, image_sampler_data *imageSampler,
ExplicitType outputType, MTdata d )
{
int error;
size_t threads[2];
cl_sampler actualSampler;
// generate_random_image_data allocates with malloc, so we use a MallocDataBuffer here
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if ( gDebugTrace )
log_info( " - Creating image %d by %d...\n", (int)imageInfo->width, (int)imageInfo->arraySize );
// Construct testing sources
cl_mem read_only_image, read_write_image;
cl_image_desc image_desc;
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_array_size = imageInfo->arraySize;
image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 );
image_desc.image_slice_pitch = 0;
image_desc.num_mip_levels = 0;
read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format,
&image_desc, imageValues, &error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_only 1D image array of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
if(gTestReadWrite)
{
read_write_image = clCreateImage(context,
CL_MEM_READ_WRITE,
imageInfo->format,
&image_desc,
NULL,
&error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_write 1D image array of size %d x %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
}
if ( gDebugTrace )
log_info( " - Creating kernel arguments...\n" );
// Create sampler to use
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 };
actualSampler = clCreateSamplerWithProperties( context, properties, &error );
test_error( error, "Unable to create image sampler" );
// Create results buffer
cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->arraySize * sizeof(cl_int), NULL, &error);
test_error( error, "Unable to create results buffer" );
size_t resultValuesSize = imageInfo->width * imageInfo->arraySize * sizeof(cl_int);
BufferOwningPtr<int> resultValues(malloc( resultValuesSize ));
memset( resultValues, 0xff, resultValuesSize );
clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
// Set arguments
int idx = 0;
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image );
test_error( error, "Unable to set kernel arguments" );
if(gTestReadWrite)
{
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image );
test_error( error, "Unable to set kernel arguments" );
}
error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results );
test_error( error, "Unable to set kernel arguments" );
// Run the kernel
threads[0] = (size_t)imageInfo->width;
threads[1] = (size_t)imageInfo->arraySize;
error = clEnqueueNDRangeKernel( queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
if ( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * imageInfo->arraySize * sizeof(cl_int) / 1024 ) );
error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if ( gDebugTrace )
log_info( " results read\n" );
// Check for non-zero comps
bool allZeroes = true;
size_t ic;
for ( ic = 0; ic < imageInfo->width * imageInfo->arraySize; ++ic )
{
if ( resultValues[ic] ) {
allZeroes = false;
break;
}
}
if ( !allZeroes )
{
log_error( " Sampler-less reads differ from reads with sampler at index %lu.\n", ic );
return -1;
}
clReleaseSampler(actualSampler);
clReleaseMemObject(results);
if(gTestReadWrite)
{
clReleaseMemObject(read_write_image);
}
return 0;
}
int test_read_image_set_1D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
ExplicitType outputType )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
const char *dataType;
clProgramWrapper program;
clKernelWrapper kernel;
RandomSeed seed( gRandomSeed );
int error;
// Get our operating params
size_t maxWidth, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
size_t pixelSize;
imageInfo.format = format;
imageInfo.height = imageInfo.depth = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if ( outputType == kInt )
{
readFormat = "i";
dataType = "int4";
}
else if ( outputType == kUInt )
{
readFormat = "ui";
dataType = "uint4";
}
else // kFloat
{
readFormat = "f";
dataType = "float4";
}
if(gTestReadWrite)
{
sprintf( programSrc,
read_write1DArrayKernelSourcePattern,
dataType,
readFormat,
readFormat,
readFormat);
}
else
{
sprintf( programSrc,
read1DArrayKernelSourcePattern,
dataType,
readFormat,
readFormat );
}
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize );
int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D_ARRAY, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch;
log_info("Testing %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ]);
if ( gDebugTrace )
log_info( " at max size %d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 2 ] );
int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
if ( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
}
imageInfo.slicePitch = imageInfo.rowPitch;
size = (size_t)imageInfo.rowPitch * (size_t)imageInfo.arraySize * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d (row pitch %d) out of %d,%d\n", (int)imageInfo.width, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)maxWidth, (int)maxArraySize );
int retCode = test_read_image_1D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,324 @@
//
// 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 <float.h>
#if defined( __APPLE__ )
#include <signal.h>
#include <sys/signal.h>
#include <setjmp.h>
#endif
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gTestSmallImages, gTestMaxImages, gTestRounding;
extern cl_device_type gDeviceType;
#define MAX_TRIES 1
#define MAX_CLAMPED 1
const char *read1DBufferKernelSourcePattern =
"__kernel void sample_kernel( read_only image1d_buffer_t inputA, read_only image1d_t inputB, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0);\n"
" int offset = tidX;\n"
" %s clr = read_image%s( inputA, tidX );\n"
" int4 test = (clr != read_image%s( inputB, sampler, tidX ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
int test_read_image_1D_buffer( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, image_sampler_data *imageSampler,
ExplicitType outputType, MTdata d )
{
int error;
size_t threads[2];
cl_sampler actualSampler;
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
if ( gDebugTrace )
log_info( " - Creating 1D image from buffer %d ...\n", (int)imageInfo->width );
// Construct testing sources
cl_mem image[2];
cl_image_desc image_desc;
cl_mem imageBuffer = clCreateBuffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->rowPitch, imageValues, &error);
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create buffer of size %d bytes (%s)\n", (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER;
image_desc.image_width = imageInfo->width;
image_desc.mem_object = imageBuffer;
image[0] = clCreateImage( context, CL_MEM_READ_ONLY, imageInfo->format,
&image_desc, NULL, &error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create IMAGE1D_BUFFER of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
cl_mem ret = NULL;
error = clGetMemObjectInfo(image[0], CL_MEM_ASSOCIATED_MEMOBJECT, sizeof(ret), &ret, NULL);
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to query CL_MEM_ASSOCIATED_MEMOBJECT\n", IGetErrorString( error ) );
return error;
}
if (ret != imageBuffer) {
log_error("ERROR: clGetImageInfo for CL_IMAGE_BUFFER returned wrong value\n");
return -1;
}
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE1D;
image_desc.image_width = imageInfo->width;
image[1] = clCreateImage( context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, imageInfo->format, &image_desc, imageValues, &error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create IMAGE1D of size %d pitch %d (%s)\n", (int)imageInfo->width, (int)imageInfo->rowPitch, IGetErrorString( error ) );
return error;
}
if ( gDebugTrace )
log_info( " - Creating kernel arguments...\n" );
// Create sampler to use
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 };
actualSampler = clCreateSamplerWithProperties( context, properties, &error );
test_error( error, "Unable to create image sampler" );
// Create results buffer
cl_mem results = clCreateBuffer( context, 0, imageInfo->width * sizeof(cl_int), NULL, &error);
test_error( error, "Unable to create results buffer" );
size_t resultValuesSize = imageInfo->width * sizeof(cl_int);
BufferOwningPtr<int> resultValues(malloc( resultValuesSize ));
memset( resultValues, 0xff, resultValuesSize );
clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
// Set arguments
int idx = 0;
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image[0] );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &image[1] );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results );
test_error( error, "Unable to set kernel arguments" );
// Run the kernel
threads[0] = (size_t)imageInfo->width;
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
if ( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * sizeof(cl_int) / 1024 ) );
error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if ( gDebugTrace )
log_info( " results read\n" );
// Check for non-zero comps
bool allZeroes = true;
for ( size_t ic = 0; ic < imageInfo->width; ++ic )
{
if ( resultValues[ic] ) {
allZeroes = false;
break;
}
}
if ( !allZeroes )
{
log_error( " Sampler-less reads differ from reads with sampler.\n" );
return -1;
}
clReleaseSampler(actualSampler);
clReleaseMemObject(results);
clReleaseMemObject(image[0]);
clReleaseMemObject(image[1]);
clReleaseMemObject(imageBuffer);
return 0;
}
int test_read_image_set_1D_buffer( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler,
ExplicitType outputType )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
const char *dataType;
clProgramWrapper program;
clKernelWrapper kernel;
RandomSeed seed( gRandomSeed );
int error;
// Get our operating params
size_t maxWidth, maxWidth1D;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
size_t pixelSize;
if (format->image_channel_order == CL_RGB || format->image_channel_order == CL_RGBx)
{
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_SIGNED_INT8:
case CL_SIGNED_INT16:
case CL_SIGNED_INT32:
case CL_UNSIGNED_INT8:
case CL_UNSIGNED_INT16:
case CL_UNSIGNED_INT32:
case CL_UNORM_INT_101010:
log_info( "Skipping image format: %s %s\n", GetChannelOrderName( format->image_channel_order ),
GetChannelTypeName( format->image_channel_data_type ));
return 0;
default:
break;
}
}
imageInfo.format = format;
imageInfo.height = imageInfo.depth = imageInfo.arraySize = imageInfo.slicePitch = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE1D;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth1D, NULL );
test_error( error, "Unable to get max image 1D buffer size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// note: image_buffer test uses image1D for results validation.
// So the test can't use the biggest possible size for image_buffer if it's bigger than the max image1D size
maxWidth = (maxWidth > maxWidth1D) ? maxWidth1D : maxWidth;
// Determine types
if ( outputType == kInt )
{
readFormat = "i";
dataType = "int4";
}
else if ( outputType == kUInt )
{
readFormat = "ui";
dataType = "uint4";
}
else // kFloat
{
readFormat = "f";
dataType = "float4";
}
sprintf( programSrc, read1DBufferKernelSourcePattern, dataType,
readFormat,
readFormat );
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
{
if ( gDebugTrace )
log_info( " at size %d\n", (int)imageInfo.width );
int retCode = test_read_image_1D_buffer( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, 1, 1, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE1D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
log_info("Testing %d\n", (int)sizes[ idx ][ 0 ]);
if ( gDebugTrace )
log_info( " at max size %d\n", (int)sizes[ idx ][ 0 ] );
int retCode = test_read_image_1D_buffer( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
size = (size_t)imageInfo.rowPitch * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d (row pitch %d) out of %d\n", (int)imageInfo.width, (int)imageInfo.rowPitch, (int)maxWidth );
int retCode = test_read_image_1D_buffer( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,334 @@
//
// 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 <float.h>
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_device_type gDeviceType;
extern bool gTestReadWrite;
const char *read2DArrayKernelSourcePattern =
"__kernel void sample_kernel( read_only %s input, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
" int offset = tidZ*get_image_width(input)*get_image_height(input) + tidY*get_image_width(input) + tidX;\n"
" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n"
" %s clr = read_image%s( input, coords );\n"
" int4 test = (clr != read_image%s( input, sampler, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
const char *read_write2DArrayKernelSourcePattern =
"__kernel void sample_kernel( read_only %s read_only_image, read_write %s read_write_image, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
" int offset = tidZ*get_image_width(read_only_image)*get_image_height(read_only_image) + tidY*get_image_width(read_only_image) + tidX;\n"
" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n"
" %s clr = read_image%s( read_only_image, sampler, coords );\n"
" write_image%s(read_write_image, coords, clr);\n"
" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n"
" int4 test = (clr != read_image%s( read_write_image, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
int test_read_image_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, image_sampler_data *imageSampler,
ExplicitType outputType, MTdata d )
{
int error;
size_t threads[3];
cl_sampler actualSampler;
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
// Don't use clEnqueueWriteImage; just use copy host ptr to get the data in
cl_image_desc image_desc;
cl_mem read_only_image, read_write_image;
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_array_size = imageInfo->arraySize;
image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 );
image_desc.image_slice_pitch = ( gEnablePitch ? imageInfo->slicePitch : 0 );
image_desc.num_mip_levels = 0;
read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format,
&image_desc, imageValues, &error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_only 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) );
return error;
}
if(gTestReadWrite)
{
read_write_image = clCreateImage(context,
CL_MEM_READ_WRITE,
imageInfo->format,
&image_desc,
NULL,
&error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_write 2D image array of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->arraySize, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) );
return error;
}
}
// Create sampler to use
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 };
actualSampler = clCreateSamplerWithProperties( context, properties, &error );
test_error( error, "Unable to create image sampler" );
// Create results buffer
cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->height * imageInfo->arraySize * sizeof(cl_int), NULL, &error);
test_error( error, "Unable to create results buffer" );
size_t resultValuesSize = imageInfo->width * imageInfo->height * imageInfo->arraySize * sizeof(cl_int);
BufferOwningPtr<int> resultValues(malloc( resultValuesSize ));
memset( resultValues, 0xff, resultValuesSize );
clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
// Set arguments
int idx = 0;
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image );
test_error( error, "Unable to set kernel arguments" );
if(gTestReadWrite)
{
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image );
test_error( error, "Unable to set kernel arguments" );
}
error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results );
test_error( error, "Unable to set kernel arguments" );
// Figure out thread dimensions
threads[0] = (size_t)imageInfo->width;
threads[1] = (size_t)imageInfo->height;
threads[2] = (size_t)imageInfo->arraySize;
// Run the kernel
error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
// Get results
error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if ( gDebugTrace )
log_info( " results read\n" );
// Check for non-zero comps
bool allZeroes = true;
for ( size_t ic = 0; ic < imageInfo->width * imageInfo->height * imageInfo->arraySize; ++ic )
{
if ( resultValues[ic] ) {
allZeroes = false;
break;
}
}
if ( !allZeroes )
{
log_error( " Sampler-less reads differ from reads with sampler.\n" );
return -1;
}
clReleaseSampler(actualSampler);
clReleaseMemObject(results);
clReleaseMemObject(read_only_image);
if(gTestReadWrite)
{
clReleaseMemObject(read_write_image);
}
return 0;
}
int test_read_image_set_2D_array( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
const char *dataType;
RandomSeed seed( gRandomSeed );
int error;
clProgramWrapper program;
clKernelWrapper kernel;
// Get operating parameters
size_t maxWidth, maxHeight, maxArraySize;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
size_t pixelSize;
imageInfo.format = format;
imageInfo.type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, sizeof( maxArraySize ), &maxArraySize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 2D array size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if ( outputType == kInt )
{
readFormat = "i";
dataType = "int4";
}
else if ( outputType == kUInt )
{
readFormat = "ui";
dataType = "uint4";
}
else // kFloat
{
readFormat = "f";
dataType = (format->image_channel_order == CL_DEPTH) ? "float" : "float4";
}
// Construct the source
if(gTestReadWrite)
{
sprintf( programSrc, read_write2DArrayKernelSourcePattern,
(format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t",
(format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t",
dataType,
readFormat,
readFormat,
readFormat);
}
else
{
sprintf( programSrc, read2DArrayKernelSourcePattern,
(format->image_channel_order == CL_DEPTH) ? "image2d_array_depth_t" : "image2d_array_t",
dataType,
readFormat,
readFormat );
}
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * get_pixel_size( imageInfo.format );
for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for ( imageInfo.arraySize = 2; imageInfo.arraySize < 9; imageInfo.arraySize++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize );
int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, 1, maxArraySize, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE2D_ARRAY, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.arraySize = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
log_info("Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ]);
if ( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.arraySize = (size_t)random_log_in_range( 16, (int)maxArraySize / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
if ( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
size_t extraHeight = (int)random_log_in_range( 0, 64, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
}
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.arraySize * 4 * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.arraySize, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxArraySize );
int retCode = test_read_image_2D_array( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
return 0;
}

View File

@@ -0,0 +1,337 @@
//
// 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 <float.h>
#define MAX_ERR 0.005f
#define MAX_HALF_LINEAR_ERR 0.3f
extern cl_command_queue queue;
extern cl_context context;
extern bool gDebugTrace, gTestSmallImages, gEnablePitch, gTestMaxImages, gTestRounding;
extern cl_device_type gDeviceType;
extern bool gTestReadWrite;
const char *read3DKernelSourcePattern =
"__kernel void sample_kernel( read_only image3d_t input, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
" int offset = tidZ*get_image_width(input)*get_image_height(input) + tidY*get_image_width(input) + tidX;\n"
" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n"
" %s clr = read_image%s( input, coords );\n"
" int4 test = (clr != read_image%s( input, sampler, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
const char *read_write3DKernelSourcePattern =
"__kernel void sample_kernel( read_only image3d_t read_only_image, read_write image3d_t read_write_image, sampler_t sampler, __global int *results )\n"
"{\n"
" int tidX = get_global_id(0), tidY = get_global_id(1), tidZ = get_global_id(2);\n"
" int offset = tidZ*get_image_width(read_only_image)*get_image_height(read_only_image) + tidY*get_image_width(read_only_image) + tidX;\n"
" int4 coords = (int4)( tidX, tidY, tidZ, 0 );\n"
" %s clr = read_image%s( read_only_image, sampler, coords );\n"
" write_image%s(read_write_image, coords, clr);\n"
" atomic_work_item_fence(CLK_IMAGE_MEM_FENCE, memory_order_acq_rel, memory_scope_work_item);\n"
" int4 test = (clr != read_image%s( read_write_image, coords ));\n"
" if ( test.x || test.y || test.z || test.w )\n"
" results[offset] = -1;\n"
" else\n"
" results[offset] = 0;\n"
"}";
int test_read_image_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_kernel kernel,
image_descriptor *imageInfo, image_sampler_data *imageSampler,
ExplicitType outputType, MTdata d )
{
int error;
size_t threads[3];
cl_sampler actualSampler;
BufferOwningPtr<char> imageValues;
generate_random_image_data( imageInfo, imageValues, d );
// Don't use clEnqueueWriteImage; just use copy host ptr to get the data in
cl_image_desc image_desc;
cl_mem read_only_image, read_write_image;
memset(&image_desc, 0x0, sizeof(cl_image_desc));
image_desc.image_type = CL_MEM_OBJECT_IMAGE3D;
image_desc.image_width = imageInfo->width;
image_desc.image_height = imageInfo->height;
image_desc.image_depth = imageInfo->depth;
image_desc.image_row_pitch = ( gEnablePitch ? imageInfo->rowPitch : 0 );
image_desc.image_slice_pitch = ( gEnablePitch ? imageInfo->slicePitch : 0 );
image_desc.num_mip_levels = 0;
read_only_image = clCreateImage( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageInfo->format,
&image_desc, imageValues, &error );
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_only 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) );
return error;
}
if(gTestReadWrite)
{
read_write_image = clCreateImage(context,
CL_MEM_READ_WRITE,
imageInfo->format,
&image_desc,
NULL,
&error);
if ( error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create read_write 3D image of size %d x %d x %d (pitch %d, %d ) (%s)", (int)imageInfo->width, (int)imageInfo->height, (int)imageInfo->depth, (int)imageInfo->rowPitch, (int)imageInfo->slicePitch, IGetErrorString( error ) );
return error;
}
}
// Create sampler to use
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 };
actualSampler = clCreateSamplerWithProperties( context, properties, &error );
test_error( error, "Unable to create image sampler" );
// Create results buffer
cl_mem results = clCreateBuffer( context, 0, imageInfo->width * imageInfo->height * imageInfo->depth * sizeof(cl_int), NULL, &error);
test_error( error, "Unable to create results buffer" );
size_t resultValuesSize = imageInfo->width * imageInfo->height * imageInfo->depth * sizeof(cl_int);
BufferOwningPtr<int> resultValues(malloc( resultValuesSize ));
memset( resultValues, 0xff, resultValuesSize );
clEnqueueWriteBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
// Set arguments
int idx = 0;
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_only_image );
test_error( error, "Unable to set kernel arguments" );
if(gTestReadWrite)
{
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &read_write_image );
test_error( error, "Unable to set kernel arguments" );
}
error = clSetKernelArg( kernel, idx++, sizeof( cl_sampler ), &actualSampler );
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernel, idx++, sizeof( cl_mem ), &results );
test_error( error, "Unable to set kernel arguments" );
// Figure out thread dimensions
threads[0] = (size_t)imageInfo->width;
threads[1] = (size_t)imageInfo->height;
threads[2] = (size_t)imageInfo->depth;
// Run the kernel
error = clEnqueueNDRangeKernel( queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to run kernel" );
if ( gDebugTrace )
log_info( " reading results, %ld kbytes\n", (unsigned long)( imageInfo->width * imageInfo->height * imageInfo->depth * sizeof(cl_int) / 1024 ) );
// Get results
error = clEnqueueReadBuffer( queue, results, CL_TRUE, 0, resultValuesSize, resultValues, 0, NULL, NULL );
test_error( error, "Unable to read results from kernel" );
if ( gDebugTrace )
log_info( " results read\n" );
// Check for non-zero comps
bool allZeroes = true;
size_t ic;
for ( ic = 0; ic < imageInfo->width * imageInfo->height * imageInfo->depth; ++ic )
{
if ( resultValues[ic] ) {
allZeroes = false;
break;
}
}
if ( !allZeroes )
{
log_error( " Sampler-less reads differ from reads with sampler at index %lu.\n", ic );
return -1;
}
clReleaseSampler(actualSampler);
clReleaseMemObject(results);
clReleaseMemObject(read_only_image);
if(gTestReadWrite)
{
clReleaseMemObject(read_write_image);
}
return 0;
}
int test_read_image_set_3D( cl_device_id device, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType )
{
char programSrc[10240];
const char *ptr;
const char *readFormat;
const char *dataType;
RandomSeed seed( gRandomSeed );
int error;
clProgramWrapper program;
clKernelWrapper kernel;
// Get operating parameters
size_t maxWidth, maxHeight, maxDepth;
cl_ulong maxAllocSize, memSize;
image_descriptor imageInfo = { 0 };
size_t pixelSize;
imageInfo.format = format;
imageInfo.arraySize = 0;
imageInfo.type = CL_MEM_OBJECT_IMAGE3D;
pixelSize = get_pixel_size( imageInfo.format );
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( maxDepth ), &maxDepth, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
error |= clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof( memSize ), &memSize, NULL );
test_error( error, "Unable to get max image 3D size from device" );
if (memSize > (cl_ulong)SIZE_MAX) {
memSize = (cl_ulong)SIZE_MAX;
}
// Determine types
if ( outputType == kInt )
{
readFormat = "i";
dataType = "int4";
}
else if ( outputType == kUInt )
{
readFormat = "ui";
dataType = "uint4";
}
else // kFloat
{
readFormat = "f";
dataType = "float4";
}
// Construct the source
if(gTestReadWrite)
{
sprintf( programSrc,
read_write3DKernelSourcePattern,
dataType,
readFormat,
readFormat,
readFormat);
}
else
{
sprintf( programSrc,
read3DKernelSourcePattern,
dataType,
readFormat,
readFormat );
}
ptr = programSrc;
error = create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, &ptr, "sample_kernel", "-cl-std=CL2.0" );
test_error( error, "Unable to create testing kernel" );
// Run tests
if ( gTestSmallImages )
{
for ( imageInfo.width = 1; imageInfo.width < 13; imageInfo.width++ )
{
imageInfo.rowPitch = imageInfo.width * pixelSize;
for ( imageInfo.height = 1; imageInfo.height < 9; imageInfo.height++ )
{
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
for ( imageInfo.depth = 2; imageInfo.depth < 9; imageInfo.depth++ )
{
if ( gDebugTrace )
log_info( " at size %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth );
int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
}
}
else if ( gTestMaxImages )
{
// Try a specific set of maximum sizes
size_t numbeOfSizes;
size_t sizes[100][3];
get_max_sizes(&numbeOfSizes, 100, sizes, maxWidth, maxHeight, maxDepth, 1, maxAllocSize, memSize, CL_MEM_OBJECT_IMAGE3D, imageInfo.format);
for ( size_t idx = 0; idx < numbeOfSizes; idx++ )
{
imageInfo.width = sizes[ idx ][ 0 ];
imageInfo.height = sizes[ idx ][ 1 ];
imageInfo.depth = sizes[ idx ][ 2 ];
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.height * imageInfo.rowPitch;
log_info("Testing %d x %d x %d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ]);
if ( gDebugTrace )
log_info( " at max size %d,%d,%d\n", (int)sizes[ idx ][ 0 ], (int)sizes[ idx ][ 1 ], (int)sizes[ idx ][ 2 ] );
int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
else
{
for ( int i = 0; i < NUM_IMAGE_ITERATIONS; i++ )
{
cl_ulong size;
// Loop until we get a size that a) will fit in the max alloc size and b) that an allocation of that
// image, the result array, plus offset arrays, will fit in the global ram space
do
{
imageInfo.width = (size_t)random_log_in_range( 16, (int)maxWidth / 32, seed );
imageInfo.height = (size_t)random_log_in_range( 16, (int)maxHeight / 32, seed );
imageInfo.depth = (size_t)random_log_in_range( 16, (int)maxDepth / 32, seed );
imageInfo.rowPitch = imageInfo.width * pixelSize;
imageInfo.slicePitch = imageInfo.rowPitch * imageInfo.height;
if ( gEnablePitch )
{
size_t extraWidth = (int)random_log_in_range( 0, 64, seed );
imageInfo.rowPitch += extraWidth * pixelSize;
size_t extraHeight = (int)random_log_in_range( 0, 64, seed );
imageInfo.slicePitch = imageInfo.rowPitch * (imageInfo.height + extraHeight);
}
size = (cl_ulong)imageInfo.slicePitch * (cl_ulong)imageInfo.depth * 4 * 4;
} while ( size > maxAllocSize || ( size * 3 ) > memSize );
if ( gDebugTrace )
log_info( " at size %d,%d,%d (pitch %d,%d) out of %d,%d,%d\n", (int)imageInfo.width, (int)imageInfo.height, (int)imageInfo.depth, (int)imageInfo.rowPitch, (int)imageInfo.slicePitch, (int)maxWidth, (int)maxHeight, (int)maxDepth );
int retCode = test_read_image_3D( device, context, queue, kernel, &imageInfo, imageSampler, outputType, seed );
if ( retCode )
return retCode;
}
}
return 0;
}

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 _testBase_h
#define _testBase_h
#include "../../test_common/harness/compat.h"
#include "../../test_common/harness/testHarness.h"
#include "../../test_common/harness/kernelHelpers.h"
#include "../../test_common/harness/clImageHelper.h"
#include "../../test_common/harness/imageHelpers.h"
// Amount to offset pixels for checking normalized reads
#define NORM_OFFSET 0.1f
enum TypesToTest
{
kTestInt = ( 1 << 0 ),
kTestUInt = ( 1 << 1 ),
kTestFloat = ( 1 << 2 ),
kTestAllTypes = kTestInt | kTestUInt | kTestFloat
};
// For the clCopyImage test
enum MethodsToTest
{
k1D = ( 1 << 0 ),
k2D = ( 1 << 1 ),
k1DArray = ( 1 << 2 ),
k2DArray = ( 1 << 3 ),
k3D = ( 1 << 4 ),
k2DTo3D = ( 1 << 5 ),
k3DTo2D = ( 1 << 6 ),
k2DArrayTo2D = ( 1 << 7 ),
k2DTo2DArray = ( 1 << 8 ),
k2DArrayTo3D = ( 1 << 9 ),
k3DTo2DArray = ( 1 << 10 ),
};
enum TestTypes
{
kReadTests = 1 << 0 ,
kWriteTests = 1 << 1,
kReadWriteTests = 1 << 2,
kAllTests = ( kReadTests | kWriteTests | kReadWriteTests )
};
typedef int (*test_format_set_fn)( cl_device_id device,
cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
image_sampler_data *imageSampler, ExplicitType outputType,
cl_mem_object_type imageType );
extern int test_read_image_formats( cl_device_id device,
cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
image_sampler_data *imageSampler, ExplicitType outputType,
cl_mem_object_type imageType );
extern int test_write_image_formats( cl_device_id device,
cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
image_sampler_data *imageSampler, ExplicitType outputType,
cl_mem_object_type imageType );
#endif // _testBase_h