Initial open source release of OpenCL 2.0 CTS.

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

View File

@@ -0,0 +1,24 @@
set(MODULE_NAME COMPILER)
set(${MODULE_NAME}_SOURCES
main.c
test_build_helpers.c
test_compile.c
test_async_build.c
test_build_options.cpp
test_preprocessor.c
test_image_macro.c
test_compiler_defines_for_extensions.cpp
test_pragma_unroll.c
../../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/os_helpers.cpp
)
include(../CMakeCommon.txt)

View File

@@ -0,0 +1,27 @@
project
: requirements
<toolset>gcc:<cflags>-xc++
<toolset>msvc:<cflags>"/TP"
;
exe test_compiler
: main.c
test_async_build.c
test_build_helpers.c
test_build_options.cpp
test_compile.c
test_preprocessor.c
test_pragma_unroll.c
;
install dist
: test_compiler
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/compiler
<variant>release:<location>$(DIST)/release/tests/test_conformance/compiler
;
install data
: includeTestDirectory/testIncludeFile.h
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/compiler/includeTestDirectory
<variant>release:<location>$(DIST)/release/tests/test_conformance/compiler/includeTestDirectory
;

View File

@@ -0,0 +1,51 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.c \
test_build_helpers.c \
test_compile.c \
test_compiler_defines_for_extensions.cpp \
test_async_build.c \
test_build_options.cpp \
test_preprocessor.c \
test_image_macro.c \
test_pragma_unroll.c \
../../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/os_helpers.cpp \
../../test_common/harness/conversions.c
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
HEADERS =
TARGET = test_compiler
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32
CC = c++
CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF}
OBJECTS := ${SOURCES:.c=.o}
OBJECTS := ${OBJECTS:.cpp=.o}
TARGETOBJECT =
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES)
clean:
rm -f $(TARGET) $(OBJECTS)
.DEFAULT:
@echo The target \"$@\" does not exist in Makefile.

View File

@@ -0,0 +1,16 @@
//
// 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.
//
#define HEADER_FOUND 12

View File

@@ -0,0 +1,168 @@
//
// 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_load_program_source,
test_load_multistring_source,
test_load_two_kernel_source,
test_load_null_terminated_source,
test_load_null_terminated_multi_line_source,
test_load_null_terminated_partial_multi_line_source,
test_load_discreet_length_source,
test_get_program_source,
test_get_program_build_info,
test_get_program_info,
test_large_compile,
test_async_build_pieces,
test_options_optimizations,
test_options_build_macro,
test_options_build_macro_existence,
test_options_include_directory,
test_options_denorm_cache,
test_preprocessor_define_udef,
test_preprocessor_include,
test_preprocessor_line_error,
test_preprocessor_pragma,
test_compiler_defines_for_extensions,
test_image_macro,
test_simple_compile_only,
test_simple_static_compile_only,
test_simple_extern_compile_only,
test_simple_compile_with_callback,
test_simple_embedded_header_compile,
test_simple_link_only,
test_two_file_regular_variable_access,
test_two_file_regular_struct_access,
test_two_file_regular_function_access,
test_simple_link_with_callback,
test_simple_embedded_header_link,
test_execute_after_simple_compile_and_link,
test_execute_after_simple_compile_and_link_no_device_info,
test_execute_after_simple_compile_and_link_with_defines,
test_execute_after_simple_compile_and_link_with_callbacks,
test_execute_after_simple_library_with_link,
test_execute_after_two_file_link,
test_execute_after_embedded_header_link,
test_execute_after_included_header_link,
test_execute_after_serialize_reload_object,
test_execute_after_serialize_reload_library,
test_simple_library_only,
test_simple_library_with_callback,
test_simple_library_with_link,
test_two_file_link,
test_multi_file_libraries,
test_multiple_files,
test_multiple_libraries,
test_multiple_files_multiple_libraries,
test_multiple_embedded_headers,
test_program_binary_type,
test_compile_and_link_status_options_log,
test_pragma_unroll
};
const char *basefn_names[] = {
"load_program_source",
"load_multistring_source",
"load_two_kernel_source",
"load_null_terminated_source",
"load_null_terminated_multi_line_source",
"load_null_terminated_partial_multi_line_source",
"load_discreet_length_source",
"get_program_source",
"get_program_build_info",
"get_program_info",
"large_compile",
"async_build",
"options_build_optimizations",
"options_build_macro",
"options_build_macro_existence",
"options_include_directory",
"options_denorm_cache",
"preprocessor_define_udef",
"preprocessor_include",
"preprocessor_line_error",
"preprocessor_pragma",
"compiler_defines_for_extensions",
"image_macro",
"simple_compile_only",
"simple_static_compile_only",
"simple_extern_compile_only",
"simple_compile_with_callback",
"simple_embedded_header_compile",
"simple_link_only",
"two_file_regular_variable_access",
"two_file_regular_struct_access",
"two_file_regular_function_access",
"simple_link_with_callback",
"simple_embedded_header_link",
"execute_after_simple_compile_and_link",
"execute_after_simple_compile_and_link_no_device_info",
"execute_after_simple_compile_and_link_with_defines",
"execute_after_simple_compile_and_link_with_callbacks",
"execute_after_simple_library_with_link",
"execute_after_two_file_link",
"execute_after_embedded_header_link",
"execute_after_included_header_link",
"execute_after_serialize_reload_object",
"execute_after_serialize_reload_library",
"simple_library_only",
"simple_library_with_callback",
"simple_library_with_link",
"two_file_link",
"multi_file_libraries",
"multiple_files",
"multiple_libraries",
"multiple_files_multiple_libraries",
"multiple_embedded_headers",
"program_binary_type",
"compile_and_link_status_options_log",
"pragma_unroll",
};
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 );
}

View File

@@ -0,0 +1,88 @@
//
// 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/conversions.h"
#include "../../test_common/harness/mt19937.h"
extern int test_load_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_load_multistring_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_load_two_kernel_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_load_null_terminated_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_load_null_terminated_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_load_null_terminated_partial_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_load_discreet_length_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_get_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_get_program_build_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_get_program_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_large_compile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_async_build_pieces(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_options_optimizations(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_options_build_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_options_build_macro_existence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_options_include_directory(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_options_denorm_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_preprocessor_define_udef(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_preprocessor_include(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_preprocessor_line_error(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_preprocessor_pragma(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_compiler_defines_for_extensions(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems );
extern int test_image_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_static_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_extern_compile_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_compile_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_embedded_header_compile(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_link_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_two_file_regular_variable_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_two_file_regular_struct_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_two_file_regular_function_access(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_link_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_embedded_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_simple_compile_and_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_simple_compile_and_link_no_device_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_simple_compile_and_link_with_defines(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_simple_compile_and_link_with_callbacks(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_simple_library_with_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_two_file_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_embedded_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_included_header_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_serialize_reload_object(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_execute_after_serialize_reload_library(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_library_only(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_library_with_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_simple_library_with_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_two_file_link(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_multi_file_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_multiple_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_multiple_files(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_multiple_files_multiple_libraries(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_multiple_embedded_headers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_program_binary_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_compile_and_link_status_options_log(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_pragma_unroll(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);

View File

@@ -0,0 +1,16 @@
//
// 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.
//
#define HEADER_FOUND 42

View 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

View File

@@ -0,0 +1,97 @@
//
// 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>
#endif
const char *sample_async_kernel[] = {
"__kernel void sample_test(__global float *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
"\n"
" dst[tid] = (int)src[tid];\n"
"\n"
"}\n" };
volatile int buildNotificationSent;
void CL_CALLBACK test_notify_build_complete( cl_program program, void *userData )
{
if( userData == NULL || strcmp( (char *)userData, "userData" ) != 0 )
{
log_error( "ERROR: User data passed in to build notify function was not correct!\n" );
buildNotificationSent = -1;
}
else
buildNotificationSent = 1;
log_info( "\n <-- program successfully built\n" );
}
int test_async_build_pieces(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
cl_build_status status;
buildNotificationSent = 0;
/* First, test by doing the slow method of the individual calls */
program = clCreateProgramWithSource( context, 1, sample_async_kernel, NULL, &error );
if( program == NULL || error != CL_SUCCESS)
{
print_error( error, "Unable to create test program" );
return -1;
}
/* Compile the program */
error = clBuildProgram( program, 1, &deviceID, NULL, test_notify_build_complete, (void *)"userData" );
test_error( error, "Unable to build program source" );
/* Wait for build to complete (just keep polling, since we're just a test */
if( ( error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL ) ) != CL_SUCCESS )
{
print_error( error, "Unable to get program build status" );
return -1;
}
while( (int)status == CL_BUILD_IN_PROGRESS )
{
log_info( "\n -- still waiting for build... (status is %d)", status );
sleep( 1 );
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
test_error( error, "Unable to get program build status" );
}
if( status != CL_BUILD_SUCCESS )
{
log_error( "ERROR: build failed! (status: %d)\n", (int)status );
return -1;
}
if( buildNotificationSent == 0 )
{
log_error( "ERROR: Async build completed, but build notification was not sent!\n" );
return -1;
}
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}

View File

@@ -0,0 +1,578 @@
//
// 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"
const char *sample_kernel_code_single_line[] = {
"__kernel void sample_test(__global float *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
"\n"
" dst[tid] = (int)src[tid];\n"
"\n"
"}\n" };
size_t sample_single_line_lengths[1];
const char *sample_kernel_code_multi_line[] = {
"__kernel void sample_test(__global float *src, __global int *dst)",
"{",
" int tid = get_global_id(0);",
"",
" dst[tid] = (int)src[tid];",
"",
"}" };
size_t sample_multi_line_lengths[ 7 ];
const char *sample_kernel_code_two_line[] = {
"__kernel void sample_test(__global float *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
"\n"
" dst[tid] = (int)src[tid];\n"
"\n"
"}\n",
"__kernel void sample_test2(__global int *src, __global float *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
"\n"
" dst[tid] = (float)src[tid];\n"
"\n"
"}\n" };
size_t sample_two_line_lengths[1];
const char *sample_kernel_code_bad_multi_line[] = {
"__kernel void sample_test(__global float *src, __global int *dst)",
"{",
" int tid = get_global_id(0);thisisanerror",
"",
" dst[tid] = (int)src[tid];",
"",
"}" };
size_t sample_bad_multi_line_lengths[ 7 ];
int test_load_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
clProgramWrapper program;
size_t length;
char *buffer;
/* Preprocess: calc the length of each source file line */
sample_single_line_lengths[ 0 ] = strlen( sample_kernel_code_single_line[ 0 ] );
/* New OpenCL API only has one entry point, so go ahead and just try it */
program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, sample_single_line_lengths, &error);
test_error( error, "Unable to create reference program" );
/* Now get the source and compare against our original */
error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, NULL, NULL, &length );
test_error( error, "Unable to get length of first program source" );
// Note: according to spec section 5.4.5, the length returned should include the null terminator
if( length != sample_single_line_lengths[0] + 1 )
{
log_error( "ERROR: Length of program (%ld) does not match reference length (%ld)!\n", length, sample_single_line_lengths[0] + 1 );
return -1;
}
buffer = (char *)malloc( length );
error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, length, buffer, NULL );
test_error( error, "Unable to get buffer of first program source" );
if( strcmp( (char *)buffer, sample_kernel_code_single_line[ 0 ] ) != 0 )
{
log_error( "ERROR: Program sources do not match!\n" );
return -1;
}
/* All done */
free( buffer );
return 0;
}
int test_load_multistring_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
clProgramWrapper program;
int i;
/* Preprocess: calc the length of each source file line */
for( i = 0; i < 7; i++ )
{
sample_multi_line_lengths[ i ] = strlen( sample_kernel_code_multi_line[ i ] );
}
/* Create another program using the macro function */
program = clCreateProgramWithSource( context, 7, sample_kernel_code_multi_line, sample_multi_line_lengths, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create reference program!\n" );
return -1;
}
/* Try compiling */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build multi-line program source" );
/* Should probably check binary here to verify the same results... */
/* All done! */
return 0;
}
int test_load_two_kernel_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
int i;
/* Preprocess: calc the length of each source file line */
for( i = 0; i < 2; i++ )
{
sample_two_line_lengths[ i ] = strlen( sample_kernel_code_two_line[ i ] );
}
/* Now create a program using the macro function */
program = clCreateProgramWithSource( context, 2, sample_kernel_code_two_line, sample_two_line_lengths, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create two-kernel program!\n" );
return -1;
}
/* Try compiling */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build two-kernel program source" );
/* Should probably check binary here to verify the same results... */
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_load_null_terminated_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
/* Now create a program using the macro function */
program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create null-terminated program!" );
return -1;
}
/* Try compiling */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build null-terminated program source" );
/* Should probably check binary here to verify the same results... */
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_load_null_terminated_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
/* Now create a program using the macro function */
program = clCreateProgramWithSource( context, 7, sample_kernel_code_multi_line, NULL, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create null-terminated program!" );
return -1;
}
/* Try compiling */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build null-terminated program source" );
/* Should probably check binary here to verify the same results... */
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_load_discreet_length_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
int i;
/* Preprocess: calc the length of each source file line */
for( i = 0; i < 7; i++ )
{
sample_bad_multi_line_lengths[ i ] = strlen( sample_kernel_code_bad_multi_line[ i ] );
}
/* Now force the length of the third line to skip the actual error */
sample_bad_multi_line_lengths[2] -= strlen("thisisanerror");
/* Now create a program using the macro function */
program = clCreateProgramWithSource( context, 7, sample_kernel_code_bad_multi_line, sample_bad_multi_line_lengths, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create null-terminated program!" );
return -1;
}
/* Try compiling */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build null-terminated program source" );
/* Should probably check binary here to verify the same results... */
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_load_null_terminated_partial_multi_line_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
int i;
/* Preprocess: calc the length of each source file line */
for( i = 0; i < 7; i++ )
{
if( i & 0x01 )
sample_multi_line_lengths[ i ] = 0; /* Should force for null-termination on this line only */
else
sample_multi_line_lengths[ i ] = strlen( sample_kernel_code_multi_line[ i ] );
}
/* Now create a program using the macro function */
program = clCreateProgramWithSource( context, 7, sample_kernel_code_multi_line, sample_multi_line_lengths, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create null-terminated program!" );
return -1;
}
/* Try compiling */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build null-terminated program source" );
/* Should probably check binary here to verify the same results... */
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_get_program_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_program program;
cl_device_id device1;
cl_context context1;
size_t paramSize;
cl_uint numInstances;
program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create reference program!\n" );
return -1;
}
/* Test that getting the device works. */
device1 = (cl_device_id)0xbaadfeed;
error = clGetProgramInfo( program, CL_PROGRAM_DEVICES, sizeof( device1 ), &device1, NULL );
test_error( error, "Unable to get device of program" );
/* Since the device IDs are opaque types we check the CL_DEVICE_VENDOR_ID which is unique for identical hardware. */
cl_uint device1_vid, deviceID_vid;
error = clGetDeviceInfo(device1, CL_DEVICE_VENDOR_ID, sizeof(device1_vid), &device1_vid, NULL );
test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" );
error = clGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(deviceID_vid), &deviceID_vid, NULL );
test_error( error, "Unable to get device CL_DEVICE_VENDOR_ID" );
if( device1_vid != deviceID_vid )
{
log_error( "ERROR: Incorrect device returned for program! (Expected vendor ID 0x%x, got 0x%x)\n", deviceID_vid, device1_vid );
return -1;
}
cl_uint devCount;
error = clGetProgramInfo( program, CL_PROGRAM_NUM_DEVICES, sizeof( devCount ), &devCount, NULL );
test_error( error, "Unable to get device count of program" );
if( devCount != 1 )
{
log_error( "ERROR: Invalid device count returned for program! (Expected 1, got %d)\n", (int)devCount );
return -1;
}
context1 = (cl_context)0xbaadfeed;
error = clGetProgramInfo( program, CL_PROGRAM_CONTEXT, sizeof( context1 ), &context1, NULL );
test_error( error, "Unable to get device of program" );
if( context1 != context )
{
log_error( "ERROR: Invalid context returned for program! (Expected %p, got %p)\n", context, context1 );
return -1;
}
error = clGetProgramInfo( program, CL_PROGRAM_REFERENCE_COUNT, sizeof( numInstances ), &numInstances, NULL );
test_error( error, "Unable to get instance count" );
/* While we're at it, test the sizes of programInfo too */
error = clGetProgramInfo( program, CL_PROGRAM_DEVICES, NULL, NULL, &paramSize );
test_error( error, "Unable to get device param size" );
if( paramSize != sizeof( cl_device_id ) )
{
log_error( "ERROR: Size returned for device is wrong!\n" );
return -1;
}
error = clGetProgramInfo( program, CL_PROGRAM_CONTEXT, NULL, NULL, &paramSize );
test_error( error, "Unable to get context param size" );
if( paramSize != sizeof( cl_context ) )
{
log_error( "ERROR: Size returned for context is wrong!\n" );
return -1;
}
error = clGetProgramInfo( program, CL_PROGRAM_REFERENCE_COUNT, NULL, NULL, &paramSize );
test_error( error, "Unable to get instance param size" );
if( paramSize != sizeof( cl_uint ) )
{
log_error( "ERROR: Size returned for num instances is wrong!\n" );
return -1;
}
error = clGetProgramInfo( program, CL_PROGRAM_NUM_DEVICES, NULL, NULL, &paramSize );
test_error( error, "Unable to get device count param size" );
if( paramSize != sizeof( cl_uint ) )
{
log_error( "ERROR: Size returned for device count is wrong!\n" );
return -1;
}
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_get_program_source(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
cl_program program;
int error;
char buffer[10240];
size_t length;
program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create test program!\n" );
return -1;
}
/* Try getting the length */
error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, NULL, NULL, &length );
test_error( error, "Unable to get program source length" );
if( length != strlen( sample_kernel_code_single_line[0] ) + 1 )
{
log_error( "ERROR: Length returned for program source is incorrect!\n" );
return -1;
}
/* Try normal source */
error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, sizeof( buffer ), buffer, NULL );
test_error( error, "Unable to get program source" );
if( strlen( buffer ) != strlen( sample_kernel_code_single_line[0] ) )
{
log_error( "ERROR: Length of program source is incorrect!\n" );
return -1;
}
/* Try both at once */
error = clGetProgramInfo( program, CL_PROGRAM_SOURCE, sizeof( buffer ), buffer, &length );
test_error( error, "Unable to get program source" );
if( strlen( buffer ) != strlen( sample_kernel_code_single_line[0] ) )
{
log_error( "ERROR: Length of program source is incorrect!\n" );
return -1;
}
if( length != strlen( sample_kernel_code_single_line[0] ) + 1 )
{
log_error( "ERROR: Returned length of program source is incorrect!\n" );
return -1;
}
/* All done! */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}
int test_get_program_build_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
cl_program program;
int error;
char *buffer;
size_t length, newLength;
cl_build_status status;
program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create test program!\n" );
return -1;
}
/* Make sure getting the length works */
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, 0, NULL, &length );
test_error( error, "Unable to get program build status length" );
if( length != sizeof( status ) )
{
log_error( "ERROR: Returned length of program build status is invalid! (Expected %d, got %d)\n", (int)sizeof( status ), (int)length );
return -1;
}
/* Now actually build it and verify the status */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Unable to build program source" );
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
test_error( error, "Unable to get program build status" );
if( status != CL_BUILD_SUCCESS )
{
log_error( "ERROR: Getting built program build status did not return CL_BUILD_SUCCESS! (%d)\n", (int)status );
return -1;
}
/***** Build log *****/
/* Try getting the length */
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &length );
test_error( error, "Unable to get program build log length" );
log_info("Build log is %ld long.\n", length);
buffer = (char*)malloc(length);
/* Try normal source */
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, length, buffer, NULL );
test_error( error, "Unable to get program build log" );
if( buffer[length-1] != '\0' )
{
log_error( "clGetProgramBuildInfo overwrote allocated space for build log! '%c'\n", buffer[length-1] );
return -1;
}
/* Try both at once */
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, length, buffer, &newLength );
test_error( error, "Unable to get program build log" );
free(buffer);
/***** Build options *****/
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, 0, NULL, &length );
test_error( error, "Unable to get program build options length" );
buffer = (char*)malloc(length);
/* Try normal source */
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, length, buffer, NULL );
test_error( error, "Unable to get program build options" );
/* Try both at once */
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, length, buffer, &newLength );
test_error( error, "Unable to get program build options" );
free(buffer);
/* Try with a valid option */
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
program = clCreateProgramWithSource( context, 1, sample_kernel_code_single_line, NULL, &error );
if( program == NULL )
{
log_error( "ERROR: Unable to create test program!\n" );
return -1;
}
error = clBuildProgram( program, 1, &deviceID, "-cl-opt-disable", NULL, NULL );
if( error != CL_SUCCESS )
{
print_error( error, "Building with valid options failed!" );
return -1;
}
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, NULL, NULL, &length );
test_error( error, "Unable to get program build options" );
buffer = (char*)malloc(length);
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_OPTIONS, length, buffer, NULL );
test_error( error, "Unable to get program build options" );
if( strcmp( (char *)buffer, "-cl-opt-disable" ) != 0 )
{
log_error( "ERROR: Getting program build options for program with -cl-opt-disable build options did not return expected value (got %s)\n", buffer );
return -1;
}
/* All done */
free( buffer );
error = clReleaseProgram( program );
test_error( error, "Unable to release program object" );
return 0;
}

View File

@@ -0,0 +1,409 @@
//
// 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/os_helpers.h"
const char *preprocessor_test_kernel[] = {
"__kernel void sample_test(__global int *dst)\n"
"{\n"
" dst[0] = TEST_MACRO;\n"
"\n"
"}\n" };
const char *preprocessor_existence_test_kernel[] = {
"__kernel void sample_test(__global int *dst)\n"
"{\n"
"#ifdef TEST_MACRO\n"
" dst[0] = 42;\n"
"#else\n"
" dst[0] = 24;\n"
"#endif\n"
"\n"
"}\n" };
const char *include_test_kernel[] = {
"#include \"./testIncludeFile.h\"\n"
"__kernel void sample_test(__global int *dst)\n"
"{\n"
" dst[0] = HEADER_FOUND;\n"
"\n"
"}\n" };
const char *options_test_kernel[] = {
"__kernel void sample_test(__global float *src, __global int *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" dst[tid] = src[tid];\n"
"}\n" };
const char *optimization_options[] = {
"-cl-single-precision-constant",
"-cl-denorms-are-zero",
"-cl-opt-disable",
"-cl-mad-enable",
"-cl-no-signed-zeros",
"-cl-unsafe-math-optimizations",
"-cl-finite-math-only",
"-cl-fast-relaxed-math",
"-w",
"-Werror",
#if defined( __APPLE__ )
"-cl-opt-enable",
"-cl-auto-vectorize-enable"
#endif
};
cl_int get_result_from_program( cl_context context, cl_command_queue queue, cl_program program, cl_int *outValue )
{
cl_int error;
clKernelWrapper kernel = clCreateKernel( program, "sample_test", &error );
test_error( error, "Unable to create kernel from program" );
clMemWrapper outStream;
outStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int), NULL, &error );
test_error( error, "Unable to create test buffer" );
error = clSetKernelArg( kernel, 0, sizeof( outStream ), &outStream );
test_error( error, "Unable to set kernel argument" );
size_t threads[1] = { 1 };
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to execute test kernel" );
error = clEnqueueReadBuffer( queue, outStream, true, 0, sizeof( cl_int ), outValue, 0, NULL, NULL );
test_error( error, "Unable to read output array!" );
return CL_SUCCESS;
}
int test_options_optimizations(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
cl_build_status status;
for(size_t i = 0; i < sizeof(optimization_options) / (sizeof(char*)); i++) {
clProgramWrapper program = clCreateProgramWithSource( context, 1, options_test_kernel, NULL, &error );
if( program == NULL || error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create reference program!\n" );
return -1;
}
/* Build with the macro defined */
log_info("Testing optimization option '%s'\n", optimization_options[i]);
error = clBuildProgram( program, 1, &deviceID, optimization_options[i], NULL, NULL );
test_error( error, "Test program did not properly build" );
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
test_error( error, "Unable to get program build status" );
if( (int)status != CL_BUILD_SUCCESS )
{
log_info("Building with optimization option '%s' failed to compile!\n", optimization_options[i]);
print_error( error, "Failed to build with optimization defined")
return -1;
}
}
return 0;
}
int test_options_build_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
clProgramWrapper program;
cl_build_status status;
program = clCreateProgramWithSource( context, 1, preprocessor_test_kernel, NULL, &error );
if( program == NULL || error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create reference program!\n" );
return -1;
}
/* Build with the macro defined */
error = clBuildProgram( program, 1, &deviceID, "-DTEST_MACRO=1 ", NULL, NULL );
test_error( error, "Test program did not properly build" );
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
test_error( error, "Unable to get program build status" );
if( (int)status != CL_BUILD_SUCCESS )
{
print_error( error, "Failed to build with macro defined" );
return -1;
}
// Go ahead and run the program to verify results
cl_int firstResult, secondResult;
error = get_result_from_program( context, queue, program, &firstResult );
test_error( error, "Unable to get result from first program" );
if( firstResult != 1 )
{
log_error( "ERROR: Result from first program did not validate! (Expected 1, got %d)\n", firstResult );
return -1;
}
// Rebuild with a different value for the define macro, to make sure caching behaves properly
error = clBuildProgram( program, 1, &deviceID, "-DTEST_MACRO=5 ", NULL, NULL );
test_error( error, "Test program did not properly rebuild" );
error = get_result_from_program( context, queue, program, &secondResult );
test_error( error, "Unable to get result from second program" );
if( secondResult != 5 )
{
if( secondResult == firstResult )
log_error( "ERROR: Program result did not change with device macro change (program was not recompiled)!\n" );
else
log_error( "ERROR: Result from second program did not validate! (Expected 5, got %d)\n", secondResult );
return -1;
}
return 0;
}
int test_options_build_macro_existence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
clProgramWrapper program;
// In this case, the program should still run without the macro, but it should give a different result
program = clCreateProgramWithSource( context, 1, preprocessor_existence_test_kernel, NULL, &error );
if( program == NULL || error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create reference program!\n" );
return -1;
}
/* Build without the macro defined */
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Test program did not properly build" );
// Go ahead and run the program to verify results
cl_int firstResult, secondResult;
error = get_result_from_program( context, queue, program, &firstResult );
test_error( error, "Unable to get result from first program" );
if( firstResult != 24 )
{
log_error( "ERROR: Result from first program did not validate! (Expected 24, got %d)\n", firstResult );
return -1;
}
// Now compile again with the macro defined and verify a change in results
error = clBuildProgram( program, 1, &deviceID, "-DTEST_MACRO", NULL, NULL );
test_error( error, "Test program did not properly build" );
error = get_result_from_program( context, queue, program, &secondResult );
test_error( error, "Unable to get result from second program" );
if( secondResult != 42 )
{
if( secondResult == firstResult )
log_error( "ERROR: Program result did not change with device macro addition (program was not recompiled)!\n" );
else
log_error( "ERROR: Result from second program did not validate! (Expected 42, got %d)\n", secondResult );
return -1;
}
return 0;
}
int test_options_include_directory(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
std::string sep = dir_sep();
std::string path = exe_dir(); // Directory where test executable is located.
std::string include_dir;
clProgramWrapper program;
cl_build_status status;
/* Try compiling the program first without the directory included Should fail. */
program = clCreateProgramWithSource( context, 1, include_test_kernel, NULL, &error );
if( program == NULL || error != CL_SUCCESS )
{
log_error( "ERROR: Unable to create reference program!\n" );
return -1;
}
/* Build with the include directory defined */
include_dir = "-I " + path + sep + "includeTestDirectory";
// log_info("%s\n", include_dir);
error = clBuildProgram( program, 1, &deviceID, include_dir.c_str(), NULL, NULL );
test_error( error, "Test program did not properly build" );
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
test_error( error, "Unable to get program build status" );
if( (int)status != CL_BUILD_SUCCESS )
{
print_error( error, "Failed to build with include directory" );
return -1;
}
// Go ahead and run the program to verify results
cl_int firstResult, secondResult;
error = get_result_from_program( context, queue, program, &firstResult );
test_error( error, "Unable to get result from first program" );
if( firstResult != 12 )
{
log_error( "ERROR: Result from first program did not validate! (Expected 12, got %d)\n", firstResult );
return -1;
}
// Rebuild with a different include directory
include_dir = "-I " + path + sep + "secondIncludeTestDirectory";
error = clBuildProgram( program, 1, &deviceID, include_dir.c_str(), NULL, NULL );
test_error( error, "Test program did not properly rebuild" );
error = get_result_from_program( context, queue, program, &secondResult );
test_error( error, "Unable to get result from second program" );
if( secondResult != 42 )
{
if( secondResult == firstResult )
log_error( "ERROR: Program result did not change with include path change (program was not recompiled)!\n" );
else
log_error( "ERROR: Result from second program did not validate! (Expected 42, got %d)\n", secondResult );
return -1;
}
return 0;
}
const char *denorm_test_kernel[] = {
"__kernel void sample_test( float src1, float src2, __global float *dst)\n"
"{\n"
" dst[ 0 ] = src1 + src2;\n"
"\n"
"}\n" };
cl_int get_float_result_from_program( cl_context context, cl_command_queue queue, cl_program program, cl_float inA, cl_float inB, cl_float *outValue )
{
cl_int error;
clKernelWrapper kernel = clCreateKernel( program, "sample_test", &error );
test_error( error, "Unable to create kernel from program" );
clMemWrapper outStream = clCreateBuffer( context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_float), NULL, &error );
test_error( error, "Unable to create test buffer" );
error = clSetKernelArg( kernel, 0, sizeof( cl_float ), &inA );
test_error( error, "Unable to set kernel argument" );
error = clSetKernelArg( kernel, 1, sizeof( cl_float ), &inB );
test_error( error, "Unable to set kernel argument" );
error = clSetKernelArg( kernel, 2, sizeof( outStream ), &outStream );
test_error( error, "Unable to set kernel argument" );
size_t threads[1] = { 1 };
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Unable to execute test kernel" );
error = clEnqueueReadBuffer( queue, outStream, true, 0, sizeof( cl_float ), outValue, 0, NULL, NULL );
test_error( error, "Unable to read output array!" );
return CL_SUCCESS;
}
int test_options_denorm_cache(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
clProgramWrapper program;
cl_build_status status;
// If denorms aren't even supported, testing this flag is pointless
cl_device_fp_config floatCaps = 0;
error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(floatCaps), &floatCaps, NULL);
test_error( error, "Unable to get device FP config" );
if( ( floatCaps & CL_FP_DENORM ) == 0 )
{
log_info( "Device does not support denormalized single-precision floats; skipping test.\n" );
return 0;
}
program = clCreateProgramWithSource( context, 1, denorm_test_kernel, NULL, &error );
test_error( error, "Unable to create test program" );
// Build first WITH the denorm flush flag
error = clBuildProgram( program, 1, &deviceID, "-cl-denorms-are-zero", NULL, NULL );
test_error( error, "Test program did not properly build" );
error = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof( status ), &status, NULL );
test_error( error, "Unable to get program build status" );
if( (int)status != CL_BUILD_SUCCESS )
{
print_error( error, "Failed to build with include directory" );
return -1;
}
// Note: the following in floating point is a subnormal number, thus adding two of them together
// should give us a subnormalized result. If denormals are flushed to zero, however, it'll give us zero instead
uint32_t intSubnormal = 0x00000001;
cl_float *input = (cl_float *)&intSubnormal;
cl_float firstResult, secondResult;
error = get_float_result_from_program( context, queue, program, *input, *input, &firstResult );
test_error( error, "Unable to get result from first program" );
// Note: since -cl-denorms-are-zero is a HINT, not a requirement, the result we got could
// either be subnormal (hint ignored) or zero (hint respected). Since either is technically
// valid, there isn't anything we can to do validate results for now
// Rebuild without flushing flag set
error = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
test_error( error, "Test program did not properly rebuild" );
error = get_float_result_from_program( context, queue, program, *input, *input, &secondResult );
test_error( error, "Unable to get result from second program" );
// Now, there are three possiblities here:
// 1. The denorms-are-zero hint is not respected, in which case the first and second result will be identical
// 2. The hint is respected, and the program was properly rebuilt, in which case the first result will be zero and the second non-zero
// 3. The hint is respected, but the program was not properly rebuilt, in which case both results will be zero
// 3 is the only error condition we need to look for
uint32_t *fPtr = (uint32_t *)&firstResult;
uint32_t *sPtr = (uint32_t *)&secondResult;
if( ( *fPtr == 0 ) && ( *sPtr == 0 ) )
{
log_error( "ERROR: Program result didn't change when -cl-denorms-are-zero flag was removed.\n"
"First result (should be zero): 0x%08x, Second result (should be non-zero): 0x%08x\n",
*fPtr, *sPtr );
return -1;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,423 @@
//
// 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 <limits.h>
#include <ctype.h>
#ifndef _WIN32
#include <unistd.h>
#endif
const char *known_extensions[] = {
"cl_khr_fp64",
"cl_khr_global_int32_base_atomics",
"cl_khr_global_int32_extended_atomics",
"cl_khr_local_int32_base_atomics",
"cl_khr_local_int32_extended_atomics",
"cl_khr_int64_base_atomics",
"cl_khr_int64_extended_atomics",
"cl_khr_3d_image_writes",
"cl_khr_byte_addressable_store",
"cl_khr_fp16",
"cl_khr_gl_sharing",
"cl_khr_gl_event",
"cl_khr_d3d10_sharing",
"cl_khr_d3d11_sharing",
"cl_khr_icd",
"cl_khr_dx9_media_sharing",
"cl_khr_depth_images",
"cl_khr_gl_depth_images",
"cl_khr_gl_msaa_sharing",
"cl_khr_image2d_from_buffer",
"cl_khr_initialize_memory",
"cl_khr_terminate_context",
"cl_khr_spir",
"cl_khr_srgb_image_writes",
"cl_khr_subgroups",
"cl_khr_mipmap_image",
"cl_khr_mipmap_image_writes",
"cl_khr_egl_image",
"cl_khr_egl_event",
"cl_khr_il_program",
};
size_t num_known_extensions = sizeof(known_extensions)/sizeof(char*);
size_t first_API_extension = 10;
const char *known_embedded_extensions[] = {
"cles_khr_int64",
NULL
};
typedef enum
{
kUnsupported_extension = -1,
kVendor_extension = 0,
kLanguage_extension = 1,
kAPI_extension = 2
}Extension_Type;
const char *kernel_strings[] = {
"kernel void test(global int *defines)\n{\n",
"#pragma OPENCL EXTENSION %s : enable\n",
"#ifdef %s\n"
" defines[%d] = 1;\n"
"#else\n"
" defines[%d] = 0;\n"
"#endif\n",
"#pragma OPENCL EXTENSION %s : disable\n\n",
"}\n"
};
int test_compiler_defines_for_extensions(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems )
{
int error;
int total_errors = 0;
// Get the extensions string for the device
size_t size;
error = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, NULL, &size);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS size failed");
char *extensions = (char*)malloc(sizeof(char)*(size + 1));
if (extensions == 0) {
log_error("Failed to allocate memory for extensions string.\n");
return -1;
}
memset( extensions, CHAR_MIN, sizeof(char)*(size+1) );
error = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, sizeof(char)*size, extensions, NULL);
test_error(error, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS failed");
// Check to make sure the extension string is NUL terminated.
if( extensions[size] != CHAR_MIN )
{
test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS wrote past the end of the array!" );
return -1;
}
extensions[size] = '\0'; // set last char to NUL to avoid problems with string functions later
// test for termination with '\0'
size_t stringSize = strlen( extensions );
if( stringSize == size )
{
test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS is not NUL terminated!" );
return -1;
}
// Break up the extensions
log_info("Device reports the following extensions:\n");
char *extensions_supported[1024];
Extension_Type extension_type[1024];
int num_of_supported_extensions = 0;
char *currentP = extensions;
memset( extension_type, 0, sizeof( extension_type) );
// loop over extension string
while (currentP != extensions + stringSize)
{
// skip leading white space
while( *currentP == ' ' )
currentP++;
// Exit if end of string
if( *currentP == '\0' )
{
if( currentP != extensions + stringSize)
{
test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS contains a NUL in the middle of the string!" );
return -1;
}
break;
}
// Not space, not end of string, so extension
char *start = currentP; // start of extension name
// loop looking for the end
while (*currentP != ' ' && currentP != extensions + stringSize)
{
// check for non-space white space in the extension name
if( isspace(*currentP) )
{
test_error( -1, "clGetDeviceInfo for CL_DEVICE_EXTENSIONS contains a non-space whitespace in an extension name!" );
return -1;
}
currentP++;
}
// record the extension name
uintptr_t extension_length = (uintptr_t) currentP - (uintptr_t) start;
extensions_supported[ num_of_supported_extensions ] = (char*) malloc( (extension_length + 1) * sizeof( char ) );
if( NULL == extensions_supported[ num_of_supported_extensions ] )
{
log_error( "Error: unable to allocate memory to hold extension name: %ld chars\n", extension_length );
return -1;
}
memcpy( extensions_supported[ num_of_supported_extensions ], start, extension_length * sizeof( char ) );
extensions_supported[ num_of_supported_extensions ][extension_length] = '\0';
// If the extension is a cl_khr extension, make sure it is an approved cl_khr extension -- looking for misspellings here
if( extensions_supported[ num_of_supported_extensions ][0] == 'c' &&
extensions_supported[ num_of_supported_extensions ][1] == 'l' &&
extensions_supported[ num_of_supported_extensions ][2] == '_' &&
extensions_supported[ num_of_supported_extensions ][3] == 'k' &&
extensions_supported[ num_of_supported_extensions ][4] == 'h' &&
extensions_supported[ num_of_supported_extensions ][5] == 'r' &&
extensions_supported[ num_of_supported_extensions ][6] == '_' )
{
size_t ii;
for( ii = 0; ii < num_known_extensions; ii++ )
{
if( 0 == strcmp( known_extensions[ii], extensions_supported[ num_of_supported_extensions ] ) )
break;
}
if( ii == num_known_extensions )
{
log_error( "FAIL: Extension %s is not in the list of approved Khronos extensions!", extensions_supported[ num_of_supported_extensions ] );
return -1;
}
}
// Is it an embedded extension?
else if( memcmp( extensions_supported[ num_of_supported_extensions ], "cles_khr_", 9 ) == 0 )
{
// Yes, but is it a known one?
size_t ii;
for( ii = 0; known_embedded_extensions[ ii ] != NULL; ii++ )
{
if( strcmp( known_embedded_extensions[ ii ], extensions_supported[ num_of_supported_extensions ] ) == 0 )
break;
}
if( known_embedded_extensions[ ii ] == NULL )
{
log_error( "FAIL: Extension %s is not in the list of approved Khronos embedded extensions!", extensions_supported[ num_of_supported_extensions ] );
return -1;
}
// It's approved, but are we even an embedded system?
char profileStr[128] = "";
error = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL );
test_error( error, "Unable to get CL_DEVICE_PROFILE to validate embedded extension name" );
if( strcmp( profileStr, "EMBEDDED_PROFILE" ) != 0 )
{
log_error( "FAIL: Extension %s is an approved embedded extension, but on a non-embedded profile!", extensions_supported[ num_of_supported_extensions ] );
return -1;
}
}
else
{ // All other extensions must be of the form cl_<vendor_name>_<name>
if( extensions_supported[ num_of_supported_extensions ][0] != 'c' ||
extensions_supported[ num_of_supported_extensions ][1] != 'l' ||
extensions_supported[ num_of_supported_extensions ][2] != '_' )
{
log_error( "FAIL: Extension %s doesn't start with \"cl_\"!", extensions_supported[ num_of_supported_extensions ] );
return -1;
}
if( extensions_supported[ num_of_supported_extensions ][3] == '_' || extensions_supported[ num_of_supported_extensions ][3] == '\0' )
{
log_error( "FAIL: Vendor name is missing in extension %s!", extensions_supported[ num_of_supported_extensions ] );
return -1;
}
// look for the second underscore for name
char *p = extensions_supported[ num_of_supported_extensions ] + 4;
while( *p != '\0' && *p != '_' )
p++;
if( *p != '_' || p[1] == '\0')
{
log_error( "FAIL: extension name is missing in extension %s!", extensions_supported[ num_of_supported_extensions ] );
return -1;
}
}
num_of_supported_extensions++;
}
// Build a list of the known extensions that are not supported by the device
char *extensions_not_supported[1024];
int num_not_supported_extensions = 0;
for( int i = 0; i < num_of_supported_extensions; i++ )
{
int is_supported = 0;
for( size_t j = 0; j < num_known_extensions; j++ )
{
if( strcmp( extensions_supported[ i ], known_extensions[ j ] ) == 0 )
{
extension_type[ i ] = ( j < first_API_extension ) ? kLanguage_extension : kAPI_extension;
is_supported = 1;
break;
}
}
if( !is_supported )
{
for( int j = 0; known_embedded_extensions[ j ] != NULL; j++ )
{
if( strcmp( extensions_supported[ i ], known_embedded_extensions[ j ] ) == 0 )
{
extension_type[ i ] = kLanguage_extension;
is_supported = 1;
break;
}
}
}
if (!is_supported) {
extensions_not_supported[num_not_supported_extensions] = (char*)malloc(strlen(extensions_supported[i])+1);
strcpy(extensions_not_supported[num_not_supported_extensions], extensions_supported[i]);
num_not_supported_extensions++;
}
}
for (int i=0; i<num_of_supported_extensions; i++) {
log_info("%40s -- Supported\n", extensions_supported[i]);
}
for (int i=0; i<num_not_supported_extensions; i++) {
log_info("%40s -- Not Supported\n", extensions_not_supported[i]);
}
// Build the kernel
char *kernel_code = (char*)malloc(1025*256*(num_not_supported_extensions+num_of_supported_extensions));
memset(kernel_code, 0, 1025*256*(num_not_supported_extensions+num_of_supported_extensions));
int i, index = 0;
strcat(kernel_code, kernel_strings[0]);
for (i=0; i<num_of_supported_extensions; i++, index++) {
if (extension_type[i] == kLanguage_extension)
sprintf(kernel_code + strlen(kernel_code), kernel_strings[1], extensions_supported[i]);
sprintf(kernel_code + strlen(kernel_code), kernel_strings[2], extensions_supported[i], index, index );
if (extension_type[i] == kLanguage_extension)
sprintf(kernel_code + strlen(kernel_code), kernel_strings[3], extensions_supported[i] );
}
for ( i = 0; i<num_not_supported_extensions; i++, index++) {
sprintf(kernel_code + strlen(kernel_code), kernel_strings[2], extensions_not_supported[i], index, index );
}
strcat(kernel_code, kernel_strings[4]);
// Now we need to execute the kernel
cl_mem defines;
cl_int *data;
cl_program program;
cl_kernel kernel;
error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&kernel_code, "test");
test_error(error, "create_single_kernel_helper failed");
data = (cl_int*)malloc(sizeof(cl_int)*(num_not_supported_extensions+num_of_supported_extensions));
memset(data, 0, sizeof(cl_int)*(num_not_supported_extensions+num_of_supported_extensions));
defines = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
sizeof(cl_int)*(num_not_supported_extensions+num_of_supported_extensions), data, &error);
test_error(error, "clCreateBuffer failed");
error = clSetKernelArg(kernel, 0, sizeof(defines), &defines);
test_error(error, "clSetKernelArg failed");
size_t global_size = 1;
error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL);
test_error(error, "clEnqueueNDRangeKernel failed");
error = clEnqueueReadBuffer(queue, defines, CL_TRUE, 0, sizeof(cl_int)*(num_not_supported_extensions+num_of_supported_extensions),
data, 0, NULL, NULL);
test_error(error, "clEnqueueReadBuffer failed");
// Report what the compiler reported
log_info("\nCompiler reported the following extensions defined in the OpenCL C kernel environment:\n");
index = 0;
int total_supported = 0;
for (int i=0; i<num_of_supported_extensions; i++, index++) {
if (data[index] == 1) {
log_info("\t%s\n", extensions_supported[i]);
total_supported++;
}
}
for (int i=0; i<num_not_supported_extensions; i++, index++) {
if (data[index] == 1) {
log_info("\t%s\n", extensions_not_supported[i]);
total_supported++;
}
}
if (total_supported == 0)
log_info("\t(none)\n");
// Count the errors
index = 0;
int unknown = 0;
for ( i=0; i<num_of_supported_extensions; i++)
{
if (data[i] != 1)
{
switch( extension_type[i] )
{
case kLanguage_extension:
log_error("ERROR: Supported extension %s not defined in kernel.\n", extensions_supported[i]);
total_errors++;
break;
case kVendor_extension:
unknown++;
break;
case kAPI_extension:
break;
default:
log_error( "ERROR: internal test error in extension detection. This is probably a bug in the test.\n" );
break;
}
}
}
if(unknown)
{
log_info( "\nThe following non-KHR extensions are supported but do not add a preprocessor symbol to OpenCL C.\n" );
for (int z=0; z<num_of_supported_extensions; z++)
{
if (data[z] != 1 && extension_type[z] == kVendor_extension )
log_info( "\t%s\n", extensions_supported[z]);
}
}
for ( ; i<num_not_supported_extensions; i++) {
if (data[i] != 0) {
log_error("ERROR: Unsupported extension %s is defined in kernel.\n", extensions_not_supported[i]);
total_errors++;
}
}
log_info("\n");
// cleanup
free(data);
free(kernel_code);
for(i=0; i<num_of_supported_extensions; i++) {
free(extensions_supported[i]);
}
free(extensions);
if( defines ) {
error = clReleaseMemObject( defines );
test_error( error, "Unable to release memory object" );
}
if (total_errors)
return -1;
return 0;
}

View File

@@ -0,0 +1,101 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#if (defined( __APPLE__ ) || defined( __linux__ ))
#include <unistd.h>
#endif
const char * image_supported_source = "kernel void enabled(global int * buf) { \r\n" \
"int n = get_global_id(0); \r\n"\
"buf[n] = 0; \r\n "\
"#ifndef __IMAGE_SUPPORT__ \r\n" \
"ERROR; \r\n"\
"#endif \r\n"\
"\r\n } \r\n";
const char * image_not_supported_source = "kernel void not_enabled(global int * buf) { \r\n" \
"int n = get_global_id(0); \r\n"\
"buf[n] = 0; \r\n "\
"#ifdef __IMAGE_SUPPORT__ \r\n" \
"ERROR; \r\n"\
"#endif \r\n"\
"\r\n } \r\n";
int test_image_macro(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
cl_bool image_support;
char buf[256];
int status;
cl_program program;
status = clGetDeviceInfo( deviceID, CL_DEVICE_NAME, sizeof( buf ), buf, NULL );
if( status )
{
log_error( "getting device info (name): %d\n", status );
exit(-1);
}
status = clGetDeviceInfo( deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof( image_support ), &image_support, NULL );
if( status )
{
log_error( "getting device info (image support): %d\n", status );
return status;
}
if( (image_support == CL_TRUE) )
{
program = clCreateProgramWithSource( context, 1, (const char**) &image_supported_source, NULL, &status );
if( status )
{
log_error ("Failure creating program, [%d] \n", status );
return status;
}
status = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
if( status )
log_error("CL_DEVICE_IMAGE_SUPPORT is set, __IMAGE_SUPPORT__ macro not set \n");
else
log_info("CL_DEVICE_IMAGE_SUPPORT is set, __IMAGE_SUPPORT__ macro is set \n");
}
else
{
program = clCreateProgramWithSource( context, 1, (const char**) &image_not_supported_source, NULL, &status );
if( status )
{
log_error ("Failure creating program, [%d] \n", status );
return status;
}
status = clBuildProgram( program, 1, &deviceID, NULL, NULL, NULL );
if( status )
log_error("CL_DEVICE_IMAGE_SUPPORT not set, __IMAGE_SUPPORT__ macro is set \n");
else
log_info("CL_DEVICE_IMAGE_SUPPORT not set, __IMAGE_SUPPORT__ macro not set \n");
}
status = clReleaseProgram( program );
if( status )
{
log_error ("Unable to release program object, [%d] \n", status );
return status;
}
return status;
}

View File

@@ -0,0 +1,290 @@
//
// 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 <vector>
const char *pragma_unroll_kernels[] = {
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" __attribute__((opencl_unroll_hint))\n"
" for(size_t i = 0; i < 100; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" __attribute__((opencl_unroll_hint(1)))\n"
" for(size_t i = 0; i < 100; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" __attribute__((opencl_unroll_hint(10)))\n"
" for(size_t i = 0; i < 100; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" __attribute__((opencl_unroll_hint(100)))\n"
" for(size_t i = 0; i < 100; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" __attribute__((opencl_unroll_hint))\n"
" for(size_t i = 0; i < n; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" __attribute__((opencl_unroll_hint(1)))\n"
" for(size_t i = 0; i < n; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" __attribute__((opencl_unroll_hint(10)))\n"
" for(size_t i = 0; i < n; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" __attribute__((opencl_unroll_hint(100)))\n"
" for(size_t i = 0; i < n; ++i)\n"
" dst[i] = i;\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint))\n"
" while(i < 100) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(1)))\n"
" while(i < 100) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(10)))\n"
" while(i < 100) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(100)))\n"
" while(i < 100) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint))\n"
" while(i < n) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(1)))\n"
" while(i < n) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(10)))\n"
" while(i < n) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(100)))\n"
" while(i < n) {\n"
" dst[i] = i;\n"
" ++i;\n"
" }\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < 100);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(1)))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < 100);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(10)))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < 100);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(100)))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < 100);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < n);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(1)))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < n);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(10)))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < n);\n"
"}\n",
"__kernel void pragma_unroll(__global uint *dst)\n"
"{\n"
" size_t tid = get_global_id(0);\n"
" size_t n = (tid + 1) * 100;\n"
" size_t i = 0;\n"
" __attribute__((opencl_unroll_hint(100)))\n"
" do {\n"
" dst[i] = i;\n"
" ++i;\n"
" } while(i < n);\n"
"}\n",
};
int test_pragma_unroll(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
const size_t ELEMENT_NUM = 100;
const size_t KERNEL_NUM = 24;
cl_int error;
//execute all kernels and check if the results are as expected
for (size_t kernelIdx = 0; kernelIdx < KERNEL_NUM; ++kernelIdx) {
clProgramWrapper program;
clKernelWrapper kernel;
if( create_single_kernel_helper_with_build_options( context, &program, &kernel, 1, (const char **)&pragma_unroll_kernels[kernelIdx], "pragma_unroll", "-cl-std=CL2.0" ) ) {
log_error("The program we attempted to compile was: \n%s\n", pragma_unroll_kernels[kernelIdx]);
return -1;
}
clMemWrapper buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, ELEMENT_NUM * sizeof(cl_uint), NULL, &error);
test_error(error, "clCreateBuffer failed");
error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer);
test_error(error, "clSetKernelArg failed");
//only one thread should be enough to verify if kernel is fully functional
size_t workSize = 1;
error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &workSize, NULL, 0, NULL, NULL);
test_error(error, "clEnqueueNDRangeKernel failed");
std::vector<cl_uint> results(ELEMENT_NUM, 0);
error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, ELEMENT_NUM * sizeof(cl_uint), &results[0], 0, NULL, NULL);
test_error(error, "clEnqueueReadBuffer failed");
for (size_t i = 0; i < ELEMENT_NUM; ++i) {
if (results[i] != i) {
log_error("Kernel %d returned invalid result. Test: %d, expected: %d\n", kernelIdx + 1, results[i], i);
return -1;
}
}
}
return 0;
}

View File

@@ -0,0 +1,342 @@
//
// 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/os_helpers.h"
extern cl_uint gRandomSeed;
const char *define_kernel_code[] = {
" #define VALUE\n"
"__kernel void define_test(__global int *src, __global int *dstA, __global int *dstB)\n"
"{\n"
" int tid = get_global_id(0);\n"
"#ifdef VALUE\n"
" dstA[tid] = src[tid] * 2;\n"
"#else\n"
" dstA[tid] = src[tid] * 4;\n"
"#endif\n"
"\n"
"#undef VALUE\n"
"#ifdef VALUE\n"
" dstB[tid] = src[tid] * 2;\n"
"#else\n"
" dstB[tid] = src[tid] * 4;\n"
"#endif\n"
"\n"
"}\n"};
int test_preprocessor_define_udef(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
cl_int error;
clKernelWrapper kernel;
clProgramWrapper program;
clMemWrapper buffer[3];
cl_int *srcData, *resultData;
int i;
MTdata d;
error = create_single_kernel_helper(context, &program, &kernel, 1, define_kernel_code, "define_test");
if (error)
return -1;
buffer[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
buffer[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
buffer[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
srcData = (cl_int*)malloc(sizeof(cl_int)*num_elements);
if (srcData == NULL) {
log_error("Failed to allocate storage for source data (%d cl_ints).\n", num_elements);
return -1;
}
d = init_genrand( gRandomSeed );
for (i=0; i<num_elements; i++)
srcData[i] = (int)get_random_float(-1024, 1024,d);
free_mtdata(d); d = NULL;
resultData = (cl_int*)malloc(sizeof(cl_int)*num_elements);
if (resultData == NULL) {
free(srcData);
log_error("Failed to allocate storage for result data (%d cl_ints).\n", num_elements);
return -1;
}
error = clSetKernelArg(kernel, 0, sizeof(buffer[0]), &buffer[0]);
test_error(error, "clSetKernelArg failed");
error = clSetKernelArg(kernel, 1, sizeof(buffer[1]), &buffer[1]);
test_error(error, "clSetKernelArg failed");
error = clSetKernelArg(kernel, 2, sizeof(buffer[2]), &buffer[2]);
test_error(error, "clSetKernelArg failed");
error = clEnqueueWriteBuffer(queue, buffer[0], CL_TRUE, 0, num_elements*sizeof(cl_int), srcData, 0, NULL, NULL);
test_error(error, "clEnqueueWriteBuffer failed");
size_t threads[3] = {num_elements, 0, 0};
error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL);
test_error(error, "clEnqueueNDRangeKernel failed");
error = clEnqueueReadBuffer(queue, buffer[1], CL_TRUE, 0, num_elements*sizeof(cl_int), resultData, 0, NULL, NULL);
test_error(error, "clEnqueueReadBuffer failed");
for (i=0; i<num_elements; i++)
if (resultData[i] != srcData[i]*2) {
free(srcData);
free(resultData);
return -1;
}
error = clEnqueueReadBuffer(queue, buffer[2], CL_TRUE, 0, num_elements*sizeof(cl_int), resultData, 0, NULL, NULL);
test_error(error, "clEnqueueReadBuffer failed");
for (i=0; i<num_elements; i++)
if (resultData[i] != srcData[i]*4) {
free(srcData);
free(resultData);
return -1;
}
free(srcData);
free(resultData);
return 0;
}
const char *include_kernel_code =
"#include \"%s\"\n"
"__kernel void include_test(__global int *src, __global int *dstA)\n"
"{\n"
" int tid = get_global_id(0);\n"
"#ifdef HEADER_FOUND\n"
" dstA[tid] = HEADER_FOUND;\n"
"#else\n"
" dstA[tid] = 0;\n"
"#endif\n"
"\n"
"}\n";
int test_preprocessor_include(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
cl_int error;
clKernelWrapper kernel;
clProgramWrapper program;
clMemWrapper buffer[2];
cl_int *resultData;
int i;
char include_dir[4096] = {0};
char include_kernel[4096] = {0};
char const * sep = get_dir_sep();
char const * path = get_exe_dir();
/* Build with the include directory defined */
sprintf(include_dir,"%s%sincludeTestDirectory%stestIncludeFile.h", path, sep, sep);
sprintf(include_kernel, include_kernel_code, include_dir);
free( (void *) sep );
free( (void *) path );
const char* test_kernel[] = { include_kernel, 0 };
error = create_single_kernel_helper(context, &program, &kernel, 1, test_kernel, "include_test");
if (error)
return -1;
buffer[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
buffer[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
resultData = (cl_int*)malloc(sizeof(cl_int)*num_elements);
if (resultData == NULL) {
log_error("Failed to allocate storage for result data (%d cl_ints).\n", num_elements);
return -1;
}
error = clSetKernelArg(kernel, 0, sizeof(buffer[0]), &buffer[0]);
test_error(error, "clSetKernelArg failed");
error = clSetKernelArg(kernel, 1, sizeof(buffer[1]), &buffer[1]);
test_error(error, "clSetKernelArg failed");
size_t threads[3] = {num_elements, 0, 0};
error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL);
test_error(error, "clEnqueueNDRangeKernel failed");
error = clEnqueueReadBuffer(queue, buffer[1], CL_TRUE, 0, num_elements*sizeof(cl_int), resultData, 0, NULL, NULL);
test_error(error, "clEnqueueReadBuffer failed");
for (i=0; i<num_elements; i++)
if (resultData[i] != 12) {
free(resultData);
return -1;
}
free(resultData);
return 0;
}
const char *line_error_kernel_code[] = {
"__kernel void line_error_test(__global int *dstA)\n"
"{\n"
" int tid = get_global_id(0);\n"
"#line 124 \"fictitious/file/name.c\" \n"
"#error some error\n"
" dstA[tid] = tid;\n"
"\n"
"}\n"};
int test_preprocessor_line_error(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
cl_int error, error2;
clKernelWrapper kernel;
clProgramWrapper program;
clMemWrapper buffer[2];
char buildLog[ 1024 * 128 ];
log_info("test_preprocessor_line_error may report spurious ERRORS in the conformance log.\n");
/* Create the program object from source */
program = clCreateProgramWithSource( context, 1, line_error_kernel_code, NULL, &error );
test_error(error, "clCreateProgramWithSource failed");
/* Compile the program */
error2 = clBuildProgram( program, 0, NULL, NULL, NULL, NULL );
if (error2) {
log_info("Build error detected at clBuildProgram.");
} else {
log_info("Error not reported by clBuildProgram.\n");
}
cl_build_status status;
error = clGetProgramBuildInfo(program, deviceID, CL_PROGRAM_BUILD_STATUS, sizeof(status), &status, NULL);
test_error(error, "clGetProgramBuildInfo failed for CL_PROGRAM_BUILD_STATUS");
if (status != CL_BUILD_ERROR) {
log_error("Build status did not return CL_BUILD_ERROR for a program with #error defined.\n");
return -1;
} else if (status == CL_BUILD_ERROR || error2) {
error2 = clGetProgramBuildInfo( program, deviceID, CL_PROGRAM_BUILD_LOG, sizeof( buildLog ), buildLog, NULL );
test_error( error2, "Unable to get program build log" );
log_info("Build failed as expected with #error in source:\n");
log_info( "Build log is: ------------\n" );
log_info( "%s\n", buildLog );
log_info( "Original source is: ------------\n" );
log_info( "%s", line_error_kernel_code[0] );
log_info( "\n----------\n" );
if (strstr(buildLog, "fictitious/file/name.c")) {
log_info("Found file name from #line param in log output.\n");
} else {
log_info("WARNING: Did not find file name from #line param in log output.\n");
}
if (strstr(buildLog, "124")) {
log_info("Found line number from #line param in log output.\n");
} else {
log_info("WARNING: Did not find line number from #line param in log output.\n");
}
log_info("test_preprocessor_line_error PASSED.\n");
return 0;
}
/* And create a kernel from it */
kernel = clCreateKernel( program, "line_error_test", &error );
test_error(error, "clCreateKernel failed");
buffer[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
error = clSetKernelArg(kernel, 0, sizeof(buffer[0]), &buffer[0]);
test_error(error, "clSetKernelArg failed");
size_t threads[3] = {num_elements, 0, 0};
error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL);
test_error(error, "clEnqueueNDRangeKernel failed");
log_error("Program built and ran with #error defined.");
return -1;
}
const char *pragma_kernel_code[] = {
"__kernel void pragma_test(__global int *dstA)\n"
"{\n"
"#pragma A fool thinks himself to be wise, but a wise man knows himself to be a fool.\n"
" int tid = get_global_id(0);\n"
"#pragma\n"
" dstA[tid] = tid;\n"
"#pragma mark Though I am not naturally honest, I am so sometimes by chance.\n"
"\n"
"}\n"};
int test_preprocessor_pragma(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
cl_int error;
clKernelWrapper kernel;
clProgramWrapper program;
clMemWrapper buffer[2];
cl_int *resultData;
int i;
error = create_single_kernel_helper(context, &program, &kernel, 1, pragma_kernel_code, "pragma_test");
if (error)
return -1;
buffer[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, num_elements*sizeof(cl_int), NULL, &error);
test_error( error, "clCreateBuffer failed");
error = clSetKernelArg(kernel, 0, sizeof(buffer[0]), &buffer[0]);
test_error(error, "clSetKernelArg failed");
size_t threads[3] = {num_elements, 0, 0};
error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL);
test_error(error, "clEnqueueNDRangeKernel failed");
resultData = (cl_int*)malloc(sizeof(cl_int)*num_elements);
if (resultData == NULL) {
log_error("Failed to allocate storage for result data (%d cl_ints).\n", num_elements);
return -1;
}
error = clEnqueueReadBuffer(queue, buffer[0], CL_TRUE, 0, num_elements*sizeof(cl_int), resultData, 0, NULL, NULL);
test_error(error, "clEnqueueReadBuffer failed");
for (i=0; i<num_elements; i++)
if (resultData[i] != i) {
free(resultData);
return -1;
}
free(resultData);
return 0;
}