mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
Initial open source release of OpenCL 2.2 CTS.
This commit is contained in:
25
test_conformance/events/CMakeLists.txt
Normal file
25
test_conformance/events/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
set(MODULE_NAME EVENTS)
|
||||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
main.c
|
||||
test_events.cpp
|
||||
test_event_dependencies.cpp
|
||||
test_waitlists.cpp
|
||||
test_userevents.cpp
|
||||
test_userevents_multithreaded.cpp
|
||||
action_classes.cpp
|
||||
test_callbacks.cpp
|
||||
../../test_common/harness/genericThread.cpp
|
||||
../../test_common/harness/errorHelpers.c
|
||||
../../test_common/harness/threadTesting.c
|
||||
../../test_common/harness/testHarness.c
|
||||
../../test_common/harness/kernelHelpers.c
|
||||
../../test_common/harness/typeWrappers.cpp
|
||||
../../test_common/harness/mt19937.c
|
||||
../../test_common/harness/conversions.c
|
||||
../../test_common/harness/msvc9.c
|
||||
../../test_common/harness/ThreadPool.c
|
||||
../../test_common/harness/parseParameters.cpp
|
||||
)
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
18
test_conformance/events/Jamfile
Normal file
18
test_conformance/events/Jamfile
Normal file
@@ -0,0 +1,18 @@
|
||||
project
|
||||
: requirements
|
||||
<toolset>gcc:<cflags>-xc++
|
||||
<toolset>msvc:<cflags>"/TP"
|
||||
;
|
||||
|
||||
exe test_events
|
||||
: main.c
|
||||
test_event_dependencies.cpp
|
||||
test_events.cpp
|
||||
test_waitlists.cpp
|
||||
;
|
||||
|
||||
install dist
|
||||
: test_events
|
||||
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/events
|
||||
<variant>release:<location>$(DIST)/release/tests/test_conformance/events
|
||||
;
|
||||
51
test_conformance/events/Makefile
Normal file
51
test_conformance/events/Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
ifdef BUILD_WITH_ATF
|
||||
ATF = -framework ATF
|
||||
USE_ATF = -DUSE_ATF
|
||||
endif
|
||||
|
||||
SRCS = main.c \
|
||||
test_events.cpp \
|
||||
test_event_dependencies.cpp \
|
||||
test_userevents.cpp \
|
||||
test_waitlists.cpp \
|
||||
test_callbacks.cpp \
|
||||
action_classes.cpp \
|
||||
test_userevents_multithreaded.cpp \
|
||||
../../test_common/harness/errorHelpers.c \
|
||||
../../test_common/harness/threadTesting.c \
|
||||
../../test_common/harness/testHarness.c \
|
||||
../../test_common/harness/genericThread.cpp \
|
||||
../../test_common/harness/kernelHelpers.c \
|
||||
../../test_common/harness/typeWrappers.cpp \
|
||||
../../test_common/harness/mt19937.c \
|
||||
../../test_common/harness/conversions.c \
|
||||
../../test_common/harness/ThreadPool.c \
|
||||
|
||||
DEFINES = DONT_TEST_GARBAGE_POINTERS
|
||||
|
||||
SOURCES = $(abspath $(SRCS))
|
||||
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
|
||||
LIBPATH += -L.
|
||||
HEADERS =
|
||||
TARGET = test_events
|
||||
INCLUDE =
|
||||
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32
|
||||
CC = c++
|
||||
CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
|
||||
CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
|
||||
LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF}
|
||||
|
||||
OBJECTS := ${SOURCES:.c=.o}
|
||||
OBJECTS := ${OBJECTS:.cpp=.o}
|
||||
|
||||
TARGETOBJECT =
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJECTS)
|
||||
|
||||
.DEFAULT:
|
||||
@echo The target \"$@\" does not exist in Makefile.
|
||||
658
test_conformance/events/action_classes.cpp
Normal file
658
test_conformance/events/action_classes.cpp
Normal file
@@ -0,0 +1,658 @@
|
||||
//
|
||||
// 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 "action_classes.h"
|
||||
|
||||
#pragma mark -------------------- Base Action Class -------------------------
|
||||
|
||||
const cl_uint BufferSizeReductionFactor = 20;
|
||||
|
||||
cl_int Action::IGetPreferredImageSize2D( cl_device_id device, size_t &outWidth, size_t &outHeight )
|
||||
{
|
||||
cl_ulong maxAllocSize;
|
||||
size_t maxWidth, maxHeight;
|
||||
cl_int error;
|
||||
|
||||
|
||||
// Get the largest possible buffer we could allocate
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
|
||||
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( maxWidth ), &maxWidth, NULL );
|
||||
error |= clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( maxHeight ), &maxHeight, NULL );
|
||||
test_error( error, "Unable to get device config" );
|
||||
|
||||
// Create something of a decent size
|
||||
if( maxWidth * maxHeight * 4 > maxAllocSize / BufferSizeReductionFactor )
|
||||
{
|
||||
float rootSize = sqrtf( (float)( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) );
|
||||
|
||||
if( (size_t)rootSize > maxWidth )
|
||||
outWidth = maxWidth;
|
||||
else
|
||||
outWidth = (size_t)rootSize;
|
||||
outHeight = (size_t)( ( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) / outWidth );
|
||||
if( outHeight > maxHeight )
|
||||
outHeight = maxHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
outWidth = maxWidth;
|
||||
outHeight = maxHeight;
|
||||
}
|
||||
|
||||
outWidth /=2;
|
||||
outHeight /=2;
|
||||
|
||||
if (outWidth > 2048)
|
||||
outWidth = 2048;
|
||||
if (outHeight > 2048)
|
||||
outHeight = 2048;
|
||||
log_info("\tImage size: %d x %d (%gMB)\n", (int)outWidth, (int)outHeight,
|
||||
(double)((int)outWidth*(int)outHeight*4)/(1024.0*1024.0));
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Action::IGetPreferredImageSize3D( cl_device_id device, size_t &outWidth, size_t &outHeight, size_t &outDepth )
|
||||
{
|
||||
cl_ulong maxAllocSize;
|
||||
size_t maxWidth, maxHeight, maxDepth;
|
||||
cl_int error;
|
||||
|
||||
|
||||
// Get the largest possible buffer we could allocate
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
|
||||
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 );
|
||||
test_error( error, "Unable to get device config" );
|
||||
|
||||
// Create something of a decent size
|
||||
if( (cl_ulong)maxWidth * maxHeight * maxDepth > maxAllocSize / ( BufferSizeReductionFactor * 4 ) )
|
||||
{
|
||||
float rootSize = cbrtf( (float)( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) );
|
||||
|
||||
if( (size_t)rootSize > maxWidth )
|
||||
outWidth = maxWidth;
|
||||
else
|
||||
outWidth = (size_t)rootSize;
|
||||
if( (size_t)rootSize > maxHeight )
|
||||
outHeight = maxHeight;
|
||||
else
|
||||
outHeight = (size_t)rootSize;
|
||||
outDepth = (size_t)( ( maxAllocSize / ( BufferSizeReductionFactor * 4 ) ) / ( outWidth * outHeight ) );
|
||||
if( outDepth > maxDepth )
|
||||
outDepth = maxDepth;
|
||||
}
|
||||
else
|
||||
{
|
||||
outWidth = maxWidth;
|
||||
outHeight = maxHeight;
|
||||
outDepth = maxDepth;
|
||||
}
|
||||
|
||||
outWidth /=2;
|
||||
outHeight /=2;
|
||||
outDepth /=2;
|
||||
|
||||
if (outWidth > 512)
|
||||
outWidth = 512;
|
||||
if (outHeight > 512)
|
||||
outHeight = 512;
|
||||
if (outDepth > 512)
|
||||
outDepth = 512;
|
||||
log_info("\tImage size: %d x %d x %d (%gMB)\n", (int)outWidth, (int)outHeight, (int)outDepth,
|
||||
(double)((int)outWidth*(int)outHeight*(int)outDepth*4)/(1024.0*1024.0));
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma mark -------------------- Execution Sub-Classes -------------------------
|
||||
|
||||
cl_int NDRangeKernelAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
const char *long_kernel[] = {
|
||||
"__kernel void sample_test(__global float *src, __global int *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
" int i;\n"
|
||||
"\n"
|
||||
" for( i = 0; i < 100000; i++ )\n"
|
||||
" {\n"
|
||||
" dst[tid] = (int)src[tid] * 3;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"}\n" };
|
||||
|
||||
size_t threads[1] = { 1000 };
|
||||
int error;
|
||||
|
||||
if( create_single_kernel_helper( context, &mProgram, &mKernel, 1, long_kernel, "sample_test" ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = get_max_common_work_group_size( context, mKernel, threads[0], &mLocalThreads[0] );
|
||||
test_error( error, "Unable to get work group size to use" );
|
||||
|
||||
mStreams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1000, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
mStreams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 1000, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
|
||||
/* Set the arguments */
|
||||
error = clSetKernelArg( mKernel, 0, sizeof( mStreams[0] ), &mStreams[0] );
|
||||
test_error( error, "Unable to set kernel arguments" );
|
||||
error = clSetKernelArg( mKernel, 1, sizeof( mStreams[1] ), &mStreams[1] );
|
||||
test_error( error, "Unable to set kernel arguments" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int NDRangeKernelAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t threads[1] = { 1000 };
|
||||
cl_int error = clEnqueueNDRangeKernel( queue, mKernel, 1, NULL, threads, mLocalThreads, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to execute kernel" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma mark -------------------- Buffer Sub-Classes -------------------------
|
||||
|
||||
cl_int BufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue, bool allocate )
|
||||
{
|
||||
cl_int error;
|
||||
cl_ulong maxAllocSize;
|
||||
|
||||
|
||||
// Get the largest possible buffer we could allocate
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof( maxAllocSize ), &maxAllocSize, NULL );
|
||||
|
||||
// Don't create a buffer quite that big, just so we have some space left over for other work
|
||||
mSize = (size_t)( maxAllocSize / BufferSizeReductionFactor );
|
||||
|
||||
// Cap at 128M so tests complete in a reasonable amount of time.
|
||||
if (mSize > 128 << 20)
|
||||
mSize = 128 << 20;
|
||||
|
||||
mSize /=2;
|
||||
|
||||
log_info("\tBuffer size: %gMB\n", (double)mSize/(1024.0*1024.0));
|
||||
|
||||
mBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, mSize, NULL, &error );
|
||||
test_error( error, "Unable to create buffer to test against" );
|
||||
|
||||
mOutBuffer = malloc( mSize );
|
||||
if( mOutBuffer == NULL )
|
||||
{
|
||||
log_error( "ERROR: Unable to allocate temp buffer (out of memory)\n" );
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int ReadBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
return BufferAction::Setup( device, context, queue, true );
|
||||
}
|
||||
|
||||
cl_int ReadBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
cl_int error = clEnqueueReadBuffer( queue, mBuffer, CL_FALSE, 0, mSize, mOutBuffer, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue buffer read" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int WriteBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
return BufferAction::Setup( device, context, queue, true );
|
||||
}
|
||||
|
||||
cl_int WriteBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
cl_int error = clEnqueueWriteBuffer( queue, mBuffer, CL_FALSE, 0, mSize, mOutBuffer, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue buffer write" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
MapBufferAction::~MapBufferAction()
|
||||
{
|
||||
if (mQueue)
|
||||
clEnqueueUnmapMemObject( mQueue, mBuffer, mMappedPtr, 0, NULL, NULL );
|
||||
}
|
||||
|
||||
cl_int MapBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
return BufferAction::Setup( device, context, queue, false );
|
||||
}
|
||||
|
||||
cl_int MapBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
cl_int error;
|
||||
mQueue = queue;
|
||||
mMappedPtr = clEnqueueMapBuffer( queue, mBuffer, CL_FALSE, CL_MAP_READ, 0, mSize, numWaits, waits, outEvent, &error );
|
||||
test_error( error, "Unable to enqueue buffer map" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int UnmapBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error = BufferAction::Setup( device, context, queue, false );
|
||||
if( error != CL_SUCCESS )
|
||||
return error;
|
||||
|
||||
mMappedPtr = clEnqueueMapBuffer( queue, mBuffer, CL_TRUE, CL_MAP_READ, 0, mSize, 0, NULL, NULL, &error );
|
||||
test_error( error, "Unable to enqueue buffer map" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int UnmapBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
cl_int error = clEnqueueUnmapMemObject( queue, mBuffer, mMappedPtr, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue buffer unmap" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -------------------- Read/Write Image Classes -------------------------
|
||||
|
||||
cl_int ReadImage2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) )
|
||||
return error;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mOutput = malloc( mWidth * mHeight * 4 );
|
||||
if( mOutput == NULL )
|
||||
{
|
||||
log_error( "ERROR: Unable to allocate buffer: out of memory\n" );
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int ReadImage2DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 };
|
||||
|
||||
cl_int error = clEnqueueReadImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image read" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int ReadImage3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mOutput = malloc( mWidth * mHeight * mDepth * 4 );
|
||||
if( mOutput == NULL )
|
||||
{
|
||||
log_error( "ERROR: Unable to allocate buffer: out of memory\n" );
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int ReadImage3DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth };
|
||||
|
||||
cl_int error = clEnqueueReadImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image read" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int WriteImage2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) )
|
||||
return error;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mOutput = malloc( mWidth * mHeight * 4 );
|
||||
if( mOutput == NULL )
|
||||
{
|
||||
log_error( "ERROR: Unable to allocate buffer: out of memory\n" );
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int WriteImage2DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 };
|
||||
|
||||
cl_int error = clEnqueueWriteImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image write" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int WriteImage3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mOutput = malloc( mWidth * mHeight * mDepth * 4 );
|
||||
if( mOutput == NULL )
|
||||
{
|
||||
log_error( "ERROR: Unable to allocate buffer: out of memory\n" );
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int WriteImage3DAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth };
|
||||
|
||||
cl_int error = clEnqueueWriteImage( queue, mImage, CL_FALSE, origin, region, 0, 0, mOutput, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image write" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma mark -------------------- Copy Image Classes -------------------------
|
||||
|
||||
cl_int CopyImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth };
|
||||
|
||||
cl_int error = clEnqueueCopyImage( queue, mSrcImage, mDstImage, origin, origin, region, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image copy" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyImage2Dto2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) )
|
||||
return error;
|
||||
|
||||
mWidth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mSrcImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDstImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDepth = 1;
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyImage2Dto3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
mDepth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mSrcImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDstImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDepth = 1;
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyImage3Dto2DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
mDepth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mSrcImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDstImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDepth = 1;
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyImage3Dto3DAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
mDepth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mSrcImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDstImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma mark -------------------- Copy Image/Buffer Classes -------------------------
|
||||
|
||||
cl_int Copy2DImageToBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) )
|
||||
return error;
|
||||
|
||||
mWidth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mSrcImage = create_image_2d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDstBuffer = clCreateBuffer( context, CL_MEM_WRITE_ONLY, mWidth * mHeight * 4, NULL, &error );
|
||||
test_error( error, "Unable to create buffer to test against" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Copy2DImageToBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 };
|
||||
|
||||
cl_int error = clEnqueueCopyImageToBuffer( queue, mSrcImage, mDstBuffer, origin, region, 0, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image to buffer copy" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Copy3DImageToBufferAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
mDepth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mSrcImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
mDstBuffer = clCreateBuffer( context, CL_MEM_WRITE_ONLY, mWidth * mHeight * mDepth * 4, NULL, &error );
|
||||
test_error( error, "Unable to create buffer to test against" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Copy3DImageToBufferAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth };
|
||||
|
||||
cl_int error = clEnqueueCopyImageToBuffer( queue, mSrcImage, mDstBuffer, origin, region, 0, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue image to buffer copy" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyBufferTo2DImageAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) )
|
||||
return error;
|
||||
|
||||
mWidth /= 2;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
|
||||
mSrcBuffer = clCreateBuffer( context, CL_MEM_READ_ONLY, mWidth * mHeight * 4, NULL, &error );
|
||||
test_error( error, "Unable to create buffer to test against" );
|
||||
|
||||
mDstImage = create_image_2d( context, CL_MEM_WRITE_ONLY, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyBufferTo2DImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 };
|
||||
|
||||
cl_int error = clEnqueueCopyBufferToImage( queue, mSrcBuffer, mDstImage, 0, origin, region, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue buffer to image copy" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyBufferTo3DImageAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize3D( device, mWidth, mHeight, mDepth ) ) )
|
||||
return error;
|
||||
|
||||
mDepth /= 2;
|
||||
|
||||
mSrcBuffer = clCreateBuffer( context, CL_MEM_READ_ONLY, mWidth * mHeight * mDepth * 4, NULL, &error );
|
||||
test_error( error, "Unable to create buffer to test against" );
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mDstImage = create_image_3d( context, CL_MEM_READ_ONLY, &format, mWidth, mHeight, mDepth, 0, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int CopyBufferTo3DImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, mDepth };
|
||||
|
||||
cl_int error = clEnqueueCopyBufferToImage( queue, mSrcBuffer, mDstImage, 0, origin, region, numWaits, waits, outEvent );
|
||||
test_error( error, "Unable to enqueue buffer to image copy" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma mark -------------------- Map Image Class -------------------------
|
||||
|
||||
MapImageAction::~MapImageAction()
|
||||
{
|
||||
if (mQueue)
|
||||
clEnqueueUnmapMemObject( mQueue, mImage, mMappedPtr, 0, NULL, NULL );
|
||||
}
|
||||
|
||||
cl_int MapImageAction::Setup( cl_device_id device, cl_context context, cl_command_queue queue )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
if( ( error = IGetPreferredImageSize2D( device, mWidth, mHeight ) ) )
|
||||
return error;
|
||||
|
||||
cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
|
||||
mImage = create_image_2d( context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, &format, mWidth, mHeight, 0, NULL, &error );
|
||||
test_error( error, "Unable to create image to test against" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int MapImageAction::Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
size_t origin[ 3 ] = { 0, 0, 0 }, region[ 3 ] = { mWidth, mHeight, 1 };
|
||||
size_t outPitch;
|
||||
|
||||
mQueue = queue;
|
||||
mMappedPtr = clEnqueueMapImage( queue, mImage, CL_FALSE, CL_MAP_READ, origin, region, &outPitch, NULL, numWaits, waits, outEvent, &error );
|
||||
test_error( error, "Unable to enqueue image map" );
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
326
test_conformance/events/action_classes.h
Normal file
326
test_conformance/events/action_classes.h
Normal file
@@ -0,0 +1,326 @@
|
||||
//
|
||||
// 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 _action_classes_h
|
||||
#define _action_classes_h
|
||||
|
||||
#include "testBase.h"
|
||||
|
||||
// This is a base class from which all actions are born
|
||||
// Note: No actions should actually feed I/O to each other, because then
|
||||
// it would potentially be possible for an implementation to make actions
|
||||
// wait on one another based on their shared I/O, not because of their
|
||||
// wait lists!
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
Action() {}
|
||||
virtual ~Action() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue ) = 0;
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent ) = 0;
|
||||
|
||||
virtual const char * GetName( void ) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
cl_int IGetPreferredImageSize2D( cl_device_id device, size_t &outWidth, size_t &outHeight );
|
||||
cl_int IGetPreferredImageSize3D( cl_device_id device, size_t &outWidth, size_t &outHeight, size_t &outDepth );
|
||||
};
|
||||
|
||||
// Simple NDRangeKernel execution that takes a noticable amount of time
|
||||
class NDRangeKernelAction : public Action
|
||||
{
|
||||
public:
|
||||
NDRangeKernelAction() {}
|
||||
virtual ~NDRangeKernelAction() {}
|
||||
|
||||
size_t mLocalThreads[ 1 ];
|
||||
clMemWrapper mStreams[ 2 ];
|
||||
clProgramWrapper mProgram;
|
||||
clKernelWrapper mKernel;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "NDRangeKernel"; }
|
||||
};
|
||||
|
||||
// Base action for buffer actions
|
||||
class BufferAction : public Action
|
||||
{
|
||||
public:
|
||||
clMemWrapper mBuffer;
|
||||
size_t mSize;
|
||||
void *mOutBuffer;
|
||||
|
||||
BufferAction() { mOutBuffer = NULL; }
|
||||
virtual ~BufferAction() { free( mOutBuffer ); }
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue, bool allocate );
|
||||
};
|
||||
|
||||
class ReadBufferAction : public BufferAction
|
||||
{
|
||||
public:
|
||||
ReadBufferAction() {}
|
||||
virtual ~ReadBufferAction() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "ReadBuffer"; }
|
||||
};
|
||||
|
||||
class WriteBufferAction : public BufferAction
|
||||
{
|
||||
public:
|
||||
WriteBufferAction() {}
|
||||
virtual ~WriteBufferAction() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "WriteBuffer"; }
|
||||
};
|
||||
|
||||
class MapBufferAction : public BufferAction
|
||||
{
|
||||
public:
|
||||
MapBufferAction() : mQueue(0) {}
|
||||
|
||||
cl_command_queue mQueue;
|
||||
void *mMappedPtr;
|
||||
|
||||
virtual ~MapBufferAction();
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "MapBuffer"; }
|
||||
};
|
||||
|
||||
class UnmapBufferAction : public BufferAction
|
||||
{
|
||||
public:
|
||||
UnmapBufferAction() {}
|
||||
virtual ~UnmapBufferAction() {}
|
||||
|
||||
void *mMappedPtr;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "UnmapBuffer"; }
|
||||
};
|
||||
|
||||
class ReadImage2DAction : public Action
|
||||
{
|
||||
public:
|
||||
ReadImage2DAction() { mOutput = NULL; }
|
||||
virtual ~ReadImage2DAction() { free( mOutput ); }
|
||||
|
||||
clMemWrapper mImage;
|
||||
size_t mWidth, mHeight;
|
||||
void *mOutput;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "ReadImage2D"; }
|
||||
};
|
||||
|
||||
class ReadImage3DAction : public Action
|
||||
{
|
||||
public:
|
||||
ReadImage3DAction() { mOutput = NULL; }
|
||||
virtual ~ReadImage3DAction() { free( mOutput ); }
|
||||
|
||||
clMemWrapper mImage;
|
||||
size_t mWidth, mHeight, mDepth;
|
||||
void *mOutput;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "ReadImage3D"; }
|
||||
};
|
||||
|
||||
class WriteImage2DAction : public Action
|
||||
{
|
||||
public:
|
||||
clMemWrapper mImage;
|
||||
size_t mWidth, mHeight;
|
||||
void *mOutput;
|
||||
|
||||
WriteImage2DAction() { mOutput = NULL; }
|
||||
virtual ~WriteImage2DAction() { free( mOutput ); }
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "WriteImage2D"; }
|
||||
};
|
||||
|
||||
class WriteImage3DAction : public Action
|
||||
{
|
||||
public:
|
||||
clMemWrapper mImage;
|
||||
size_t mWidth, mHeight, mDepth;
|
||||
void *mOutput;
|
||||
|
||||
WriteImage3DAction() { mOutput = NULL; }
|
||||
virtual ~WriteImage3DAction() { free( mOutput ); }
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "WriteImage3D"; }
|
||||
};
|
||||
|
||||
class CopyImageAction : public Action
|
||||
{
|
||||
public:
|
||||
CopyImageAction() {}
|
||||
virtual ~CopyImageAction() {}
|
||||
|
||||
clMemWrapper mSrcImage, mDstImage;
|
||||
size_t mWidth, mHeight, mDepth;
|
||||
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
};
|
||||
|
||||
class CopyImage2Dto2DAction : public CopyImageAction
|
||||
{
|
||||
public:
|
||||
CopyImage2Dto2DAction() {}
|
||||
virtual ~CopyImage2Dto2DAction() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
|
||||
virtual const char * GetName( void ) const { return "CopyImage2Dto2D"; }
|
||||
};
|
||||
|
||||
class CopyImage2Dto3DAction : public CopyImageAction
|
||||
{
|
||||
public:
|
||||
CopyImage2Dto3DAction() {}
|
||||
virtual ~CopyImage2Dto3DAction() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
|
||||
virtual const char * GetName( void ) const { return "CopyImage2Dto3D"; }
|
||||
};
|
||||
|
||||
class CopyImage3Dto2DAction : public CopyImageAction
|
||||
{
|
||||
public:
|
||||
CopyImage3Dto2DAction() {}
|
||||
virtual ~CopyImage3Dto2DAction() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
|
||||
virtual const char * GetName( void ) const { return "CopyImage3Dto2D"; }
|
||||
};
|
||||
|
||||
class CopyImage3Dto3DAction : public CopyImageAction
|
||||
{
|
||||
public:
|
||||
CopyImage3Dto3DAction() {}
|
||||
virtual ~CopyImage3Dto3DAction() {}
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
|
||||
virtual const char * GetName( void ) const { return "CopyImage3Dto3D"; }
|
||||
};
|
||||
|
||||
class Copy2DImageToBufferAction : public Action
|
||||
{
|
||||
public:
|
||||
Copy2DImageToBufferAction() {}
|
||||
virtual ~Copy2DImageToBufferAction() {}
|
||||
|
||||
clMemWrapper mSrcImage, mDstBuffer;
|
||||
size_t mWidth, mHeight;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "Copy2DImageToBuffer"; }
|
||||
};
|
||||
|
||||
class Copy3DImageToBufferAction : public Action
|
||||
{
|
||||
public:
|
||||
Copy3DImageToBufferAction() {}
|
||||
virtual ~Copy3DImageToBufferAction() {}
|
||||
|
||||
clMemWrapper mSrcImage, mDstBuffer;
|
||||
size_t mWidth, mHeight, mDepth;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "Copy3DImageToBuffer"; }
|
||||
};
|
||||
|
||||
class CopyBufferTo2DImageAction : public Action
|
||||
{
|
||||
public:
|
||||
CopyBufferTo2DImageAction() {}
|
||||
virtual ~CopyBufferTo2DImageAction() {}
|
||||
|
||||
clMemWrapper mSrcBuffer, mDstImage;
|
||||
size_t mWidth, mHeight;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "CopyBufferTo2D"; }
|
||||
};
|
||||
|
||||
class CopyBufferTo3DImageAction : public Action
|
||||
{
|
||||
public:
|
||||
CopyBufferTo3DImageAction() {}
|
||||
virtual ~CopyBufferTo3DImageAction() {}
|
||||
|
||||
clMemWrapper mSrcBuffer, mDstImage;
|
||||
size_t mWidth, mHeight, mDepth;
|
||||
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "CopyBufferTo3D"; }
|
||||
};
|
||||
|
||||
class MapImageAction : public Action
|
||||
{
|
||||
public:
|
||||
MapImageAction() : mQueue(0) {}
|
||||
|
||||
clMemWrapper mImage;
|
||||
size_t mWidth, mHeight;
|
||||
void *mMappedPtr;
|
||||
cl_command_queue mQueue;
|
||||
|
||||
virtual ~MapImageAction();
|
||||
virtual cl_int Setup( cl_device_id device, cl_context context, cl_command_queue queue );
|
||||
virtual cl_int Execute( cl_command_queue queue, cl_uint numWaits, cl_event *waits, cl_event *outEvent );
|
||||
|
||||
virtual const char * GetName( void ) const { return "MapImage"; }
|
||||
};
|
||||
|
||||
|
||||
#endif // _action_classes_h
|
||||
108
test_conformance/events/main.c
Normal file
108
test_conformance/events/main.c
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// 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>
|
||||
#include "procs.h"
|
||||
#include "../../test_common/harness/testHarness.h"
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
basefn basefn_list[] = {
|
||||
test_event_get_execute_status,
|
||||
test_event_get_write_array_status,
|
||||
test_event_get_read_array_status,
|
||||
test_event_get_info,
|
||||
test_event_wait_for_execute,
|
||||
test_event_wait_for_array,
|
||||
test_event_flush,
|
||||
test_event_finish_execute,
|
||||
test_event_finish_array,
|
||||
test_event_release_before_done,
|
||||
test_event_enqueue_marker,
|
||||
#ifdef CL_VERSION_1_2
|
||||
test_event_enqueue_marker_with_list,
|
||||
test_event_enqueue_barrier_with_list,
|
||||
#endif
|
||||
|
||||
|
||||
test_event_waitlist_single_queue,
|
||||
test_event_waitlist_multi_queue,
|
||||
test_event_waitlist_multi_queue_multi_device,
|
||||
test_event_enqueue_wait_for_events_single_queue,
|
||||
test_event_enqueue_wait_for_events_multi_queue,
|
||||
test_event_enqueue_wait_for_events_multi_queue_multi_device,
|
||||
test_event_enqueue_marker_single_queue,
|
||||
test_event_enqueue_marker_multi_queue,
|
||||
test_event_enqueue_marker_multi_queue_multi_device,
|
||||
test_event_enqueue_barrier_single_queue,
|
||||
|
||||
test_waitlists,
|
||||
test_userevents,
|
||||
test_callbacks,
|
||||
test_callbacks_simultaneous,
|
||||
test_userevents_multithreaded,
|
||||
};
|
||||
|
||||
const char *basefn_names[] = {
|
||||
"event_get_execute_status",
|
||||
"event_get_write_array_status",
|
||||
"event_get_read_array_status",
|
||||
"event_get_info",
|
||||
"event_wait_for_execute",
|
||||
"event_wait_for_array",
|
||||
"event_flush",
|
||||
"event_finish_execute",
|
||||
"event_finish_array",
|
||||
"event_release_before_done",
|
||||
"event_enqueue_marker",
|
||||
#ifdef CL_VERSION_1_2
|
||||
"event_enqueue_marker_with_event_list",
|
||||
"event_enqueue_barrier_with_event_list",
|
||||
#endif
|
||||
|
||||
"out_of_order_event_waitlist_single_queue",
|
||||
"out_of_order_event_waitlist_multi_queue",
|
||||
"out_of_order_event_waitlist_multi_queue_multi_device",
|
||||
"out_of_order_event_enqueue_wait_for_events_single_queue",
|
||||
"out_of_order_event_enqueue_wait_for_events_multi_queue",
|
||||
"out_of_order_event_enqueue_wait_for_events_multi_queue_multi_device",
|
||||
"out_of_order_event_enqueue_marker_single_queue",
|
||||
"out_of_order_event_enqueue_marker_multi_queue",
|
||||
"out_of_order_event_enqueue_marker_multi_queue_multi_device",
|
||||
"out_of_order_event_enqueue_barrier_single_queue",
|
||||
|
||||
"waitlists",
|
||||
"test_userevents",
|
||||
|
||||
"callbacks",
|
||||
"callbacks_simultaneous",
|
||||
|
||||
"userevents_multithreaded",
|
||||
};
|
||||
|
||||
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[])
|
||||
{
|
||||
return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, false, 0 );
|
||||
}
|
||||
|
||||
|
||||
61
test_conformance/events/procs.h
Normal file
61
test_conformance/events/procs.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// 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/errorHelpers.h"
|
||||
#include "../../test_common/harness/kernelHelpers.h"
|
||||
#include "../../test_common/harness/typeWrappers.h"
|
||||
#include "../../test_common/harness/clImageHelper.h"
|
||||
|
||||
extern float random_float(float low, float high);
|
||||
extern float calculate_ulperror(float a, float b);
|
||||
|
||||
|
||||
extern int test_event_get_execute_status(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_get_write_array_status(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_get_read_array_status(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_get_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_wait_for_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_wait_for_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_flush(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_finish_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_finish_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_release_before_done(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_enqueue_marker(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
#ifdef CL_VERSION_1_2
|
||||
extern int test_event_enqueue_marker_with_list(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_enqueue_barrier_with_list(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
#endif
|
||||
|
||||
extern int test_event_waitlist_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_waitlist_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_waitlist_multi_queue_multi_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_event_enqueue_wait_for_events_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_enqueue_wait_for_events_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_enqueue_wait_for_events_multi_queue_multi_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_event_enqueue_barrier_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_event_enqueue_marker_single_queue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_enqueue_marker_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_event_enqueue_marker_multi_queue_multi_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_waitlists( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_userevents( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_callbacks( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_callbacks_simultaneous( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_userevents_multithreaded( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
|
||||
|
||||
31
test_conformance/events/testBase.h
Normal file
31
test_conformance/events/testBase.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef _testBase_h
|
||||
#define _testBase_h
|
||||
|
||||
#include "../../test_common/harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
#endif // _testBase_h
|
||||
|
||||
|
||||
|
||||
341
test_conformance/events/test_callbacks.cpp
Normal file
341
test_conformance/events/test_callbacks.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
//
|
||||
// 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 "action_classes.h"
|
||||
#include "../../test_common/harness/conversions.h"
|
||||
#include "../../test_common/harness/ThreadPool.h"
|
||||
|
||||
#if !defined (_MSC_VER)
|
||||
#include <unistd.h>
|
||||
#endif // !_MSC_VER
|
||||
|
||||
extern const char *IGetStatusString( cl_int status );
|
||||
|
||||
#define PRINT_OPS 0
|
||||
|
||||
// Yes, this is somewhat nasty, in that we're relying on the CPU (the real CPU, not the OpenCL device)
|
||||
// to be atomic w.r.t. boolean values. Although if it isn't, we'll just miss the check on this bool
|
||||
// until the next time around, so it's not that big of a deal. Ideally, we'd be using a semaphore with
|
||||
// a trywait on it, but then that introduces the fun issue of what to do on Win32, etc. This way is
|
||||
// far more portable, and worst case of failure is a slightly longer test run.
|
||||
static bool sCallbackTriggered = false;
|
||||
|
||||
|
||||
#define EVENT_CALLBACK_TYPE_TOTAL 3
|
||||
static bool sCallbackTriggered_flag[ EVENT_CALLBACK_TYPE_TOTAL ] ={ false,false, false };
|
||||
cl_int event_callback_types[EVENT_CALLBACK_TYPE_TOTAL] ={ CL_SUBMITTED, CL_RUNNING, CL_COMPLETE};
|
||||
|
||||
// Our callback function
|
||||
/*void CL_CALLBACK single_event_callback_function( cl_event event, cl_int commandStatus, void * userData )
|
||||
{
|
||||
int i=*static_cast<int *>(userData);
|
||||
log_info( "\tEvent callback %d triggered\n", i);
|
||||
sCallbackTriggered_flag [ i ] = true;
|
||||
}*/
|
||||
|
||||
/* use struct as call back para */
|
||||
typedef struct { cl_int enevt_type; int index; } CALL_BACK_USER_DATA;
|
||||
|
||||
void CL_CALLBACK single_event_callback_function_flags( cl_event event, cl_int commandStatus, void * userData )
|
||||
{
|
||||
// int i=*static_cast<int *>(userData);
|
||||
CALL_BACK_USER_DATA *pdata= static_cast<CALL_BACK_USER_DATA *>(userData);
|
||||
|
||||
log_info( "\tEvent callback %d of type %d triggered\n", pdata->index, pdata->enevt_type);
|
||||
sCallbackTriggered_flag [pdata->index ] = true;
|
||||
}
|
||||
|
||||
int test_callback_event_single( cl_device_id device, cl_context context, cl_command_queue queue, Action *actionToTest )
|
||||
{
|
||||
// Note: we don't use the waiting feature here. We just want to verify that we get a callback called
|
||||
// when the given event finishes
|
||||
|
||||
cl_int error = actionToTest->Setup( device, context, queue );
|
||||
test_error( error, "Unable to set up test action" );
|
||||
|
||||
// Set up a user event, which we use as a gate for the second event
|
||||
clEventWrapper gateEvent = clCreateUserEvent( context, &error );
|
||||
test_error( error, "Unable to set up user gate event" );
|
||||
|
||||
// Set up the execution of the action with its actual event
|
||||
clEventWrapper actualEvent;
|
||||
error = actionToTest->Execute( queue, 1, &gateEvent, &actualEvent );
|
||||
test_error( error, "Unable to set up action execution" );
|
||||
|
||||
// Set up the callback on the actual event
|
||||
|
||||
/* use struct as call back para */
|
||||
CALL_BACK_USER_DATA user_data[EVENT_CALLBACK_TYPE_TOTAL];
|
||||
int index [EVENT_CALLBACK_TYPE_TOTAL]={ 0,1,2};
|
||||
for( int i=0;i< EVENT_CALLBACK_TYPE_TOTAL; i++)
|
||||
{
|
||||
user_data[i].enevt_type=event_callback_types[i];
|
||||
user_data[i].index =i;
|
||||
error = clSetEventCallback( actualEvent, event_callback_types[i], single_event_callback_function_flags, user_data+i );
|
||||
|
||||
}
|
||||
|
||||
// Now release the user event, which will allow our actual action to run
|
||||
error = clSetUserEventStatus( gateEvent, CL_COMPLETE );
|
||||
test_error( error, "Unable to trigger gate event" );
|
||||
|
||||
// Now we wait for completion. Note that we can actually wait on the event itself, at least at first
|
||||
error = clWaitForEvents( 1, &actualEvent );
|
||||
test_error( error, "Unable to wait for actual test event" );
|
||||
|
||||
// Note: we can check our callback now, and it MIGHT have been triggered, but that's not guaranteed
|
||||
if( sCallbackTriggered )
|
||||
{
|
||||
// We're all good, so return success
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The callback has not yet been called, but that doesn't mean it won't be. So wait for it
|
||||
log_info( "\tWaiting for callback..." );
|
||||
fflush( stdout );
|
||||
for( int i = 0; i < 10 * 10; i++ )
|
||||
{
|
||||
usleep( 100000 ); // 1/10th second
|
||||
|
||||
int cc=0;
|
||||
for( int k=0;k< EVENT_CALLBACK_TYPE_TOTAL;k++)
|
||||
if (sCallbackTriggered_flag[k]) {
|
||||
cc++;
|
||||
}
|
||||
|
||||
if (cc== EVENT_CALLBACK_TYPE_TOTAL )
|
||||
{
|
||||
log_info( "\n" );
|
||||
return 0;
|
||||
}
|
||||
log_info( "." );
|
||||
fflush( stdout );
|
||||
}
|
||||
|
||||
// If we got here, we never got the callback
|
||||
log_error( "\nCallback not called within 10 seconds! (assuming failure)\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define TEST_ACTION( name ) \
|
||||
{ \
|
||||
name##Action action; \
|
||||
log_info( "-- Testing " #name "...\n" ); \
|
||||
if( ( error = test_callback_event_single( deviceID, context, queue, &action ) ) != CL_SUCCESS ) \
|
||||
retVal++; \
|
||||
clFinish( queue ); \
|
||||
}
|
||||
|
||||
int test_callbacks( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements )
|
||||
{
|
||||
cl_int error;
|
||||
int retVal = 0;
|
||||
|
||||
log_info( "\n" );
|
||||
|
||||
TEST_ACTION( NDRangeKernel )
|
||||
|
||||
TEST_ACTION( ReadBuffer )
|
||||
TEST_ACTION( WriteBuffer )
|
||||
TEST_ACTION( MapBuffer )
|
||||
TEST_ACTION( UnmapBuffer )
|
||||
|
||||
if( checkForImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED )
|
||||
{
|
||||
log_info( "\nNote: device does not support images. Skipping remainder of callback tests...\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ACTION( ReadImage2D )
|
||||
TEST_ACTION( WriteImage2D )
|
||||
TEST_ACTION( CopyImage2Dto2D )
|
||||
TEST_ACTION( Copy2DImageToBuffer )
|
||||
TEST_ACTION( CopyBufferTo2DImage )
|
||||
TEST_ACTION( MapImage )
|
||||
|
||||
if( checkFor3DImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED )
|
||||
log_info( "\nNote: device does not support 3D images. Skipping remainder of waitlist tests...\n" );
|
||||
else
|
||||
{
|
||||
TEST_ACTION( ReadImage3D )
|
||||
TEST_ACTION( WriteImage3D )
|
||||
TEST_ACTION( CopyImage2Dto3D )
|
||||
TEST_ACTION( CopyImage3Dto2D )
|
||||
TEST_ACTION( CopyImage3Dto3D )
|
||||
TEST_ACTION( Copy3DImageToBuffer )
|
||||
TEST_ACTION( CopyBufferTo3DImage )
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#define SIMUTANEOUS_ACTION_TOTAL 18
|
||||
static bool sSimultaneousFlags[ 54 ];// for 18 actions with 3 callback status
|
||||
static volatile int sSimultaneousCount;
|
||||
|
||||
Action * actions[ 19 ] = { 0 };
|
||||
|
||||
// Callback for the simultaneous tests
|
||||
void CL_CALLBACK simultaneous_event_callback_function( cl_event event, cl_int commandStatus, void * userData )
|
||||
{
|
||||
int eventIndex = (int)(size_t)userData;
|
||||
int actionIndex = eventIndex/EVENT_CALLBACK_TYPE_TOTAL;
|
||||
int statusIndex = eventIndex%EVENT_CALLBACK_TYPE_TOTAL;
|
||||
log_info( "\tEvent callback triggered for action %s callback type %s \n", actions[actionIndex]->GetName(), IGetStatusString(statusIndex) );
|
||||
sSimultaneousFlags[ actionIndex ] = true;
|
||||
ThreadPool_AtomicAdd(&sSimultaneousCount,1);
|
||||
}
|
||||
|
||||
int test_callbacks_simultaneous( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
// Unlike the singles test, in this one, we run a bunch of events all at once, to verify that
|
||||
// the callbacks do get called once-and-only-once for each event, even if the run out of order or
|
||||
// are dependent on each other
|
||||
|
||||
// First, the list of actions to run
|
||||
int actionCount = 0, index = 0;
|
||||
|
||||
actions[ index++ ] = new NDRangeKernelAction();
|
||||
actions[ index++ ] = new ReadBufferAction();
|
||||
actions[ index++ ] = new WriteBufferAction();
|
||||
actions[ index++ ] = new MapBufferAction();
|
||||
actions[ index++ ] = new UnmapBufferAction();
|
||||
|
||||
if( checkForImageSupport( deviceID ) != CL_IMAGE_FORMAT_NOT_SUPPORTED )
|
||||
{
|
||||
actions[ index++ ] = new ReadImage2DAction();
|
||||
actions[ index++ ] = new WriteImage2DAction();
|
||||
actions[ index++ ] = new CopyImage2Dto2DAction();
|
||||
actions[ index++ ] = new Copy2DImageToBufferAction();
|
||||
actions[ index++ ] = new CopyBufferTo2DImageAction();
|
||||
actions[ index++ ] = new MapImageAction();
|
||||
|
||||
if( checkFor3DImageSupport( deviceID ) != CL_IMAGE_FORMAT_NOT_SUPPORTED )
|
||||
{
|
||||
actions[ index++ ] = new ReadImage3DAction();
|
||||
actions[ index++ ] = new WriteImage3DAction();
|
||||
actions[ index++ ] = new CopyImage2Dto3DAction();
|
||||
actions[ index++ ] = new CopyImage3Dto2DAction();
|
||||
actions[ index++ ] = new CopyImage3Dto3DAction();
|
||||
actions[ index++ ] = new Copy3DImageToBufferAction();
|
||||
actions[ index++ ] = new CopyBufferTo3DImageAction();
|
||||
}
|
||||
}
|
||||
actionCount = index;
|
||||
actions[ index++ ] = NULL;
|
||||
|
||||
// Now set them all up
|
||||
log_info( "\tSetting up test events...\n" );
|
||||
for( index = 0; actions[ index ] != NULL; index++ )
|
||||
{
|
||||
error = actions[ index ]->Setup( deviceID, context, queue );
|
||||
test_error( error, "Unable to set up test action" );
|
||||
sSimultaneousFlags[ index ] = false;
|
||||
}
|
||||
sSimultaneousCount = 0;
|
||||
|
||||
// Set up the user event to start them all
|
||||
clEventWrapper gateEvent = clCreateUserEvent( context, &error );
|
||||
test_error( error, "Unable to set up user gate event" );
|
||||
|
||||
// Start executing, all tied to the gate event
|
||||
//clEventWrapper actionEvents[ 18 ];// current actionCount is 18
|
||||
clEventWrapper *actionEvents= new clEventWrapper[actionCount];
|
||||
if (actionEvents == NULL)
|
||||
{
|
||||
log_error(" memory error in test_callbacks_simultaneous \n");
|
||||
for (size_t i=0;i<(sizeof(actions)/sizeof(actions[0]));++i)
|
||||
if (actions[i]) delete actions[i];
|
||||
return -1;
|
||||
}
|
||||
|
||||
RandomSeed seed( gRandomSeed );
|
||||
for( index = 0; actions[ index ] != NULL; index++ )
|
||||
{
|
||||
// Randomly choose to wait on the gate, or wait on the previous event
|
||||
cl_event * eventPtr = &gateEvent;
|
||||
if( ( index > 0 ) && ( random_in_range( 0, 255, seed ) & 1 ) )
|
||||
eventPtr = &actionEvents[ index - 1 ];
|
||||
|
||||
error = actions[ index ]->Execute( queue, 1, eventPtr, &actionEvents[ index ] );
|
||||
test_error( error, "Unable to execute test action" );
|
||||
|
||||
|
||||
for( int k=0; k< EVENT_CALLBACK_TYPE_TOTAL; k++)
|
||||
{
|
||||
error = clSetEventCallback( actionEvents[index], event_callback_types[k], simultaneous_event_callback_function, (void *)(size_t)(index*EVENT_CALLBACK_TYPE_TOTAL+k ) );
|
||||
test_error( error, "Unable to set event callback function" );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int total_callbacks= actionCount * EVENT_CALLBACK_TYPE_TOTAL;
|
||||
|
||||
// Now release the user event, which will allow our actual action to run
|
||||
error = clSetUserEventStatus( gateEvent, CL_COMPLETE );
|
||||
test_error( error, "Unable to trigger gate event" );
|
||||
|
||||
// Wait on the actual action events now
|
||||
log_info( "\tWaiting for test completions...\n" );
|
||||
error = clWaitForEvents( actionCount, &actionEvents[ 0 ] );
|
||||
test_error( error, "Unable to wait for actual test events" );
|
||||
|
||||
// Note: we can check our callback now, and it MIGHT have been triggered, but that's not guaranteed
|
||||
int last_count = 0;
|
||||
if( ((last_count = sSimultaneousCount)) == total_callbacks)
|
||||
{
|
||||
// We're all good, so return success
|
||||
log_info( "\t%d of %d callbacks received\n", sSimultaneousCount, total_callbacks );
|
||||
|
||||
if (actionEvents) delete [] actionEvents;
|
||||
for (size_t i=0;i<(sizeof(actions)/sizeof(actions[0]));++i)
|
||||
if (actions[i]) delete actions[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We haven't gotten (all) of the callbacks, so wait for them
|
||||
log_info( "\tWe've only received %d of the %d callbacks we expected; waiting for more...\n", last_count, total_callbacks );
|
||||
|
||||
for( int i = 0; i < 10 * 10; i++ )
|
||||
{
|
||||
usleep( 100000 ); // 1/10th second
|
||||
if( ((last_count = sSimultaneousCount)) == total_callbacks )
|
||||
{
|
||||
// All of the callbacks were executed
|
||||
if (actionEvents) delete [] actionEvents;
|
||||
for (size_t i=0;i<(sizeof(actions)/sizeof(actions[0]));++i)
|
||||
if (actions[i]) delete actions[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, some of the callbacks did not occur in time
|
||||
log_error( "\nError: We only ever received %d of our %d callbacks!\n", last_count, total_callbacks );
|
||||
log_error( "Events that did not receive callbacks:\n" );
|
||||
for( index = 0; actions[ index ] != NULL; index++ )
|
||||
{
|
||||
if( !sSimultaneousFlags[ index ] )
|
||||
log_error( "\t%s\n", actions[ index ]->GetName() );
|
||||
}
|
||||
|
||||
if (actionEvents) delete [] actionEvents;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
509
test_conformance/events/test_event_dependencies.cpp
Normal file
509
test_conformance/events/test_event_dependencies.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "testBase.h"
|
||||
#include "../../test_common/harness/testHarness.h"
|
||||
|
||||
const char *write_kernels[] = {
|
||||
"__kernel void write_up(__global int *dst, int length)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
" dst[get_global_id(0)] *= 2;\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"__kernel void write_down(__global int *dst, int length)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
" dst[get_global_id(0)]--;\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
#define TEST_SIZE 10000
|
||||
#define TEST_COUNT 100
|
||||
#define RANDOMIZE 1
|
||||
#define DEBUG_OUT 0
|
||||
|
||||
/*
|
||||
Tests event dependencies by running two kernels that use the same buffer.
|
||||
If two_queues is set they are run in separate queues.
|
||||
If test_enqueue_wait_for_events is set then clEnqueueWaitForEvent is called between them.
|
||||
If test_barrier is set then clEnqueueBarrier is called between them (only for single queue).
|
||||
If neither are set, nothing is done to prevent them from executing in the wrong order. This can be used for verification.
|
||||
*/
|
||||
int test_event_enqueue_wait_for_events_run_test( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, int two_queues, int two_devices,
|
||||
int test_enqueue_wait_for_events, int test_barrier, int use_waitlist, int use_marker)
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
size_t threads[3] = {TEST_SIZE,0,0};
|
||||
int i, loop_count, event_count, expected_value, failed;
|
||||
int expected_if_only_queue[2];
|
||||
int max_count = TEST_SIZE;
|
||||
|
||||
cl_platform_id platform;
|
||||
cl_command_queue queues[2]; // Not a wrapper so we don't autorelease if they are the same
|
||||
clCommandQueueWrapper queueWrappers[2]; // If they are different, we use the wrapper so it will auto release
|
||||
clContextWrapper context_to_use;
|
||||
clMemWrapper data;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel1[TEST_COUNT], kernel2[TEST_COUNT];
|
||||
clEventWrapper event[TEST_COUNT*4+2]; // If we usemarkers we get 2 more events per iteration
|
||||
|
||||
if (test_enqueue_wait_for_events)
|
||||
log_info("\tTesting with clEnqueueBarrierWithWaitList as barrier function.\n");
|
||||
if (test_barrier)
|
||||
log_info("\tTesting with clEnqueueBarrierWithWaitList as barrier function.\n");
|
||||
if (use_waitlist)
|
||||
log_info("\tTesting with waitlist-based depenednecies between kernels.\n");
|
||||
if (use_marker)
|
||||
log_info("\tTesting with clEnqueueMarker as a barrier function.\n");
|
||||
if (test_barrier && (two_queues || two_devices)) {
|
||||
log_error("\tTest requested with clEnqueueBarrier across two queues. This is not a valid combination.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = clGetPlatformIDs(1, &platform, NULL);
|
||||
test_error(error, "clGetPlatformIDs failed.");
|
||||
|
||||
// If we are to use two devices, then get them and create a context with both.
|
||||
cl_device_id *two_device_ids;
|
||||
if (two_devices) {
|
||||
two_device_ids = (cl_device_id*)malloc(sizeof(cl_device_id)*2);
|
||||
cl_uint number_returned;
|
||||
error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 2, two_device_ids, &number_returned);
|
||||
test_error( error, "clGetDeviceIDs for CL_DEVICE_TYPE_ALL failed.");
|
||||
if (number_returned != 2) {
|
||||
log_info("Failed to obtain two devices. Test can not run.\n");
|
||||
free(two_device_ids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
cl_device_type type;
|
||||
error = clGetDeviceInfo(two_device_ids[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL);
|
||||
test_error( error, "clGetDeviceInfo failed.");
|
||||
if (type & CL_DEVICE_TYPE_CPU)
|
||||
log_info("\tDevice %d is CL_DEVICE_TYPE_CPU.\n", i);
|
||||
if (type & CL_DEVICE_TYPE_GPU)
|
||||
log_info("\tDevice %d is CL_DEVICE_TYPE_GPU.\n", i);
|
||||
if (type & CL_DEVICE_TYPE_ACCELERATOR)
|
||||
log_info("\tDevice %d is CL_DEVICE_TYPE_ACCELERATOR.\n", i);
|
||||
if (type & CL_DEVICE_TYPE_DEFAULT)
|
||||
log_info("\tDevice %d is CL_DEVICE_TYPE_DEFAULT.\n", i);
|
||||
}
|
||||
|
||||
context_to_use = clCreateContext(NULL, 2, two_device_ids, notify_callback, NULL, &error);
|
||||
test_error(error, "clCreateContext failed for two devices.");
|
||||
|
||||
log_info("\tTesting with two devices.\n");
|
||||
} else {
|
||||
context_to_use = clCreateContext(NULL, 1, &deviceID, NULL, NULL, &error);
|
||||
test_error(error, "clCreateContext failed for one device.");
|
||||
|
||||
log_info("\tTesting with one device.\n");
|
||||
}
|
||||
|
||||
// If we are using two queues then create them
|
||||
cl_queue_properties props[] = {CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0};
|
||||
if (two_queues) {
|
||||
// Get a second queue
|
||||
if (two_devices)
|
||||
{
|
||||
if( !checkDeviceForQueueSupport( two_device_ids[ 0 ], props[1] ) ||
|
||||
!checkDeviceForQueueSupport( two_device_ids[ 1 ], props[1] ) )
|
||||
{
|
||||
log_info( "WARNING: One or more device for multi-device test does not support out-of-order exec mode; skipping test.\n" );
|
||||
return -1942;
|
||||
}
|
||||
|
||||
queueWrappers[0] = clCreateCommandQueueWithProperties(context_to_use, two_device_ids[0], &props[0], &error);
|
||||
test_error(error, "clCreateCommandQueue for first queue on first device failed.");
|
||||
queueWrappers[1] = clCreateCommandQueueWithProperties(context_to_use, two_device_ids[1], &props[0], &error);
|
||||
test_error(error, "clCreateCommandQueue for second queue on second device failed.");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Single device has already been checked for out-of-order exec support
|
||||
queueWrappers[0] = clCreateCommandQueueWithProperties(context_to_use, deviceID, &props[0], &error);
|
||||
test_error(error, "clCreateCommandQueue for first queue failed.");
|
||||
queueWrappers[1] = clCreateCommandQueueWithProperties(context_to_use, deviceID, &props[0], &error);
|
||||
test_error(error, "clCreateCommandQueue for second queue failed.");
|
||||
}
|
||||
// Ugly hack to make sure we only have the wrapper auto-release if they are different queues
|
||||
queues[0] = queueWrappers[0];
|
||||
queues[1] = queueWrappers[1];
|
||||
log_info("\tTesting with two queues.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// (Note: single device has already been checked for out-of-order exec support)
|
||||
// Otherwise create one queue and have the second one be the same
|
||||
queueWrappers[0] = clCreateCommandQueueWithProperties(context_to_use, deviceID, &props[0], &error);
|
||||
test_error(error, "clCreateCommandQueue for first queue failed.");
|
||||
queues[0] = queueWrappers[0];
|
||||
queues[1] = (cl_command_queue)queues[0];
|
||||
log_info("\tTesting with one queue.\n");
|
||||
}
|
||||
|
||||
|
||||
// Setup - create a buffer and the two kernels
|
||||
data = clCreateBuffer(context_to_use, CL_MEM_READ_WRITE, TEST_SIZE*sizeof(cl_int), NULL, &error);
|
||||
test_error( error, "clCreateBuffer failed");
|
||||
|
||||
|
||||
// Initialize the values to zero
|
||||
cl_int *values = (cl_int*)malloc(TEST_SIZE*sizeof(cl_int));
|
||||
for (i=0; i<(int)TEST_SIZE; i++)
|
||||
values[i] = 0;
|
||||
error = clEnqueueWriteBuffer(queues[0], data, CL_TRUE, 0, TEST_SIZE*sizeof(cl_int), values, 0, NULL, NULL);
|
||||
test_error( error, "clEnqueueWriteBuffer failed");
|
||||
expected_value = 0;
|
||||
|
||||
// Build the kernels
|
||||
if (create_single_kernel_helper( context_to_use, &program, &kernel1[0], 1, write_kernels, "write_up" ))
|
||||
return -1;
|
||||
|
||||
error = clSetKernelArg(kernel1[0], 0, sizeof(data), &data);
|
||||
error |= clSetKernelArg(kernel1[0], 1, sizeof(max_count), &max_count);
|
||||
test_error( error, "clSetKernelArg 1 failed");
|
||||
|
||||
for (i=1; i<TEST_COUNT; i++) {
|
||||
kernel1[i] = clCreateKernel(program, "write_up", &error);
|
||||
test_error( error, "clCreateKernel 1 failed");
|
||||
|
||||
error = clSetKernelArg(kernel1[i], 0, sizeof(data), &data);
|
||||
error |= clSetKernelArg(kernel1[i], 1, sizeof(max_count), &max_count);
|
||||
test_error( error, "clSetKernelArg 1 failed");
|
||||
}
|
||||
|
||||
for (i=0; i<TEST_COUNT; i++) {
|
||||
kernel2[i] = clCreateKernel(program, "write_down", &error);
|
||||
test_error( error, "clCreateKernel 2 failed");
|
||||
|
||||
error = clSetKernelArg(kernel2[i], 0, sizeof(data), &data);
|
||||
error |= clSetKernelArg(kernel2[i], 1, sizeof(max_count), &max_count);
|
||||
test_error( error, "clSetKernelArg 2 failed");
|
||||
}
|
||||
|
||||
// Execution - run the first kernel, then enqueue the wait on the events, then the second kernel
|
||||
// If clEnqueueBarrierWithWaitList works, the buffer will be filled with 1s, then multiplied by 4s,
|
||||
// then incremented to 5s, repeatedly. Otherwise the values may be 2s (if the first one doesn't work) or 8s
|
||||
// (if the second one doesn't work).
|
||||
if (RANDOMIZE)
|
||||
log_info("Queues chosen randomly for each kernel exection.\n");
|
||||
else
|
||||
log_info("Queues chosen alternatily for each kernel execution.\n");
|
||||
|
||||
event_count = 0;
|
||||
for (i=0; i<(int)TEST_SIZE; i++)
|
||||
values[i] = 1;
|
||||
error = clEnqueueWriteBuffer(queues[0], data, CL_FALSE, 0, TEST_SIZE*sizeof(cl_int), values, 0, NULL, &event[event_count]);
|
||||
test_error( error, "clEnqueueWriteBuffer 2 failed");
|
||||
expected_value = 1;
|
||||
expected_if_only_queue[0] = 1;
|
||||
expected_if_only_queue[1] = 1;
|
||||
|
||||
int queue_to_use = 1;
|
||||
if (test_enqueue_wait_for_events) {
|
||||
error = clEnqueueBarrierWithWaitList(queues[queue_to_use], 1, &event[event_count], NULL );
|
||||
test_error( error, "Unable to queue wait for events" );
|
||||
} else if (test_barrier) {
|
||||
error = clEnqueueBarrierWithWaitList(queues[queue_to_use], 0, NULL, NULL);
|
||||
test_error( error, "Unable to queue barrier" );
|
||||
}
|
||||
|
||||
for (loop_count=0; loop_count<TEST_COUNT; loop_count++) {
|
||||
// Execute kernel 1
|
||||
event_count++;
|
||||
if (use_waitlist | use_marker) {
|
||||
if (DEBUG_OUT) log_info("clEnqueueNDRangeKernel(queues[%d], kernel1[%d], 1, NULL, threads, NULL, 1, &event[%d], &event[%d])\n", queue_to_use, loop_count, event_count-1, event_count);
|
||||
error = clEnqueueNDRangeKernel(queues[queue_to_use], kernel1[loop_count], 1, NULL, threads, NULL, 1, &event[event_count-1], &event[event_count]);
|
||||
} else {
|
||||
if (DEBUG_OUT) log_info("clEnqueueNDRangeKernel(queues[%d], kernel1[%d], 1, NULL, threads, NULL, 0, NULL, &event[%d])\n", queue_to_use, loop_count, event_count);
|
||||
error = clEnqueueNDRangeKernel(queues[queue_to_use], kernel1[loop_count], 1, NULL, threads, NULL, 0, NULL, &event[event_count]);
|
||||
}
|
||||
if (error) {
|
||||
log_info("\tLoop count %d\n", loop_count);
|
||||
print_error( error, "clEnqueueNDRangeKernel for kernel 1 failed");
|
||||
return error;
|
||||
}
|
||||
expected_value *= 2;
|
||||
expected_if_only_queue[queue_to_use] *= 2;
|
||||
|
||||
// If we are using a marker, it needs to go in the same queue
|
||||
if (use_marker) {
|
||||
event_count++;
|
||||
if (DEBUG_OUT) log_info("clEnqueueMarker(queues[%d], event[%d])\n", queue_to_use, event_count);
|
||||
|
||||
#ifdef CL_VERSION_1_2
|
||||
error = clEnqueueMarkerWithWaitList(queues[queue_to_use], 0, NULL, &event[event_count]);
|
||||
#else
|
||||
error = clEnqueueMarker(queues[queue_to_use], &event[event_count]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Pick the next queue to run
|
||||
if (RANDOMIZE)
|
||||
queue_to_use = rand()%2;
|
||||
else
|
||||
queue_to_use = (queue_to_use + 1)%2;
|
||||
|
||||
// Put in a barrier if requested
|
||||
if (test_enqueue_wait_for_events) {
|
||||
if (DEBUG_OUT) log_info("clEnqueueBarrierWithWaitList(queues[%d], 1, &event[%d], NULL)\n", queue_to_use, event_count);
|
||||
error = clEnqueueBarrierWithWaitList(queues[queue_to_use], 1, &event[event_count], NULL);
|
||||
test_error( error, "Unable to queue wait for events" );
|
||||
} else if (test_barrier) {
|
||||
if (DEBUG_OUT) log_info("clEnqueueBarrierWithWaitList(queues[%d])\n", queue_to_use);
|
||||
error = clEnqueueBarrierWithWaitList(queues[queue_to_use], 0, NULL, NULL);
|
||||
test_error( error, "Unable to queue barrier" );
|
||||
}
|
||||
|
||||
// Execute Kernel 2
|
||||
event_count++;
|
||||
if (use_waitlist | use_marker) {
|
||||
if (DEBUG_OUT) log_info("clEnqueueNDRangeKernel(queues[%d], kernel2[%d], 1, NULL, threads, NULL, 1, &event[%d], &event[%d])\n", queue_to_use, loop_count, event_count-1, event_count);
|
||||
error = clEnqueueNDRangeKernel(queues[queue_to_use], kernel2[loop_count], 1, NULL, threads, NULL, 1, &event[event_count-1], &event[event_count]);
|
||||
} else {
|
||||
if (DEBUG_OUT) log_info("clEnqueueNDRangeKernel(queues[%d], kernel2[%d], 1, NULL, threads, NULL, 0, NULL, &event[%d])\n", queue_to_use, loop_count, event_count);
|
||||
error = clEnqueueNDRangeKernel(queues[queue_to_use], kernel2[loop_count], 1, NULL, threads, NULL, 0, NULL, &event[event_count]);
|
||||
}
|
||||
if (error) {
|
||||
log_info("\tLoop count %d\n", loop_count);
|
||||
print_error( error, "clEnqueueNDRangeKernel for kernel 2 failed");
|
||||
return error;
|
||||
}
|
||||
expected_value--;
|
||||
expected_if_only_queue[queue_to_use]--;
|
||||
|
||||
// If we are using a marker, it needs to go in the same queue
|
||||
if (use_marker) {
|
||||
event_count++;
|
||||
if (DEBUG_OUT) log_info("clEnqueueMarker(queues[%d], event[%d])\n", queue_to_use, event_count);
|
||||
|
||||
#ifdef CL_VERSION_1_2
|
||||
error = clEnqueueMarkerWithWaitList(queues[queue_to_use], 0, NULL, &event[event_count]);
|
||||
#else
|
||||
error = clEnqueueMarker(queues[queue_to_use], &event[event_count]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Pick the next queue to run
|
||||
if (RANDOMIZE)
|
||||
queue_to_use = rand()%2;
|
||||
else
|
||||
queue_to_use = (queue_to_use + 1)%2;
|
||||
|
||||
// Put in a barrier if requested
|
||||
if (test_enqueue_wait_for_events) {
|
||||
if (DEBUG_OUT) log_info("clEnqueueBarrierWithWaitList(queues[%d], 1, &event[%d], NULL)\n", queue_to_use, event_count);
|
||||
error = clEnqueueBarrierWithWaitList(queues[queue_to_use], 1, &event[event_count], NULL );
|
||||
test_error( error, "Unable to queue wait for events" );
|
||||
} else if (test_barrier) {
|
||||
if (DEBUG_OUT) log_info("clEnqueueBarrierWithWaitList(queues[%d])\n", queue_to_use);
|
||||
error = clEnqueueBarrierWithWaitList(queues[queue_to_use], 0, NULL, NULL);
|
||||
test_error( error, "Unable to queue barrier" );
|
||||
}
|
||||
}
|
||||
|
||||
// Now finish up everything
|
||||
if (two_queues) {
|
||||
error = clFlush(queues[1]);
|
||||
test_error( error, "clFlush[1] failed");
|
||||
}
|
||||
|
||||
error = clEnqueueReadBuffer(queues[0], data, CL_TRUE, 0, TEST_SIZE*sizeof(cl_int), values, 1, &event[event_count], NULL);
|
||||
|
||||
test_error(error, "clEnqueueReadBuffer failed");
|
||||
|
||||
failed = 0;
|
||||
for (i=0; i<(int)TEST_SIZE; i++)
|
||||
if (values[i] != expected_value) {
|
||||
failed = 1;
|
||||
log_info("\tvalues[%d] = %d, expected %d (If only queue 1 accessed memory: %d only queue 2 accessed memory: %d)\n",
|
||||
i, values[i], expected_value, expected_if_only_queue[0], expected_if_only_queue[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
free(values);
|
||||
if (two_devices)
|
||||
free(two_device_ids);
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
int test( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements,
|
||||
int two_queues, int two_devices,
|
||||
int test_enqueue_wait_for_events, int test_barrier, int use_waitlists, int use_marker)
|
||||
{
|
||||
if( !checkDeviceForQueueSupport( deviceID, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE ) )
|
||||
{
|
||||
log_info( "WARNING: Device does not support out-of-order exec mode; skipping test.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("Running test for baseline results to determine if out-of-order execution can be detected...\n");
|
||||
int baseline_results = test_event_enqueue_wait_for_events_run_test(deviceID, context, queue, num_elements, two_queues, two_devices, 0, 0, 0, 0);
|
||||
if (baseline_results == 0) {
|
||||
if (test_enqueue_wait_for_events)
|
||||
log_info("WARNING: could not detect any out-of-order execution without using clEnqueueBarrierWithWaitList, so this test is not a valid test of out-of-order event dependencies.\n");
|
||||
if (test_barrier)
|
||||
log_info("WARNING: could not detect any out-of-order execution without using clEnqueueBarrierWithWaitList, so this test is not a valid test of out-of-order event dependencies.\n");
|
||||
if (use_waitlists)
|
||||
log_info("WARNING: could not detect any out-of-order execution without using waitlists, so this test is not a valid test of out-of-order event dependencies.\n");
|
||||
if (use_marker)
|
||||
log_info("WARNING: could not detect any out-of-order execution without using clEnqueueMarker, so this test is not a valid test of out-of-order event dependencies.\n");
|
||||
} else if (baseline_results == 1) {
|
||||
if (test_enqueue_wait_for_events)
|
||||
log_info("Detected incorrect execution (possibly out-of-order) without clEnqueueBarrierWithWaitList. Test can be a valid test of out-of-order event dependencies.\n");
|
||||
if (test_barrier)
|
||||
log_info("Detected incorrect execution (possibly out-of-order) without clEnqueueBarrierWithWaitList. Test can be a valid test of out-of-order event dependencies.\n");
|
||||
if (use_waitlists)
|
||||
log_info("Detected incorrect execution (possibly out-of-order) without waitlists. Test can be a valid test of out-of-order event dependencies.\n");
|
||||
if (use_marker)
|
||||
log_info("Detected incorrect execution (possibly out-of-order) without clEnqueueMarker. Test can be a valid test of out-of-order event dependencies.\n");
|
||||
} else if( baseline_results == -1942 ) {
|
||||
// Just ignore and return (out-of-order exec mode not supported)
|
||||
return 0;
|
||||
} else {
|
||||
print_error(baseline_results, "Baseline run failed");
|
||||
return baseline_results;
|
||||
}
|
||||
log_info("Running test for actual results...\n");
|
||||
return test_event_enqueue_wait_for_events_run_test(deviceID, context, queue, num_elements, two_queues, two_devices,
|
||||
test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
int test_event_waitlist_single_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 0;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 1;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
int test_event_waitlist_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 1;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 1;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
int test_event_waitlist_multi_queue_multi_device( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 1;
|
||||
int two_devices = 1;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 1;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
int test_event_enqueue_wait_for_events_single_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 0;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 1;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
int test_event_enqueue_wait_for_events_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 1;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 1;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
int test_event_enqueue_wait_for_events_multi_queue_multi_device( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 1;
|
||||
int two_devices = 1;
|
||||
int test_enqueue_wait_for_events = 1;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int test_event_enqueue_barrier_single_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 0;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 1;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 0;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
int test_event_enqueue_marker_single_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 0;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 1;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
int test_event_enqueue_marker_multi_queue( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 1;
|
||||
int two_devices = 0;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 1;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
int test_event_enqueue_marker_multi_queue_multi_device( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int two_queues = 1;
|
||||
int two_devices = 1;
|
||||
int test_enqueue_wait_for_events = 0;
|
||||
int test_barrier = 0;
|
||||
int use_waitlists = 0;
|
||||
int use_marker = 1;
|
||||
return test(deviceID, context, queue, num_elements, two_queues, two_devices, test_enqueue_wait_for_events, test_barrier, use_waitlists, use_marker);
|
||||
}
|
||||
|
||||
|
||||
682
test_conformance/events/test_events.cpp
Normal file
682
test_conformance/events/test_events.cpp
Normal file
@@ -0,0 +1,682 @@
|
||||
//
|
||||
// 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 "unistd.h" // for "sleep" used in the "while (1)" busy wait loop in
|
||||
#endif
|
||||
// test_event_flush
|
||||
|
||||
const char *sample_long_test_kernel[] = {
|
||||
"__kernel void sample_test(__global float *src, __global int *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
" int i;\n"
|
||||
"\n"
|
||||
" for( i = 0; i < 10000; i++ )\n"
|
||||
" {\n"
|
||||
" dst[tid] = (int)src[tid] * 3;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"}\n" };
|
||||
|
||||
int create_and_execute_kernel( cl_context inContext, cl_command_queue inQueue, cl_program *outProgram, cl_kernel *outKernel, cl_mem *streams,
|
||||
unsigned int lineCount, const char **lines, const char *kernelName, cl_event *outEvent )
|
||||
{
|
||||
size_t threads[1] = { 1000 }, localThreads[1];
|
||||
int error;
|
||||
|
||||
if( create_single_kernel_helper( inContext, outProgram, outKernel, lineCount, lines, kernelName ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = get_max_common_work_group_size( inContext, *outKernel, threads[0], &localThreads[0] );
|
||||
test_error( error, "Unable to get work group size to use" );
|
||||
|
||||
streams[0] = clCreateBuffer(inContext, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1000, NULL, &error);
|
||||
test_error( error, "Creating test array failed" );
|
||||
streams[1] = clCreateBuffer(inContext, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * 1000, NULL, &error);
|
||||
test_error( error, "Creating test array failed" );
|
||||
|
||||
/* Set the arguments */
|
||||
error = clSetKernelArg( *outKernel, 0, sizeof( streams[0] ), &streams[0] );
|
||||
test_error( error, "Unable to set kernel arguments" );
|
||||
error = clSetKernelArg( *outKernel, 1, sizeof( streams[1] ), &streams[1] );
|
||||
test_error( error, "Unable to set kernel arguments" );
|
||||
|
||||
error = clEnqueueNDRangeKernel(inQueue, *outKernel, 1, NULL, threads, localThreads, 0, NULL, outEvent);
|
||||
test_error( error, "Unable to execute test kernel" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SETUP_EVENT( c, q ) \
|
||||
clProgramWrapper program; \
|
||||
clKernelWrapper kernel; \
|
||||
clMemWrapper streams[2]; \
|
||||
clEventWrapper event; \
|
||||
int error; \
|
||||
if( create_and_execute_kernel( c, q, &program, &kernel, &streams[0], 1, sample_long_test_kernel, "sample_test", &event ) ) return -1;
|
||||
|
||||
#define FINISH_EVENT(_q) clFinish(_q)
|
||||
|
||||
const char *IGetStatusString( cl_int status )
|
||||
{
|
||||
static char tempString[ 128 ];
|
||||
switch( status )
|
||||
{
|
||||
case CL_COMPLETE: return "CL_COMPLETE";
|
||||
case CL_RUNNING: return "CL_RUNNING";
|
||||
case CL_QUEUED: return "CL_QUEUED";
|
||||
case CL_SUBMITTED: return "CL_SUBMITTED";
|
||||
default:
|
||||
sprintf( tempString, "<unknown: %d>", (int)status );
|
||||
return tempString;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: tests clGetEventStatus and clReleaseEvent (implicitly) */
|
||||
int test_event_get_execute_status( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
|
||||
/* Now wait for it to be done */
|
||||
error = clWaitForEvents( 1, &event );
|
||||
test_error( error, "Unable to wait for event" );
|
||||
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus to wait for event completion failed" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_get_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
SETUP_EVENT( context, queue );
|
||||
|
||||
/* Verify parameters of clGetEventInfo not already tested by other tests */
|
||||
cl_command_queue otherQueue;
|
||||
size_t size;
|
||||
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_QUEUE, sizeof( otherQueue ), &otherQueue, &size );
|
||||
test_error( error, "Unable to get event info!" );
|
||||
// We can not check if this is the right queue because this is an opaque object.
|
||||
if( size != sizeof( queue ) )
|
||||
{
|
||||
log_error( "ERROR: Returned command queue size does not validate (expected %d, got %d)\n", (int)sizeof( queue ), (int)size );
|
||||
return -1;
|
||||
}
|
||||
|
||||
cl_command_type type;
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_TYPE, sizeof( type ), &type, &size );
|
||||
test_error( error, "Unable to get event info!" );
|
||||
if( type != CL_COMMAND_NDRANGE_KERNEL )
|
||||
{
|
||||
log_error( "ERROR: Returned command type does not validate (expected %d, got %d)\n", (int)CL_COMMAND_NDRANGE_KERNEL, (int)type );
|
||||
return -1;
|
||||
}
|
||||
if( size != sizeof( type ) )
|
||||
{
|
||||
log_error( "ERROR: Returned command type size does not validate (expected %d, got %d)\n", (int)sizeof( type ), (int)size );
|
||||
return -1;
|
||||
}
|
||||
|
||||
cl_uint count;
|
||||
error = clGetEventInfo( event, CL_EVENT_REFERENCE_COUNT, sizeof( count ), &count, &size );
|
||||
test_error( error, "Unable to get event info for CL_EVENT_REFERENCE_COUNT!" );
|
||||
if( size != sizeof( count ) )
|
||||
{
|
||||
log_error( "ERROR: Returned command type size does not validate (expected %d, got %d)\n", (int)sizeof( type ), (int)size );
|
||||
return -1;
|
||||
}
|
||||
|
||||
cl_context testCtx;
|
||||
error = clGetEventInfo( event, CL_EVENT_CONTEXT, sizeof( testCtx ), &testCtx, &size );
|
||||
test_error( error, "Unable to get event context info!" );
|
||||
if( size != sizeof( context ) )
|
||||
{
|
||||
log_error( "ERROR: Returned context size does not validate (expected %d, got %d)\n", (int)sizeof( context ), (int)size );
|
||||
return -1;
|
||||
}
|
||||
if( testCtx != context )
|
||||
{
|
||||
log_error( "ERROR: Returned context does not match (expected %p, got %p)\n", (void *)context, (void *)testCtx );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_get_write_array_status( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem stream;
|
||||
cl_float testArray[ 1024 * 32 ];
|
||||
cl_event event;
|
||||
int error;
|
||||
cl_int status;
|
||||
|
||||
|
||||
stream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
|
||||
error = clEnqueueWriteBuffer(queue, stream, CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)testArray, 0, NULL, &event);
|
||||
test_error( error, "Unable to set testing kernel data" );
|
||||
|
||||
/* Now wait for it to be done */
|
||||
error = clWaitForEvents( 1, &event );
|
||||
test_error( error, "Unable to wait for event" );
|
||||
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus to wait for event completion failed" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array write complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
clReleaseMemObject( stream );
|
||||
clReleaseEvent( event );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_get_read_array_status( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem stream;
|
||||
cl_float testArray[ 1024 * 32 ];
|
||||
cl_event event;
|
||||
int error;
|
||||
cl_int status;
|
||||
|
||||
|
||||
stream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
|
||||
error = clEnqueueReadBuffer(queue, stream, CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)testArray, 0, NULL, &event);
|
||||
test_error( error, "Unable to get testing kernel data" );
|
||||
|
||||
|
||||
/* It should still be running... */
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
|
||||
if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE)
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array read (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now wait for it to be done */
|
||||
error = clWaitForEvents( 1, &event );
|
||||
test_error( error, "Unable to wait for event" );
|
||||
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus to wait for event completion failed" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array read complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
clReleaseMemObject( stream );
|
||||
clReleaseEvent( event );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clGetEventStatus not implemented yet */
|
||||
|
||||
int test_event_wait_for_execute( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
|
||||
/* Now we wait for it to be done, then test the status again */
|
||||
error = clWaitForEvents( 1, &event );
|
||||
test_error( error, "Unable to wait for execute event" );
|
||||
|
||||
/* Make sure it worked */
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_wait_for_array( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_float readArray[ 1024 * 32 ];
|
||||
cl_float writeArray[ 1024 * 32 ];
|
||||
cl_event events[2];
|
||||
int error;
|
||||
cl_int status;
|
||||
|
||||
|
||||
streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
|
||||
error = clEnqueueReadBuffer(queue, streams[0], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)readArray, 0, NULL, &events[0]);
|
||||
test_error( error, "Unable to read testing kernel data" );
|
||||
|
||||
error = clEnqueueWriteBuffer(queue, streams[1], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)writeArray, 0, NULL, &events[1]);
|
||||
test_error( error, "Unable to write testing kernel data" );
|
||||
|
||||
/* Both should still be running */
|
||||
error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE)
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array read (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE)
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array write (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now try waiting for both */
|
||||
error = clWaitForEvents( 2, events );
|
||||
test_error( error, "Unable to wait for array events" );
|
||||
|
||||
/* Double check status on both */
|
||||
error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array read complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array write complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
clReleaseMemObject( streams[0] );
|
||||
clReleaseMemObject( streams[1] );
|
||||
clReleaseEvent( events[0] );
|
||||
clReleaseEvent( events[1] );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_flush( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int loopCount = 0;
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
|
||||
/* Now flush. Note that we can't guarantee this actually lets the op finish, but we can guarantee it's no longer queued */
|
||||
error = clFlush( queue );
|
||||
test_error( error, "Unable to flush events" );
|
||||
|
||||
/* Make sure it worked */
|
||||
while (1) {
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS,
|
||||
sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
|
||||
if( status != CL_QUEUED )
|
||||
break;
|
||||
|
||||
#if ! defined( _WIN32 )
|
||||
sleep(1); // give it some time here.
|
||||
#else // _WIN32
|
||||
Sleep(1000);
|
||||
#endif
|
||||
++loopCount;
|
||||
}
|
||||
|
||||
/*
|
||||
CL_QUEUED (command has been enqueued in the command-queue),
|
||||
CL_SUBMITTED (enqueued command has been submitted by the host to the device associated with the command-queue),
|
||||
CL_RUNNING (device is currently executing this command),
|
||||
CL_COMPLETE (the command has completed), or
|
||||
Error code given by a negative integer value. (command was abnormally terminated – this may be caused by a bad memory access etc.).
|
||||
*/
|
||||
if(status != CL_COMPLETE && status != CL_SUBMITTED &&
|
||||
status != CL_RUNNING && status != CL_COMPLETE)
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event flush (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now wait */
|
||||
error = clFinish( queue );
|
||||
test_error( error, "Unable to finish events" );
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int test_event_finish_execute( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
|
||||
/* Now flush and finish all ops */
|
||||
error = clFinish( queue );
|
||||
test_error( error, "Unable to finish all events" );
|
||||
|
||||
/* Make sure it worked */
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after event complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_finish_array( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_float readArray[ 1024 * 32 ];
|
||||
cl_float writeArray[ 1024 * 32 ];
|
||||
cl_event events[2];
|
||||
int error;
|
||||
cl_int status;
|
||||
|
||||
|
||||
streams[0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
streams[1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * 1024 * 32, NULL, &error );
|
||||
test_error( error, "Creating test array failed" );
|
||||
|
||||
error = clEnqueueReadBuffer(queue, streams[0], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)readArray, 0, NULL, &events[0]);
|
||||
test_error( error, "Unable to read testing kernel data" );
|
||||
|
||||
error = clEnqueueWriteBuffer(queue, streams[1], CL_FALSE, 0, sizeof(cl_float)*1024*32, (void *)writeArray, 0, NULL, &events[1]);
|
||||
test_error( error, "Unable to write testing kernel data" );
|
||||
|
||||
/* Both should still be running */
|
||||
error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE)
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array read (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_RUNNING && status != CL_QUEUED && status != CL_SUBMITTED && status != CL_COMPLETE)
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus during array write (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now try finishing all ops */
|
||||
error = clFinish( queue );
|
||||
test_error( error, "Unable to finish all events" );
|
||||
|
||||
/* Double check status on both */
|
||||
error = clGetEventInfo( events[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array read complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = clGetEventInfo( events[1], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventStatus didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetErrorStatus after array write complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
clReleaseMemObject( streams[0] );
|
||||
clReleaseMemObject( streams[1] );
|
||||
clReleaseEvent( events[0] );
|
||||
clReleaseEvent( events[1] );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define NUM_EVENT_RUNS 100
|
||||
|
||||
int test_event_release_before_done( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
// Create a kernel to run
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel[NUM_EVENT_RUNS];
|
||||
size_t threads[1] = { 1000 };
|
||||
cl_event events[NUM_EVENT_RUNS];
|
||||
cl_int status;
|
||||
clMemWrapper streams[NUM_EVENT_RUNS][2];
|
||||
int error, i;
|
||||
|
||||
// Create a kernel
|
||||
if( create_single_kernel_helper( context, &program, &kernel[0], 1, sample_long_test_kernel, "sample_test" ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i = 1; i < NUM_EVENT_RUNS; i++ ) {
|
||||
kernel[i] = clCreateKernel(program, "sample_test", &error);
|
||||
test_error(error, "Unable to create kernel");
|
||||
}
|
||||
|
||||
error = get_max_common_work_group_size( context, kernel[0], 1024, &threads[0] );
|
||||
test_error( error, "Unable to get work group size to use" );
|
||||
|
||||
// Create a set of streams to use as arguments
|
||||
for( i = 0; i < NUM_EVENT_RUNS; i++ )
|
||||
{
|
||||
streams[i][0] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float) * threads[0], NULL, &error );
|
||||
streams[i][1] = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * threads[0], NULL, &error );
|
||||
if( ( streams[i][0] == NULL ) || ( streams[i][1] == NULL ) )
|
||||
{
|
||||
log_error( "ERROR: Unable to allocate testing streams" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the kernels one by one, hopefully making sure they won't be done by the time we get to the end
|
||||
for( i = 0; i < NUM_EVENT_RUNS; i++ )
|
||||
{
|
||||
error = clSetKernelArg( kernel[i], 0, sizeof( cl_mem ), &streams[i][0] );
|
||||
error |= clSetKernelArg( kernel[i], 1, sizeof( cl_mem ), &streams[i][1] );
|
||||
test_error( error, "Unable to set kernel arguments" );
|
||||
|
||||
error = clEnqueueNDRangeKernel( queue, kernel[i], 1, NULL, threads, threads, 0, NULL, &events[i]);
|
||||
test_error( error, "Unable to execute test kernel" );
|
||||
}
|
||||
|
||||
// Free all but the last event
|
||||
for( i = 0; i < NUM_EVENT_RUNS - 1; i++ )
|
||||
{
|
||||
clReleaseEvent( events[ i ] );
|
||||
}
|
||||
|
||||
// Get status on the last one, then free it
|
||||
error = clGetEventInfo( events[ NUM_EVENT_RUNS - 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
|
||||
clReleaseEvent( events[ NUM_EVENT_RUNS - 1 ] );
|
||||
|
||||
// Was the status still-running?
|
||||
if( status == CL_COMPLETE )
|
||||
{
|
||||
log_info( "WARNING: Events completed before they could be released, so test is a null-op. Increase workload and try again." );
|
||||
}
|
||||
else if( status == CL_RUNNING || status == CL_QUEUED || status == CL_SUBMITTED )
|
||||
{
|
||||
log_info( "Note: Event status was running or queued when released, so test was good.\n" );
|
||||
}
|
||||
|
||||
// If we didn't crash by now, the test succeeded
|
||||
clFinish( queue );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_enqueue_marker( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
|
||||
/* Now we queue a marker and wait for that, which--since it queues afterwards--should guarantee the execute finishes too */
|
||||
clEventWrapper markerEvent;
|
||||
//error = clEnqueueMarker( queue, &markerEvent );
|
||||
|
||||
#ifdef CL_VERSION_1_2
|
||||
error = clEnqueueMarkerWithWaitList(queue, 0, NULL, &markerEvent );
|
||||
#else
|
||||
error = clEnqueueMarker( queue, &markerEvent );
|
||||
#endif
|
||||
test_error( error, "Unable to queue marker" );
|
||||
/* Now we wait for it to be done, then test the status again */
|
||||
error = clWaitForEvents( 1, &markerEvent );
|
||||
test_error( error, "Unable to wait for marker event" );
|
||||
|
||||
/* Check the status of the first event */
|
||||
error = clGetEventInfo( event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status ), &status, NULL );
|
||||
test_error( error, "Calling clGetEventInfo didn't work!" );
|
||||
if( status != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Incorrect status returned from clGetEventInfo after event complete (%d:%s)\n", status, IGetStatusString( status ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CL_VERSION_1_2
|
||||
int test_event_enqueue_marker_with_list( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
cl_event event_list[3]={ NULL, NULL, NULL};
|
||||
|
||||
size_t threads[1] = { 10 }, localThreads[1]={1};
|
||||
cl_uint event_count=2;
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList 1 " );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList 2" );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, NULL);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList 3" );
|
||||
|
||||
// test the case event returned
|
||||
error =clEnqueueMarkerWithWaitList(queue, event_count, event_list, &event_list[2]);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList " );
|
||||
|
||||
error = clReleaseEvent(event_list[0]);
|
||||
error |= clReleaseEvent(event_list[1]);
|
||||
test_error( error, "clReleaseEvent" );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList 1 -1 " );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList 2-2" );
|
||||
|
||||
// test the case event =NULL, caused [CL_INVALID_VALUE] : OpenCL Error : clEnqueueMarkerWithWaitList failed: event is a NULL value
|
||||
error =clEnqueueMarkerWithWaitList(queue, event_count, event_list, NULL);
|
||||
test_error( error, " clEnqueueMarkerWithWaitList " );
|
||||
|
||||
error = clReleaseEvent(event_list[0]);
|
||||
error |= clReleaseEvent(event_list[1]);
|
||||
error |= clReleaseEvent(event_list[2]);
|
||||
test_error( error, "clReleaseEvent" );
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CL_VERSION_1_2
|
||||
int test_event_enqueue_barrier_with_list( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
|
||||
cl_int status;
|
||||
SETUP_EVENT( context, queue );
|
||||
cl_event event_list[3]={ NULL, NULL, NULL};
|
||||
|
||||
size_t threads[1] = { 10 }, localThreads[1]={1};
|
||||
cl_uint event_count=2;
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList 1 " );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList 2" );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, NULL);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList 20" );
|
||||
|
||||
// test the case event returned
|
||||
error =clEnqueueBarrierWithWaitList(queue, event_count, event_list, &event_list[2]);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList " );
|
||||
|
||||
clReleaseEvent(event_list[0]);
|
||||
clReleaseEvent(event_list[1]);
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[0]);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList 1 " );
|
||||
|
||||
error= clEnqueueNDRangeKernel( queue,kernel,1,NULL, threads, localThreads, 0, NULL, &event_list[1]);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList 2" );
|
||||
|
||||
// test the case event =NULL, caused [CL_INVALID_VALUE] : OpenCL Error : clEnqueueMarkerWithWaitList failed: event is a NULL value
|
||||
error = clEnqueueBarrierWithWaitList(queue, event_count, event_list, NULL);
|
||||
test_error( error, " clEnqueueBarrierWithWaitList " );
|
||||
|
||||
clReleaseEvent(event_list[0]);
|
||||
clReleaseEvent(event_list[1]);
|
||||
clReleaseEvent(event_list[2]);
|
||||
|
||||
FINISH_EVENT(queue);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
293
test_conformance/events/test_userevents.cpp
Normal file
293
test_conformance/events/test_userevents.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenCL/opencl.h>
|
||||
#include <mach/mach_time.h>
|
||||
#else
|
||||
#include <CL/cl.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../../test_common/harness/kernelHelpers.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ATF performance framework.
|
||||
|
||||
#if USE_ATF
|
||||
#include <ATF/ATF.h>
|
||||
#define test_start() ATFTestStart()
|
||||
#define log_perf(_number, _higherBetter, _numType, _format, ...) ATFLogPerformanceNumber(_number, _higherBetter, _numType, _format,##__VA_ARGS__)
|
||||
#define log_info ATFLogInfo
|
||||
#define log_error ATFLogError
|
||||
#define log_no_atf
|
||||
#define test_finish() ATFTestFinish()
|
||||
#else
|
||||
#define test_start()
|
||||
#define log_perf(_number, _higherBetter, _numType, _format, ...) printf("Performance Number " _format " (in %s, %s): %g\n",##__VA_ARGS__, _numType, _higherBetter?"higher is better":"lower is better" , _number)
|
||||
#define log_info(...) fprintf(stdout, ## __VA_ARGS__ )
|
||||
#define log_error(...) fprintf(stderr, ## __VA_ARGS__ )
|
||||
#define log_info_no_atf(...) log_info(## __VA_ARGS__ )
|
||||
#define test_finish()
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CL error checking.
|
||||
|
||||
#define CL_DEVICE_TYPE_ENV_MUST_BE( bitfield_ )\
|
||||
{\
|
||||
cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT;\
|
||||
const char* device_env = getenv("CL_DEVICE_TYPE");\
|
||||
if (device_env != NULL) {\
|
||||
if (!strcmp( device_env, "gpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_GPU" ))\
|
||||
device_type = CL_DEVICE_TYPE_GPU;\
|
||||
else if(!strcmp( device_env, "cpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_CPU" ))\
|
||||
device_type = CL_DEVICE_TYPE_CPU;\
|
||||
else if(!strcmp( device_env, "default" ) || !strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ))\
|
||||
device_type = CL_DEVICE_TYPE_DEFAULT;\
|
||||
if (!(device_type & bitfield_)) {\
|
||||
log_error( "CL_DEVICE_TYPE environment variable \"%s\" must be \"%s\".", device_env, #bitfield_ );\
|
||||
abort();\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define CL_DEVICE_TYPE_ENV( device_type_ )\
|
||||
{\
|
||||
const char* device_env = getenv("CL_DEVICE_TYPE");\
|
||||
if (device_env != NULL) {\
|
||||
if (!strcmp( device_env, "gpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_GPU" ))\
|
||||
device_type_ = CL_DEVICE_TYPE_GPU;\
|
||||
else if(!strcmp( device_env, "cpu" ) || !strcmp( device_env, "CL_DEVICE_TYPE_CPU" ))\
|
||||
device_type_ = CL_DEVICE_TYPE_CPU;\
|
||||
else if(!strcmp( device_env, "default" ) || !strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ))\
|
||||
device_type_ = CL_DEVICE_TYPE_DEFAULT;\
|
||||
}\
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define CL_EXIT_ERROR(cmd,...) \
|
||||
{ \
|
||||
if ((cmd) != CL_SUCCESS) { \
|
||||
log_error("CL ERROR: %s %u: ", __FILE__,__LINE__);\
|
||||
log_error(## __VA_ARGS__ );\
|
||||
log_error("\n");\
|
||||
return -1;\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define CL_EXIT_ERROR(cmd,format,...) \
|
||||
{ \
|
||||
if ((cmd) != CL_SUCCESS) { \
|
||||
log_error("CL ERROR: %s %u: ", __FILE__,__LINE__);\
|
||||
log_error(format,## __VA_ARGS__ );\
|
||||
log_error("\n");\
|
||||
return -1;\
|
||||
}\
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CL_EXIT_BUILD_ERROR(cmd,program,format,...) \
|
||||
{ \
|
||||
if ((cmd) != CL_SUCCESS) { \
|
||||
cl_uint num_devices_;\
|
||||
clGetProgramInfo(program,CL_PROGRAM_NUM_DEVICES,sizeof(num_devices_),&num_devices_,NULL);\
|
||||
cl_device_id *device_list;\
|
||||
device_list=(cl_device_id *)malloc(num_devices_*sizeof(cl_device_id));\
|
||||
clGetProgramInfo(program,CL_PROGRAM_DEVICES,num_devices_*sizeof(cl_device_id),device_list,NULL);\
|
||||
for (unsigned i=0;i<num_devices_;++i) {\
|
||||
size_t len;\
|
||||
char buffer[2048];\
|
||||
clGetProgramBuildInfo(program,device_list[i],CL_PROGRAM_BUILD_LOG,sizeof(buffer),buffer,&len);\
|
||||
log_error("DEVICE %u CL BUILD ERROR: %s(%u): ",i,__FILE__,__LINE__);\
|
||||
log_error(format,## __VA_ARGS__ );\
|
||||
log_error("\n");\
|
||||
}\
|
||||
free(device_list);\
|
||||
return -1;\
|
||||
}\
|
||||
}
|
||||
|
||||
const char* src[] = {
|
||||
"__kernel void simple_task(__global float* output) {\n"
|
||||
" output[0] += 1;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
enum { MaxDevices = 8 };
|
||||
|
||||
int test_userevents( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
|
||||
cl_int err;
|
||||
|
||||
cl_event u1 = clCreateUserEvent( context, &err );
|
||||
CL_EXIT_ERROR(err,"clCreateUserEvent failed");
|
||||
|
||||
// Test event properties.
|
||||
cl_int s;
|
||||
size_t sizeofs;
|
||||
CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof s, &s, &sizeofs),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((sizeof s == sizeofs) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_COMMAND_EXECUTION_STATUS");
|
||||
CL_EXIT_ERROR((s == CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_COMMAND_EXECUTION_STATUS");
|
||||
|
||||
cl_command_type t;
|
||||
size_t sizeoft;
|
||||
CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_TYPE, sizeof t, &t, &sizeoft),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((sizeof t == sizeoft) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_COMMAND_TYPE");
|
||||
CL_EXIT_ERROR((t == CL_COMMAND_USER) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_COMMAND_TYPE");
|
||||
|
||||
cl_command_queue q;
|
||||
size_t sizeofq;
|
||||
CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_QUEUE, sizeof q, &q, &sizeofq),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((sizeof q == sizeofq) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_COMMAND_QUEUE");
|
||||
CL_EXIT_ERROR((q == NULL) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_COMMAND_QUEUE");
|
||||
|
||||
cl_context c;
|
||||
size_t sizeofc;
|
||||
CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_CONTEXT, sizeof c, &c, &sizeofc),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((sizeof c == sizeofc) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_CONTEXT");
|
||||
CL_EXIT_ERROR((c == context) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_CONTEXT");
|
||||
|
||||
cl_ulong p;
|
||||
err = clGetEventProfilingInfo(u1,CL_PROFILING_COMMAND_QUEUED,sizeof p,&p,0);
|
||||
CL_EXIT_ERROR((err != CL_SUCCESS) ? CL_SUCCESS : -1,"clGetEventProfilingInfo returned wrong error.");
|
||||
|
||||
// Test semantics.
|
||||
cl_program program;
|
||||
err = create_single_kernel_helper_create_program(context, &program, 1, src);
|
||||
CL_EXIT_ERROR(err,"clCreateProgramWithSource failed");
|
||||
|
||||
CL_EXIT_BUILD_ERROR(clBuildProgram(program,0,NULL,"",NULL,NULL),program,"Building program from inline src:\t%s",src[0]);
|
||||
|
||||
cl_kernel k0 = clCreateKernel(program,"simple_task",&err);
|
||||
CL_EXIT_ERROR(err,"clCreateKernel failed");
|
||||
|
||||
float buffer[1];
|
||||
cl_mem output = clCreateBuffer(context,CL_MEM_USE_HOST_PTR,sizeof buffer, buffer, &err);
|
||||
CL_EXIT_ERROR(err,"clCreateBuffer failed.");
|
||||
|
||||
CL_EXIT_ERROR(clSetKernelArg(k0,0,sizeof(output),&output),"clSetKernelArg failed");
|
||||
|
||||
|
||||
// Successful case. //////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
cl_event e[4];
|
||||
cl_uint N = sizeof e / sizeof(cl_event);
|
||||
|
||||
log_info("Enqueuing tasks\n");
|
||||
for (cl_uint i = 0; i != N; ++i)
|
||||
CL_EXIT_ERROR(clEnqueueTask(queue,k0,1,&u1,&e[i]),"clEnqueueTaskFailed");
|
||||
|
||||
log_info("Checking task status before setting user event status\n");
|
||||
for (cl_uint i = 0; i != N; ++i) {
|
||||
CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((s >= CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status before user event",i);
|
||||
}
|
||||
|
||||
log_info("Setting user event status to complete\n");
|
||||
CL_EXIT_ERROR(clSetUserEventStatus(u1,CL_COMPLETE),"clSetUserEventStatus failed");
|
||||
|
||||
log_info("Waiting for tasks to finish executing\n");
|
||||
CL_EXIT_ERROR(clWaitForEvents( 1, &e[N-1] ),"clWaitForEvent failed");
|
||||
|
||||
log_info("Checking task status after setting user event status\n");
|
||||
for (cl_uint i = 0; i != N; ++i) {
|
||||
CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %04x after successful user event",i,s);
|
||||
}
|
||||
|
||||
CL_EXIT_ERROR(clReleaseEvent(u1),"clReleaseEvent failed");
|
||||
|
||||
for (cl_uint i = 0; i != N; ++i)
|
||||
CL_EXIT_ERROR(clReleaseEvent(e[i]),"clReleaseEvent failed");
|
||||
|
||||
log_info("Successful user event case passed.\n");
|
||||
|
||||
}
|
||||
|
||||
// Test unsuccessful user event case. ///////////////////////////////////////////////////////////////////
|
||||
{
|
||||
cl_event u2 = clCreateUserEvent( context, &err );
|
||||
CL_EXIT_ERROR(err,"clCreateUserEvent failed");
|
||||
|
||||
cl_event e[4];
|
||||
cl_uint N = sizeof e / sizeof(cl_event);
|
||||
|
||||
log_info("Enqueuing tasks\n");
|
||||
for (cl_uint i = 0; i != N; ++i)
|
||||
CL_EXIT_ERROR(clEnqueueTask(queue,k0,1,&u2,&e[i]),"clEnqueueTaskFailed");
|
||||
|
||||
log_info("Checking task status before setting user event status\n");
|
||||
for (cl_uint i = 0; i != N; ++i) {
|
||||
CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((s == CL_QUEUED || s == CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %d before user event",i, (int) s);
|
||||
}
|
||||
|
||||
log_info("Setting user event status to unsuccessful result\n");
|
||||
CL_EXIT_ERROR(clSetUserEventStatus(u2,-1),"clSetUserEventStatus failed");
|
||||
|
||||
log_info("Waiting for tasks to finish executing\n");
|
||||
CL_EXIT_ERROR((clWaitForEvents( N, &e[0] )!=CL_SUCCESS) ? CL_SUCCESS : -1,"clWaitForEvent succeeded when it should have failed");
|
||||
|
||||
log_info("Checking task status after setting user event status\n");
|
||||
for (cl_uint i = 0; i != N; ++i) {
|
||||
CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
|
||||
CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %04x after unsuccessful user event",i,s);
|
||||
}
|
||||
|
||||
CL_EXIT_ERROR(clReleaseEvent(u2),"clReleaseEvent failed");
|
||||
|
||||
for (cl_uint i = 0; i != N; ++i)
|
||||
CL_EXIT_ERROR(clReleaseEvent(e[i]),"clReleaseEvent failed");
|
||||
|
||||
log_info("Unsuccessful user event case passed.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
cl_int err;
|
||||
|
||||
test_start();
|
||||
|
||||
cl_device_type device_type;
|
||||
CL_DEVICE_TYPE_ENV( device_type );
|
||||
|
||||
cl_device_id device_id;
|
||||
CL_EXIT_ERROR(clGetDeviceIDs(NULL, device_type, 1, &device_id, NULL),"GetDeviceIDs");
|
||||
|
||||
// Create a context.
|
||||
cl_context context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
|
||||
CL_EXIT_ERROR(err,"CreateContext");
|
||||
|
||||
// Create a command queue.
|
||||
q = clCreateCommandQueueWithProperties(context,device_id,0,&err);
|
||||
CL_EXIT_ERROR(err,"clCreateCommandQueue failed");
|
||||
|
||||
int ret = test_userevents( device_type, context, queue, 0 );
|
||||
|
||||
test_finish();
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
82
test_conformance/events/test_userevents_multithreaded.cpp
Normal file
82
test_conformance/events/test_userevents_multithreaded.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// 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 "action_classes.h"
|
||||
#include "../../test_common/harness/conversions.h"
|
||||
#include "../../test_common/harness/genericThread.h"
|
||||
|
||||
#if !defined (_MSC_VER)
|
||||
#include <unistd.h>
|
||||
#endif // !_MSC_VER
|
||||
|
||||
class releaseEvent_thread : public genericThread
|
||||
{
|
||||
public:
|
||||
releaseEvent_thread( cl_event *event ) : mEvent( event ) {}
|
||||
|
||||
cl_event * mEvent;
|
||||
|
||||
protected:
|
||||
virtual void * IRun( void )
|
||||
{
|
||||
usleep( 1000000 );
|
||||
log_info( "\tTriggering gate from separate thread...\n" );
|
||||
clSetUserEventStatus( *mEvent, CL_COMPLETE );
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
int test_userevents_multithreaded( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements )
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
||||
// Set up a user event to act as a gate
|
||||
clEventWrapper gateEvent = clCreateUserEvent( context, &error );
|
||||
test_error( error, "Unable to create user gate event" );
|
||||
|
||||
// Set up a few actions gated on the user event
|
||||
NDRangeKernelAction action1;
|
||||
ReadBufferAction action2;
|
||||
WriteBufferAction action3;
|
||||
|
||||
clEventWrapper actionEvents[ 3 ];
|
||||
Action * actions[] = { &action1, &action2, &action3, NULL };
|
||||
|
||||
for( int i = 0; actions[ i ] != NULL; i++ )
|
||||
{
|
||||
error = actions[ i ]->Setup( deviceID, context, queue );
|
||||
test_error( error, "Unable to set up test action" );
|
||||
|
||||
error = actions[ i ]->Execute( queue, 1, &gateEvent, &actionEvents[ i ] );
|
||||
test_error( error, "Unable to execute test action" );
|
||||
}
|
||||
|
||||
// Now, instead of releasing the gate, we spawn a separate thread to do so
|
||||
releaseEvent_thread thread( &gateEvent );
|
||||
log_info( "\tStarting trigger thread...\n" );
|
||||
thread.Start();
|
||||
|
||||
log_info( "\tWaiting for actions...\n" );
|
||||
error = clWaitForEvents( 3, &actionEvents[ 0 ] );
|
||||
test_error( error, "Unable to wait for action events" );
|
||||
|
||||
log_info( "\tActions completed.\n" );
|
||||
|
||||
// If we got here without error, we're good
|
||||
return 0;
|
||||
}
|
||||
|
||||
322
test_conformance/events/test_waitlists.cpp
Normal file
322
test_conformance/events/test_waitlists.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//
|
||||
// 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 "action_classes.h"
|
||||
|
||||
|
||||
extern const char *IGetStatusString( cl_int status );
|
||||
|
||||
#define PRINT_OPS 0
|
||||
|
||||
int test_waitlist( cl_device_id device, cl_context context, cl_command_queue queue, Action *actionToTest, bool multiple )
|
||||
{
|
||||
NDRangeKernelAction actions[ 2 ];
|
||||
clEventWrapper events[ 3 ];
|
||||
cl_int status[ 3 ];
|
||||
cl_int error;
|
||||
|
||||
if (multiple)
|
||||
log_info("\tExecuting reference event 0, then reference event 1 with reference event 0 in its waitlist, then test event 2 with reference events 0 and 1 in its waitlist.\n");
|
||||
else
|
||||
log_info("\tExecuting reference event 0, then test event 2 with reference event 0 in its waitlist.\n");
|
||||
|
||||
// Set up the first base action to wait against
|
||||
error = actions[ 0 ].Setup( device, context, queue );
|
||||
test_error( error, "Unable to setup base event to wait against" );
|
||||
|
||||
if( multiple )
|
||||
{
|
||||
// Set up a second event to wait against
|
||||
error = actions[ 1 ].Setup( device, context, queue );
|
||||
test_error( error, "Unable to setup second base event to wait against" );
|
||||
}
|
||||
|
||||
// Now set up the actual action to test
|
||||
error = actionToTest->Setup( device, context, queue );
|
||||
test_error( error, "Unable to set up test event" );
|
||||
|
||||
// Execute all events now
|
||||
if (PRINT_OPS) log_info("\tExecuting action 0...\n");
|
||||
error = actions[ 0 ].Execute( queue, 0, NULL, &events[ 0 ] );
|
||||
test_error( error, "Unable to execute first event" );
|
||||
|
||||
if( multiple )
|
||||
{
|
||||
if (PRINT_OPS) log_info("\tExecuting action 1...\n");
|
||||
error = actions[ 1 ].Execute( queue, 1, &events[0], &events[ 1 ] );
|
||||
test_error( error, "Unable to execute second event" );
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if( multiple ) {
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
|
||||
error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
}
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
|
||||
error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
|
||||
log_info("\t\tEvent status after starting reference events: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
|
||||
IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), "N/A");
|
||||
|
||||
if( ( status[ 0 ] == CL_COMPLETE ) || ( multiple && status[ 1 ] == CL_COMPLETE ) )
|
||||
{
|
||||
log_info( "WARNING: Reference event(s) already completed before we could execute test event! Possible that the reference event blocked (implicitly passing)\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PRINT_OPS) log_info("\tExecuting action to test...\n");
|
||||
error = actionToTest->Execute( queue, ( multiple ) ? 2 : 1, &events[ 0 ], &events[ 2 ] );
|
||||
test_error( error, "Unable to execute test event" );
|
||||
|
||||
// Hopefully, the first event is still running
|
||||
if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
|
||||
error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
if( multiple ) {
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
|
||||
error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
}
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
|
||||
error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
|
||||
log_info("\t\tEvent status after starting test event: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
|
||||
IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
|
||||
|
||||
if( multiple )
|
||||
{
|
||||
if( status[ 0 ] == CL_COMPLETE && status[ 1 ] == CL_COMPLETE )
|
||||
{
|
||||
log_info( "WARNING: Both events completed, so unable to test further (implicitly passing).\n" );
|
||||
clFinish( queue );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(status[1] == CL_COMPLETE && status[0] != CL_COMPLETE)
|
||||
{
|
||||
log_error("ERROR: Test failed because the second wait event is complete and the first is not.(status: 0: %s and 1: %s)\n", IGetStatusString( status[ 0 ] ), IGetStatusString( status[ 1 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( status[ 0 ] == CL_COMPLETE )
|
||||
{
|
||||
log_info( "WARNING: Reference event completed, so unable to test further (implicitly passing).\n" );
|
||||
clFinish( queue );
|
||||
return 0;
|
||||
}
|
||||
if( status[ 0 ] != CL_RUNNING && status[ 0 ] != CL_QUEUED && status[ 0 ] != CL_SUBMITTED )
|
||||
{
|
||||
log_error( "ERROR: Test failed because first wait event is not currently running, queued, or submitted! (status: 0: %s)\n", IGetStatusString( status[ 0 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if( status[ 2 ] != CL_QUEUED && status[ 2 ] != CL_SUBMITTED )
|
||||
{
|
||||
log_error( "ERROR: Test event is not waiting to run! (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Now wait for the first reference event
|
||||
if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n");
|
||||
error = clWaitForEvents( 1, &events[ 0 ] );
|
||||
test_error( error, "Unable to wait for reference event" );
|
||||
|
||||
// Grab statuses again
|
||||
if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
|
||||
error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
if( multiple ) {
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
|
||||
error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
}
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
|
||||
error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
|
||||
log_info("\t\tEvent status after waiting for reference event 0: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
|
||||
IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
|
||||
|
||||
// Sanity
|
||||
if( status[ 0 ] != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Waited for first event but it's not complete (status: 0: %s)\n", IGetStatusString( status[ 0 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If we're multiple, and the second event isn't complete, then our test event should still be queued
|
||||
if( multiple && status[ 1 ] != CL_COMPLETE )
|
||||
{
|
||||
if( status[ 1 ] == CL_RUNNING && status[ 2 ] == CL_RUNNING ) {
|
||||
log_error("ERROR: Test event and second event are both running.\n");
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
if( status[ 2 ] != CL_QUEUED && status[ 2 ] != CL_SUBMITTED )
|
||||
{
|
||||
log_error( "ERROR: Test event did not wait for second event before starting! (status of ref: 1: %s, of test: 2: %s)\n", IGetStatusString( status[ 1 ] ), IGetStatusString( status[ 2 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Now wait for second event to complete, too
|
||||
if (PRINT_OPS) log_info("\tWaiting for action 1 to finish...\n");
|
||||
error = clWaitForEvents( 1, &events[ 1 ] );
|
||||
test_error( error, "Unable to wait for second reference event" );
|
||||
|
||||
// Grab statuses again
|
||||
if (PRINT_OPS) log_info("\tChecking status of action to test 2...\n");
|
||||
error = clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
if( multiple ) {
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 1...\n");
|
||||
error = clGetEventInfo( events[ 1 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 1 ] ), &status[ 1 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
}
|
||||
if (PRINT_OPS) log_info("\tChecking status of action 0...\n");
|
||||
error = clGetEventInfo( events[ 0 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 0 ] ), &status[ 0 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
|
||||
log_info("\t\tEvent status after waiting for reference event 1: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
|
||||
IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
|
||||
|
||||
// Sanity
|
||||
if( status[ 1 ] != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Waited for second reference event but it didn't complete (status: 1: %s)\n", IGetStatusString( status[ 1 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, the test event SHOULD be running, but if it completed, we consider it a pass
|
||||
if( status[ 2 ] == CL_COMPLETE )
|
||||
{
|
||||
log_info( "WARNING: Test event already completed. Assumed valid.\n" );
|
||||
clFinish( queue );
|
||||
return 0;
|
||||
}
|
||||
if( status[ 2 ] != CL_RUNNING && status[ 2 ] != CL_SUBMITTED && status[ 2 ] != CL_QUEUED)
|
||||
{
|
||||
log_error( "ERROR: Second event did not start running after reference event(s) completed! (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Wait for the test event, then return
|
||||
if (PRINT_OPS) log_info("\tWaiting for action 2 to test to finish...\n");
|
||||
error = clWaitForEvents( 1, &events[ 2 ] );
|
||||
test_error( error, "Unable to wait for test event" );
|
||||
|
||||
error |= clGetEventInfo( events[ 2 ], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof( status[ 2 ] ), &status[ 2 ], NULL );
|
||||
test_error( error, "Unable to get event status" );
|
||||
|
||||
log_info("\t\tEvent status after waiting for test event: reference event 0: %s, reference event 1: %s, test event 2: %s.\n",
|
||||
IGetStatusString( status[ 0 ] ), (multiple ? IGetStatusString( status[ 1 ] ) : "N/A"), IGetStatusString( status[ 2 ] ));
|
||||
|
||||
// Sanity
|
||||
if( status[ 2 ] != CL_COMPLETE )
|
||||
{
|
||||
log_error( "ERROR: Test event didn't complete (status: 2: %s)\n", IGetStatusString( status[ 2 ] ) );
|
||||
clFinish( queue );
|
||||
return -1;
|
||||
}
|
||||
|
||||
clFinish(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_ACTION( name ) \
|
||||
{ \
|
||||
name##Action action; \
|
||||
log_info( "-- Testing " #name " (waiting on 1 event)...\n" ); \
|
||||
if( ( error = test_waitlist( deviceID, context, queue, &action, false ) ) != CL_SUCCESS ) \
|
||||
retVal++; \
|
||||
clFinish( queue ); \
|
||||
} \
|
||||
if( error == CL_SUCCESS ) /* Only run multiples test if single test passed */ \
|
||||
{ \
|
||||
name##Action action; \
|
||||
log_info( "-- Testing " #name " (waiting on 2 events)...\n" ); \
|
||||
if( ( error = test_waitlist( deviceID, context, queue, &action, true ) ) != CL_SUCCESS ) \
|
||||
retVal++; \
|
||||
clFinish( queue ); \
|
||||
}
|
||||
|
||||
int test_waitlists( cl_device_id deviceID, cl_context context, cl_command_queue oldQueue, int num_elements )
|
||||
{
|
||||
cl_int error;
|
||||
int retVal = 0;
|
||||
cl_queue_properties props[] = {CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0};
|
||||
|
||||
if( !checkDeviceForQueueSupport( deviceID, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE ) )
|
||||
{
|
||||
log_info( "WARNING: Device does not support out-of-order exec mode; skipping test.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
clCommandQueueWrapper queue = clCreateCommandQueueWithProperties( context, deviceID, &props[0], &error );
|
||||
test_error(error, "Unable to create out-of-order queue");
|
||||
|
||||
log_info( "\n" );
|
||||
|
||||
TEST_ACTION( NDRangeKernel )
|
||||
|
||||
TEST_ACTION( ReadBuffer )
|
||||
TEST_ACTION( WriteBuffer )
|
||||
TEST_ACTION( MapBuffer )
|
||||
TEST_ACTION( UnmapBuffer )
|
||||
|
||||
if( checkForImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED )
|
||||
{
|
||||
log_info( "\nNote: device does not support images. Skipping remainder of waitlist tests...\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ACTION( ReadImage2D )
|
||||
TEST_ACTION( WriteImage2D )
|
||||
TEST_ACTION( CopyImage2Dto2D )
|
||||
TEST_ACTION( Copy2DImageToBuffer )
|
||||
TEST_ACTION( CopyBufferTo2DImage )
|
||||
TEST_ACTION( MapImage )
|
||||
|
||||
if( checkFor3DImageSupport( deviceID ) == CL_IMAGE_FORMAT_NOT_SUPPORTED )
|
||||
log_info("Device does not support 3D images. Skipping remainder of waitlist tests...\n");
|
||||
else
|
||||
{
|
||||
TEST_ACTION( ReadImage3D )
|
||||
TEST_ACTION( WriteImage3D )
|
||||
TEST_ACTION( CopyImage2Dto3D )
|
||||
TEST_ACTION( CopyImage3Dto2D )
|
||||
TEST_ACTION( CopyImage3Dto3D )
|
||||
TEST_ACTION( Copy3DImageToBuffer )
|
||||
TEST_ACTION( CopyBufferTo3DImage )
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user