Initial open source release of OpenCL 2.2 CTS.

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

View File

@@ -0,0 +1,12 @@
set(MODULE_NAME CPP_API)
set(${MODULE_NAME}_SOURCES
main.cpp
../../../test_common/harness/errorHelpers.c
../../../test_common/harness/testHarness.c
../../../test_common/harness/kernelHelpers.c
../../../test_common/harness/msvc9.c
../../../test_common/harness/parseParameters.cpp
)
include(../../CMakeCommon.txt)

View File

@@ -0,0 +1,32 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "../common.hpp"
#include "test_spec_consts.hpp"
#include "test_ctors_dtors.hpp"
#include "test_ctors.hpp"
#include "test_dtors.hpp"
int main(int argc, const char *argv[])
{
// Get list to all test functions
std::vector<basefn> testfn_list = autotest::test_suite::get_test_functions();
// Get names of all test functions
std::vector<std::string> testfn_names = autotest::test_suite::get_test_names();
// Create a vector of pointers to the names test functions
std::vector<const char *> testfn_names_c_str = autotest::get_strings_ptrs(testfn_names);
return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0);
}

View File

@@ -0,0 +1,481 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_HPP
#define TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_HPP
#include <vector>
#include <limits>
#include <algorithm>
#include <numeric>
#include "../common.hpp"
// TEST 1
// Verify that constructors are executed before any kernel is executed.
// Verify that when present, multiple constructors are executed. The order between
// constructors is undefined, but they should all execute.
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * kernel_test_ctors_executed =
"__kernel void test_ctors_executed(global uint *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
const char * kernel_test_ctors_executed_multiple_ctors =
"__kernel void test_ctors_executed_multiple_ctors(global uint *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * kernel_test_ctors_executed =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"using namespace cl;\n"
"struct ctor_test_class {\n"
// non-trivial ctor
" ctor_test_class(int y) { x = y;};\n"
" int x;\n"
"};\n"
// global scope program variable
"ctor_test_class global_var(int(0xbeefbeef));\n"
"__kernel void test_ctors_executed(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(global_var.x != int(0xbeefbeef)) result = 1;\n"
" output[gid] = result;\n"
"}\n"
;
const char * kernel_test_ctors_executed_multiple_ctors =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"#include <opencl_limits>\n"
"using namespace cl;\n"
"template<class T>\n"
"struct ctor_test_class {\n"
// non-trivial ctor
" ctor_test_class(T y) { x = y;};\n"
" T x;\n"
"};\n"
// global scope program variables
"ctor_test_class<int> global_var0(int(0xbeefbeef));\n"
"ctor_test_class<uint> global_var1(uint(0xbeefbeefU));\n"
"ctor_test_class<float> global_var2(float(FLT_MAX));\n"
"__kernel void test_ctors_executed_multiple_ctors(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(global_var0.x != int(0xbeefbeef)) result = 1;\n"
" if(global_var1.x != uint(0xbeefbeefU)) result = 1;\n"
" if(global_var2.x != float(FLT_MAX)) result = 1;\n"
" output[gid] = result;\n"
"}\n"
;
#endif
int test_ctors_execution(cl_device_id device,
cl_context context,
cl_command_queue queue,
int count,
std::string kernel_name,
const char * kernel_source)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(context, &program, &kernel, kernel_source, kernel_name);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(context, &program, &kernel, kernel_source, kernel_name, "", false);
RETURN_ON_ERROR(error)
// Normal run
#else
error = create_opencl_kernel(context, &program, &kernel, kernel_source, kernel_name);
RETURN_ON_ERROR(error)
#endif
// host vector, size == count, output[0...count-1] == 1
std::vector<cl_uint> output(count, cl_uint(1));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_uint) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_uint) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
size_t sum = std::accumulate(output.begin(), output.end(), size_t(0));
if(sum != 0)
{
error = -1;
CHECK_ERROR_MSG(error, "Test %s failed.", kernel_name.c_str());
}
clReleaseMemObject(output_buffer);
clReleaseKernel(kernel);
clReleaseProgram(program);
return error;
}
AUTO_TEST_CASE(test_global_scope_ctors_executed)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
int local_error = CL_SUCCESS;
local_error = test_ctors_execution(
device, context, queue, count,
"test_ctors_executed", kernel_test_ctors_executed
);
CHECK_ERROR(local_error);
error |= local_error;
local_error = test_ctors_execution(
device, context, queue, count,
"test_ctors_executed_multiple_ctors", kernel_test_ctors_executed_multiple_ctors
);
CHECK_ERROR(local_error);
error |= local_error;
if(error != CL_SUCCESS)
{
return -1;
}
return error;
}
// TEST 2
// Verify that constructors are only executed once when multiple kernels from a program are executed.
// How: The first kernel (test_ctors_executed_once_set) is run once. It changes values of program scope
// variables, then the second kernel is run multiple times, each time verifying that global variables
// have correct values (the second kernel should observe the values assigned by the first kernel, not
// by the constructors).
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * program_test_ctors_executed_once =
"__kernel void test_ctors_executed_once_set()\n"
"{\n"
"}\n"
"__kernel void test_ctors_executed_once_read(global uint *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * program_test_ctors_executed_once =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"using namespace cl;\n"
// struct template
"template<class T>\n"
"struct ctor_test_class {\n"
// non-trivial ctor
" ctor_test_class(T y) { x = y;};\n"
" T x;\n"
"};\n"
// global scope program variables
"ctor_test_class<int> global_var0(int(0));\n"
"ctor_test_class<uint> global_var1(uint(0));\n"
"__kernel void test_ctors_executed_once_set()\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" if(gid == 0) {\n"
" global_var0.x = int(0xbeefbeef);\n"
" global_var1.x = uint(0xbeefbeefU);\n"
" }\n"
"}\n\n"
"__kernel void test_ctors_executed_once_read(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(global_var0.x != int(0xbeefbeef)) result = 1;\n"
" if(global_var1.x != uint(0xbeefbeefU)) result = 1;\n"
" output[gid] = result;\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_global_scope_ctors_executed_once)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel_set_global_vars;
cl_kernel kernel_read_global_vars;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(
context, &program, &kernel_set_global_vars,
program_test_ctors_executed_once, "test_ctors_executed_once_set"
);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(
context, &program, &kernel_set_global_vars,
program_test_ctors_executed_once, "test_ctors_executed_once_set", "", false
);
RETURN_ON_ERROR(error)
// Get the second kernel
kernel_read_global_vars = clCreateKernel(program, "test_ctors_executed_once_read", &error);
RETURN_ON_CL_ERROR(error, "clCreateKernel");
// Normal run
#else
error = create_opencl_kernel(
context, &program, &kernel_set_global_vars,
program_test_ctors_executed_once, "test_ctors_executed_once_set"
);
RETURN_ON_ERROR(error)
// Get the second kernel
kernel_read_global_vars = clCreateKernel(program, "test_ctors_executed_once_read", &error);
RETURN_ON_CL_ERROR(error, "clCreateKernel");
#endif
// Execute kernel_set_global_vars
work_size[0] = count;
error = clEnqueueNDRangeKernel(queue, kernel_set_global_vars, dim, NULL, work_size, NULL, 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
// Execute kernel_read_global_vars 4 times, each time we check if
// global variables have correct values.
// host vector, size == count, output[0...count-1] == 1
std::vector<cl_uint> output(count, cl_uint(1));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
for(size_t i = 0; i < 4; i++)
{
std::fill(output.begin(), output.end(), cl_uint(1));
error = clEnqueueWriteBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel_read_global_vars, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(
queue, kernel_read_global_vars,
dim, NULL, work_size, NULL,
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
error = clEnqueueReadBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
size_t sum = std::accumulate(output.begin(), output.end(), size_t(0));
if(sum != 0)
{
error = -1;
CHECK_ERROR_MSG(error, "Test test_ctors_executed_onces failed.");
}
}
clReleaseMemObject(output_buffer);
clReleaseKernel(kernel_set_global_vars);
clReleaseKernel(kernel_read_global_vars);
clReleaseProgram(program);
return error;
}
// TEST3
// Verify that when constructor is executed, the ND-range used is (1,1,1).
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * program_test_ctors_ndrange =
"__kernel void test_ctors_ndrange(global int *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * program_test_ctors_ndrange =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"using namespace cl;\n"
// struct
"struct ctor_test_class {\n"
// non-trivial ctor
" ctor_test_class() {\n"
" x = get_global_size(0);\n"
" y = get_global_size(1);\n"
" z = get_global_size(2);\n"
" };\n"
" ulong x;\n"
" ulong y;\n"
" ulong z;\n"
// return true if the ND-range used when ctor was exectured was
// (1, 1, 1); otherwise - false
" bool check() { return (x == 1) && (y == 1) && (z == 1);}"
"};\n"
// global scope program variables
"ctor_test_class global_var0;\n"
"ctor_test_class global_var1;\n"
"__kernel void test_ctors_ndrange(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(!global_var0.check()) result = 1;\n"
" if(!global_var1.check()) result = 1;\n"
" output[gid] = result;\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_global_scope_ctors_ndrange)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_ctors_ndrange, "test_ctors_ndrange"
);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_ctors_ndrange, "test_ctors_ndrange", "", false
);
RETURN_ON_ERROR(error)
// Normal run
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_ctors_ndrange, "test_ctors_ndrange"
);
RETURN_ON_ERROR(error)
#endif
// host vector, size == count, output[0...count-1] == 1
std::vector<cl_uint> output(count, cl_uint(1));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(
queue, kernel,
dim, NULL, work_size, NULL,
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
error = clEnqueueReadBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
size_t sum = std::accumulate(output.begin(), output.end(), size_t(0));
if(sum != 0)
{
error = -1;
CHECK_ERROR_MSG(error, "Test test_ctors_executed_ndrange failed.");
}
clReleaseMemObject(output_buffer);
clReleaseKernel(kernel);
clReleaseProgram(program);
return error;
}
#endif // TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_HPP

View File

@@ -0,0 +1,185 @@
//
// 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 TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_DTORS_HPP
#define TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_DTORS_HPP
#include <vector>
#include <limits>
#include <algorithm>
#include "../common.hpp"
// Verify queries clGetProgramInfo correctly return the presence of constructors and/or destructors
// in the program (using option CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT/CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT)
// (both are present, either one is present, none is present).
std::string generate_ctor_dtor_program(const bool ctor, const bool dtor)
{
std::string program;
if(ctor)
{
program +=
"struct ctor_test_class {\n"
// non-trivial ctor
" ctor_test_class(int y) { x = y;};\n"
" int x;\n"
"};\n"
"ctor_test_class ctor = ctor_test_class(1024);\n"
;
}
if(dtor)
{
program +=
"struct dtor_test_class {\n"
// non-trivial dtor
" ~dtor_test_class() { x = -1024; };\n"
" int x;\n"
"};\n"
"dtor_test_class dtor;\n"
;
}
program += "__kernel void test_ctor_dtor()\n {\n }\n";
return program;
}
int test_get_program_info_global_ctors_dtors_present(cl_device_id device,
cl_context context,
cl_command_queue queue,
const bool ctor,
const bool dtor)
{
int error = CL_SUCCESS;
cl_program program;
// program source and options
std::string options = "";
std::string source = generate_ctor_dtor_program(ctor, dtor);
const char * source_ptr = source.c_str();
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
// Create program
error = create_openclcpp_program(context, &program, 1, &source_ptr, options.c_str());
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
return CL_SUCCESS;
// Normal run
#else
// Create program
error = create_openclcpp_program(context, &program, 1, &source_ptr, options.c_str());
RETURN_ON_ERROR(error)
#endif
// CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT cl_bool
// This indicates that the program object contains non-trivial constructor(s) that will be
// executed by runtime before any kernel from the program is executed.
// CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT cl_bool
// This indicates that the program object contains non-trivial destructor(s) that will be
// executed by runtime when program is destroyed.
// CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT
cl_bool ctors_present;
size_t cl_bool_size;
error = clGetProgramInfo(
program,
CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT,
sizeof(cl_bool),
static_cast<void*>(&ctors_present),
&cl_bool_size
);
RETURN_ON_CL_ERROR(error, "clGetProgramInfo")
if(cl_bool_size != sizeof(cl_bool))
{
error = -1;
CHECK_ERROR_MSG(-1, "Test failed, param_value_size_ret != sizeof(cl_bool) (%lu != %lu).", cl_bool_size, sizeof(cl_bool));
}
if(ctor && ctors_present != CL_TRUE)
{
error = -1;
CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT: 0, should be: 1.");
}
else if(!ctor && ctors_present == CL_TRUE)
{
error = -1;
CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT: 1, should be: 0.");
}
// CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT
cl_bool dtors_present = 0;
error = clGetProgramInfo(
program,
CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT,
sizeof(cl_bool),
static_cast<void*>(&ctors_present),
&cl_bool_size
);
RETURN_ON_CL_ERROR(error, "clGetProgramInfo")
if(cl_bool_size != sizeof(cl_bool))
{
error = -1;
CHECK_ERROR_MSG(-1, "Test failed, param_value_size_ret != sizeof(cl_bool) (%lu != %lu).", cl_bool_size, sizeof(cl_bool));
}
if(dtor && dtors_present != CL_TRUE)
{
error = -1;
CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT: 0, should be: 1.");
}
else if(!dtor && dtors_present == CL_TRUE)
{
error = -1;
CHECK_ERROR_MSG(-1, "Test failed, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT: 1, should be: 0.");
}
clReleaseProgram(program);
return error;
}
AUTO_TEST_CASE(test_global_scope_ctors_dtors_present)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
int last_error = CL_SUCCESS;
// both present
last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, true, true);
CHECK_ERROR(last_error);
error |= last_error;
// dtor
last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, false, true);
CHECK_ERROR(last_error);
error |= last_error;
// ctor
last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, true, false);
CHECK_ERROR(last_error);
error |= last_error;
// none present
last_error = test_get_program_info_global_ctors_dtors_present(device, context, queue, false, false);
CHECK_ERROR(last_error);
error |= last_error;
if(error != CL_SUCCESS)
{
return -1;
}
return error;
}
#endif // TEST_CONFORMANCE_CLCPP_API_TEST_CTORS_DTORS_HPP

View File

@@ -0,0 +1,553 @@
//
// 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 TEST_CONFORMANCE_CLCPP_API_TEST_DTORS_HPP
#define TEST_CONFORMANCE_CLCPP_API_TEST_DTORS_HPP
#include <vector>
#include <limits>
#include <algorithm>
#include <numeric>
#include "../common.hpp"
// TEST 1
// Verify that destructor is executed.
// How: destructor of struct dtor_test_class has a side effect: zeroing buffer. If values
// in buffer are not zeros after releasing program, destructor was not executed.
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * program_test_dtor_is_executed =
"__kernel void test_dtor_is_executed(global uint *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * program_test_dtor_is_executed =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"using namespace cl;\n"
// struct
"struct dtor_test_class {\n"
// non-trivial dtor
// set all values in buffer to 0
" ~dtor_test_class() {\n"
" for(ulong i = 0; i < size; i++)\n"
" buffer[i] = 0;\n"
" };\n"
" global_ptr<uint[]> buffer;\n"
" ulong size;\n"
"};\n"
// global scope program variable
"dtor_test_class global_var;\n"
// values in output __MUST BE__ greater than 0 for the test to work
// correctly
"__kernel void test_dtor_is_executed(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
// set buffer and size in global var
" if(gid == 0){\n"
" global_var.buffer = output;\n"
" global_var.size = get_global_size(0);\n"
" }\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_global_scope_dtor_is_executed)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_is_executed, "test_dtor_is_executed"
);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_is_executed, "test_dtor_is_executed", "", false
);
RETURN_ON_ERROR(error)
// Normal run
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_is_executed, "test_dtor_is_executed"
);
RETURN_ON_ERROR(error)
#endif
// host vector, size == count, output[0...count-1] == 0xbeefbeef (3203383023)
// values in output __MUST BE__ greater than 0 for the test to work correctly
std::vector<cl_uint> output(count, cl_uint(0xbeefbeef));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(
queue, kernel,
dim, NULL, work_size, NULL,
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
// Release kernel and program
// Dtor should be called now
error = clReleaseKernel(kernel);
RETURN_ON_CL_ERROR(error, "clReleaseKernel")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
// Finish
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
// Read output buffer
error = clEnqueueReadBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
size_t sum = std::accumulate(output.begin(), output.end(), size_t(0));
if(sum != 0)
{
error = -1;
CHECK_ERROR_MSG(error, "Test test_dtor_is_executed failed.");
}
clReleaseMemObject(output_buffer);
return error;
}
// TEST 2
// Verify that multiple destructors, if present, are executed. Order between multiple
// destructors is undefined.
// Verify that each destructor is executed only once.
// How:
// 0) dtor_test_class struct has a global pointer to a buffer, it's set by
// test_dtors_executed_once kernel.
// 1) Destructors have a side effect: each dtor writes to its part of the buffer. If all
// dtors are executed, all values in that buffer should be changed.
// 2) The first time destructors are executed, they set their parts of the buffer to zero.
// Next time to 1, next time to 2 etc. Since dtors should be executed only once, all
// values in that buffer should be equal to zero.
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * program_test_dtors_executed_once =
"__kernel void test_dtors_executed_once(global uint *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * program_test_dtors_executed_once =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"using namespace cl;\n"
// struct
"struct dtor_test_class {\n"
// non-trivial dtor
// Set all values in range [start; end - 1] in buffer to counter.
// If dtor is executed only once (correct), all values in range
// [start; end - 1] in buffer should be equal to zero after releasing
// the program
" ~dtor_test_class() {\n"
" for(ulong i = start; i < end; i++){\n"
" buffer[i] = counter;\n"
" };\n"
" counter++;\n"
" };\n"
" global_ptr<uint[]> buffer;\n"
" ulong start;\n"
" ulong end;\n"
" ulong counter;\n"
"};\n"
// global scope program variables
"dtor_test_class global_var0;\n"
"dtor_test_class global_var1;\n"
"dtor_test_class global_var2;\n"
"dtor_test_class global_var3;\n"
// values in output __MUST BE__ greater than 0 for the test to work correctly
"__kernel void test_dtors_executed_once(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
// set buffer and size in global var
" if(gid == 0){\n"
" ulong end = get_global_size(0) / 4;"
// global_var0
" global_var0.buffer = output;\n"
" global_var0.start = 0;\n"
" global_var0.end = end;\n"
" global_var0.counter = 0;\n"
// global_var1
" global_var1.buffer = output;\n"
" global_var1.start = end;\n"
" end += get_global_size(0) / 4;\n"
" global_var1.end = end;\n"
" global_var1.counter = 0;\n"
// global_var2
" global_var2.buffer = output;\n"
" global_var2.start = end;\n"
" end += get_global_size(0) / 4;\n"
" global_var2.end = end;\n"
" global_var2.counter = 0;\n"
// global_var3
" global_var3.buffer = output;\n"
" global_var3.start = end;\n"
" global_var3.end = get_global_size(0);\n"
" global_var3.counter = 0;\n"
" }\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_global_scope_dtors_executed_once)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtors_executed_once, "test_dtors_executed_once"
);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtors_executed_once, "test_dtors_executed_once", "", false
);
RETURN_ON_ERROR(error)
// Normal run
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtors_executed_once, "test_dtors_executed_once"
);
RETURN_ON_ERROR(error)
#endif
// host vector, size == count, output[0...count-1] == 0xbeefbeef (3203383023)
// values in output __MUST BE__ greater than 0 for the test to work correctly
cl_uint init_value = cl_uint(0xbeefbeef);
std::vector<cl_uint> output(count, init_value);
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(
queue, kernel,
dim, NULL, work_size, NULL,
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
// Increments the program reference count. Twice
error = clRetainProgram(program);
RETURN_ON_CL_ERROR(error, "clRetainProgram")
error = clRetainProgram(program);
RETURN_ON_CL_ERROR(error, "clRetainProgram")
// Should just decrement the program reference count.
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
// Should just decrement the program reference count.
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
#ifndef USE_OPENCLC_KERNELS
// At this point global scope variables should not be destroyed,
// values in output buffer should not be modified.
// Read output buffer
error = clEnqueueReadBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
for(auto& i : output)
{
if(i != init_value)
{
log_error("ERROR: Test test_global_scope_dtors_executed_once failed.");
log_error("\tDestructors were executed prematurely.\n");
RETURN_ON_ERROR(-1)
}
}
#endif
// Release kernel and program, destructors should be called now
error = clReleaseKernel(kernel);
RETURN_ON_CL_ERROR(error, "clReleaseKernel")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
// Finish
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
// Read output buffer
error = clEnqueueReadBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
size_t sum = std::accumulate(output.begin(), output.end(), size_t(0));
if(sum != 0)
{
log_error("ERROR: Test test_global_scope_dtors_executed_once failed.");
// Maybe some dtors were not run?
for(auto& i : output)
{
if(i == init_value)
{
log_error("\tSome dtors were not executed.");
break;
}
}
log_error("\n");
RETURN_ON_ERROR(-1)
}
// Clean
clReleaseMemObject(output_buffer);
return error;
}
// TEST3
// Verify that ND-range during destructor execution is set to (1,1,1)
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * program_test_dtor_ndrange =
"__kernel void test_dtor_ndrange(global uint *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * program_test_dtor_ndrange =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"using namespace cl;\n"
// struct
"struct dtor_test_class {\n"
// non-trivial dtor
// set all values in buffer to 0 only if ND-range is (1, 1, 1)
" ~dtor_test_class() {\n"
" if(check()){\n"
" for(ulong i = 0; i < size; i++)\n"
" buffer[i] = 0;\n"
" }\n"
" };\n"
// return true if the ND-range is (1, 1, 1); otherwise - false
" bool check() {\n"
" return (get_global_size(0) == 1)"
" && (get_global_size(1) == 1)"
" && (get_global_size(2) == 1);\n"
" }"
" ulong size;\n"
" global_ptr<uint[]> buffer;\n"
"};\n"
// global scope program variable
"dtor_test_class global_var;\n"
// values in output __MUST BE__ greater than 0 for the test to work correctly
"__kernel void test_dtor_ndrange(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
// set buffer and size in global var
" if(gid == 0){\n"
" global_var.buffer = output;\n"
" global_var.size = get_global_size(0);\n"
" }\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_global_scope_dtor_ndrange)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_ndrange, "test_dtor_ndrange"
);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_ndrange, "test_dtor_ndrange", "", false
);
RETURN_ON_ERROR(error)
// Normal run
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_ndrange, "test_dtor_ndrange"
);
RETURN_ON_ERROR(error)
#endif
// host vector, size == count, output[0...count-1] == 0xbeefbeef (3203383023)
// values in output __MUST BE__ greater than 0 for the test to work correctly
std::vector<cl_uint> output(count, cl_uint(0xbeefbeef));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_uint) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(
queue, kernel,
dim, NULL, work_size, NULL,
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
// Release kernel and program
// Dtor should be called now
error = clReleaseKernel(kernel);
RETURN_ON_CL_ERROR(error, "clReleaseKernel")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
// Finish
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
// Read output buffer
error = clEnqueueReadBuffer(
queue, output_buffer, CL_TRUE,
0, sizeof(cl_uint) * output.size(),
static_cast<void *>(output.data()),
0, NULL, NULL
);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
size_t sum = std::accumulate(output.begin(), output.end(), size_t(0));
if(sum != 0)
{
error = -1;
CHECK_ERROR_MSG(error, "Test test_dtor_ndrange failed.");
}
clReleaseMemObject(output_buffer);
return error;
}
#endif // TEST_CONFORMANCE_CLCPP_API_TEST_DTORS_HPP

View File

@@ -0,0 +1,474 @@
//
// 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 TEST_CONFORMANCE_CLCPP_API_TEST_SPEC_CONSTS_HPP
#define TEST_CONFORMANCE_CLCPP_API_TEST_SPEC_CONSTS_HPP
#include <vector>
#include <limits>
#include <algorithm>
#include "../common.hpp"
// TEST 1
// Verify that if left unset the specialization constant defaults to the default value set in SPIR-V (zero).
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * kernel_test_spec_consts_defaults =
"__kernel void test_spec_consts_defaults(global int *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * kernel_test_spec_consts_defaults =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"#include <opencl_spec_constant>\n"
"using namespace cl;\n"
"spec_constant<char, 1> spec1(0);\n"
"spec_constant<uchar, 2> spec2(0);\n"
"spec_constant<short, 3> spec3(0);\n"
"spec_constant<ushort,4> spec4(0);\n"
"spec_constant<int, 5> spec5(0);\n"
"spec_constant<uint, 6> spec6(0);\n"
"spec_constant<long, 7> spec7(0);\n"
"spec_constant<ulong, 8> spec8(0);\n"
"spec_constant<float, 9> spec9(0.0f);\n"
"#ifdef cl_khr_fp64\n"
"spec_constant<double, 10> spec10(0.0);\n"
"#endif\n"
"#ifdef cl_khr_fp16\n"
"spec_constant<half, 11> spec11(0.0h);\n"
"#endif\n"
"__kernel void test_spec_consts_defaults(global_ptr<int[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(get(spec1) != char(0)) result = 1;\n"
" if(get(spec2) != uchar(0)) result = 1;\n"
" if(get(spec3) != short(0)) result = 1;\n"
" if(get(spec4) != ushort(0)) result = 1;\n"
" if(get(spec5) != int(0)) result = 1;\n"
" if(get(spec6) != uint(0)) result = 1;\n"
" if(get(spec7) != long(0)) result = 1;\n"
" if(get(spec8) != ulong(0)) result = 1;\n"
" if(get(spec9) != float(0)) result = 1;\n"
"#ifdef cl_khr_fp64\n"
" if(get(spec10) != double(0)) result = 1;\n"
"#endif\n"
"#ifdef cl_khr_fp16\n"
" if(get(spec11) != half(0)) result = 1;\n"
"#endif\n"
" output[gid] = result;\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_spec_consts_defaults)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
std::string options = "";
if(is_extension_available(device, "cl_khr_fp16"))
{
options += " -cl-fp16-enable";
}
if(is_extension_available(device, "cl_khr_fp64"))
{
options += " -cl-fp64-enable";
}
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_defaults, "test_spec_consts_defaults", options);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_defaults, "test_spec_consts_defaults", "", false);
RETURN_ON_ERROR(error)
// Normal run
#else
// Spec constants are NOT set before clBuildProgram (called in create_opencl_kernel), so
// they all should default to the default value set in SPIR-V (zero).
error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_defaults, "test_spec_consts_defaults", options);
RETURN_ON_ERROR(error)
#endif
// host vector, size == 1, output[0] == 1
std::vector<cl_int> output(1, cl_int(1));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKerne")
error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
// if output[0] != 0, then some spec constant(s) did not default to zero.
if(output[0] != 0)
{
RETURN_ON_ERROR_MSG(-1, "Test test_spec_consts_defaults failed, output[0]: %d.", output[0])
}
clReleaseMemObject(output_buffer);
clReleaseKernel(kernel);
clReleaseProgram(program);
return error;
}
// TEST 2
// Verify that setting an existing specialization constant affects only
// the value of that constant and not of other specialization constants.
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * kernel_test_spec_consts_many_constants =
"__kernel void test_spec_consts_many_constants(global int *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * kernel_test_spec_consts_many_constants =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"#include <opencl_spec_constant>\n"
"using namespace cl;\n"
"spec_constant<int, 1> spec1(0);\n"
"spec_constant<int, 2> spec2(0);\n"
"spec_constant<int, 3> spec3(0);\n"
"__kernel void test_spec_consts_defaults(global_ptr<int[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(get(spec1) != int(-1024)) result += 1;\n"
" if(get(spec2) != int(0)) result += 2;\n"
" if(get(spec3) != int(1024)) result += 4;\n"
" output[gid] = result;\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_spec_consts_many_constants)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(
context, &program, &kernel,
kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants"
);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(
context, &program, &kernel,
kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants", "", false
);
RETURN_ON_ERROR(error)
// Normal run
#else
// Create program
error = create_openclcpp_program(context, &program, 1, &kernel_test_spec_consts_many_constants);
RETURN_ON_ERROR(error)
// Set specialization constants
// clSetProgramSpecializationConstant(
// cl_program /* program */, cl_uint /* spec_id */, size_t /* spec_size */,const void* /* spec_value */
// )
cl_int spec1 = -1024;
cl_int spec3 = 1024;
// Set spec1
error = clSetProgramSpecializationConstant(program, cl_uint(1), sizeof(cl_int), static_cast<void*>(&spec1));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Specialization constant spec2 should default to zero
// Set spec3
error = clSetProgramSpecializationConstant(program, cl_uint(3), sizeof(cl_int), static_cast<void*>(&spec3));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Build program and create kernel
error = build_program_create_kernel_helper(
context, &program, &kernel, 1, &kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants"
);
RETURN_ON_ERROR(error)
#endif
// host vector, size == 1, output[0] == 1
std::vector<cl_int> output(1, cl_int(1));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
// if output[0] != 0, then values of spec constants were incorrect
if(output[0] != 0)
{
RETURN_ON_ERROR_MSG(-1, "Test test_spec_consts_many_constants failed, output[0]: %d.", output[0]);
}
clReleaseMemObject(output_buffer);
clReleaseKernel(kernel);
clReleaseProgram(program);
return error;
}
// TEST 3
// Verify that the API correctly handles the size of a specialization constant by exercising
// the API for specialization constants of different types (int, bool, float, etc.)
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
const char * kernel_test_spec_consts_different_types =
"__kernel void test_spec_consts_different_types(global int *output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" output[gid] = 0;\n"
"}\n"
;
#else
const char * kernel_test_spec_consts_different_types =
"#include <opencl_memory>\n"
"#include <opencl_work_item>\n"
"#include <opencl_spec_constant>\n"
"#include <opencl_limits>\n"
"using namespace cl;\n"
"spec_constant<char, 1> spec1(0);\n"
"spec_constant<uchar, 2> spec2(0);\n"
"spec_constant<short, 3> spec3(0);\n"
"spec_constant<ushort,4> spec4(0);\n"
"spec_constant<int, 5> spec5(0);\n"
"spec_constant<uint, 6> spec6(0);\n"
"spec_constant<long, 7> spec7(0);\n"
"spec_constant<ulong, 8> spec8(0);\n"
"spec_constant<float, 9> spec9(0.0f);\n"
"#ifdef cl_khr_fp64\n"
"spec_constant<double, 10> spec10(0.0);\n"
"#endif\n"
"#ifdef cl_khr_fp16\n"
"spec_constant<half, 11> spec11(0.0h);\n"
"#endif\n"
"__kernel void test_spec_consts_different_types(global_ptr<int[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" int result = 0;\n"
" if(get(spec1) != char(CHAR_MAX)) result += 1;\n"
" if(get(spec2) != uchar(UCHAR_MAX)) result += 2;\n"
" if(get(spec3) != short(SHRT_MAX)) result += 4;\n"
" if(get(spec4) != ushort(USHRT_MAX)) result += 8;\n"
" if(get(spec5) != int(INT_MAX)) result += 16;\n"
" if(get(spec6) != uint(UINT_MAX)) result += 32;\n"
" if(get(spec7) != long(LONG_MAX)) result += 64;\n"
" if(get(spec8) != ulong(ULONG_MAX)) result += 128;\n"
" if(get(spec9) != float(FLT_MAX)) result += 256;\n"
"#ifdef cl_khr_fp64\n"
" if(get(spec10) != double(DBL_MAX)) result += 512;\n"
"#endif\n"
"#ifdef cl_khr_fp16\n"
" if(get(spec11) != half(HALF_MAX)) result += 1024;\n"
"#endif\n"
" output[gid] = result;\n"
"}\n"
;
#endif
AUTO_TEST_CASE(test_spec_consts_different_types)
(cl_device_id device, cl_context context, cl_command_queue queue, int count)
{
int error = CL_SUCCESS;
cl_mem output_buffer;
cl_program program;
cl_kernel kernel;
size_t dim = 1;
size_t work_size[1];
std::string options = "";
if(is_extension_available(device, "cl_khr_fp16"))
{
options += " -cl-fp16-enable";
}
if(is_extension_available(device, "cl_khr_fp64"))
{
options += " -cl-fp64-enable";
}
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
// Only OpenCL C++ to SPIR-V compilation
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_different_types, "test_spec_consts_different_types", options);
RETURN_ON_ERROR(error)
return error;
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
error = create_opencl_kernel(context, &program, &kernel, kernel_test_spec_consts_different_types, "test_spec_consts_different_types", "", false);
RETURN_ON_ERROR(error)
// Normal run
#else
// Create program
error = create_openclcpp_program(context, &program, 1, &kernel_test_spec_consts_different_types, options.c_str());
RETURN_ON_ERROR(error)
// Set specialization constants
cl_uint spec_id = 1;
cl_char spec1 = CL_CHAR_MAX;
cl_uchar spec2 = CL_UCHAR_MAX;
cl_short spec3 = CL_SHRT_MAX;
cl_ushort spec4 = CL_USHRT_MAX;
cl_int spec5 = CL_INT_MAX;
cl_uint spec6 = CL_UINT_MAX;
cl_long spec7 = CL_LONG_MAX;
cl_ulong spec8 = CL_ULONG_MAX;
cl_float spec9 = CL_FLT_MAX;
cl_double spec10 = CL_DBL_MAX;
cl_half spec11 = CL_HALF_MAX;
// Set spec1
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_char), static_cast<void*>(&spec1));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec2
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_uchar), static_cast<void*>(&spec2));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec3
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_short), static_cast<void*>(&spec3));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec4
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_ushort), static_cast<void*>(&spec4));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec5
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_int), static_cast<void*>(&spec5));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec6
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_uint), static_cast<void*>(&spec6));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec7
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_long), static_cast<void*>(&spec7));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec8
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_ulong), static_cast<void*>(&spec8));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec9
error = clSetProgramSpecializationConstant(program, spec_id++, sizeof(cl_float), static_cast<void*>(&spec9));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
// Set spec10
if(is_extension_available(device, "cl_khr_fp64"))
{
error = clSetProgramSpecializationConstant(program, cl_uint(10), sizeof(cl_double), static_cast<void*>(&spec10));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
}
// Set spec11
if(is_extension_available(device, "cl_khr_fp16"))
{
error = clSetProgramSpecializationConstant(program, cl_uint(11), sizeof(cl_half), static_cast<void*>(&spec11));
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
}
// Build program and create kernel
error = build_program_create_kernel_helper(
context, &program, &kernel, 1, &kernel_test_spec_consts_many_constants, "test_spec_consts_many_constants"
);
RETURN_ON_ERROR(error)
#endif
// Copy output to output_buffer, run kernel, copy output_buffer back to output, check result
// host vector, size == 1, output[0] == 1
std::vector<cl_int> output(1, cl_int(1));
output_buffer = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &error);
RETURN_ON_CL_ERROR(error, "clCreateBuffer")
error = clEnqueueWriteBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueWriteBuffer")
error = clSetKernelArg(kernel, 0, sizeof(output_buffer), &output_buffer);
RETURN_ON_CL_ERROR(error, "clSetKernelArg")
work_size[0] = output.size();
error = clEnqueueNDRangeKernel(queue, kernel, dim, NULL, work_size, NULL, 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueNDRangeKernel")
error = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(cl_int) * output.size(), static_cast<void *>(output.data()), 0, NULL, NULL);
RETURN_ON_CL_ERROR(error, "clEnqueueReadBuffer")
// if output[0] != 0, then some spec constants had incorrect values
if(output[0] != 0)
{
RETURN_ON_ERROR_MSG(-1, "Test test_spec_consts_different_types failed, output[0]: %d.", output[0])
}
clReleaseMemObject(output_buffer);
clReleaseKernel(kernel);
clReleaseProgram(program);
return error;
}
#endif // TEST_CONFORMANCE_CLCPP_API_TEST_SPEC_CONSTS_HPP