#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"
#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 dtor_test_class {\n"
" ~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"
"dtor_test_class global_var;\n"
"__kernel void test_dtor_is_executed(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" 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];
#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;
#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)
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_is_executed, "test_dtor_is_executed"
);
RETURN_ON_ERROR(error)
#endif
std::vector<cl_uint> output(count, cl_uint(0xbeefbeef));
output_buffer =
clCreateBuffer(context, 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 = clReleaseKernel(kernel);
RETURN_ON_CL_ERROR(error, "clReleaseKernel")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
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;
}
#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 dtor_test_class {\n"
" ~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"
"dtor_test_class global_var0;\n"
"dtor_test_class global_var1;\n"
"dtor_test_class global_var2;\n"
"dtor_test_class global_var3;\n"
"__kernel void test_dtors_executed_once(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" if(gid == 0){\n"
" ulong end = get_global_size(0) / 4;"
" global_var0.buffer = output;\n"
" global_var0.start = 0;\n"
" global_var0.end = end;\n"
" global_var0.counter = 0;\n"
" 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.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.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];
#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;
#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)
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtors_executed_once, "test_dtors_executed_once"
);
RETURN_ON_ERROR(error)
#endif
cl_uint init_value = cl_uint(0xbeefbeef);
std::vector<cl_uint> output(count, init_value);
output_buffer =
clCreateBuffer(context, 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 = clRetainProgram(program);
RETURN_ON_CL_ERROR(error, "clRetainProgram")
error = clRetainProgram(program);
RETURN_ON_CL_ERROR(error, "clRetainProgram")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
#ifndef USE_OPENCLC_KERNELS
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
error = clReleaseKernel(kernel);
RETURN_ON_CL_ERROR(error, "clReleaseKernel")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
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.");
for(auto& i : output)
{
if(i == init_value)
{
log_error("\tSome dtors were not executed.");
break;
}
}
log_error("\n");
RETURN_ON_ERROR(-1)
}
clReleaseMemObject(output_buffer);
return error;
}
#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 dtor_test_class {\n"
" ~dtor_test_class() {\n"
" if(check()){\n"
" for(ulong i = 0; i < size; i++)\n"
" buffer[i] = 0;\n"
" }\n"
" };\n"
" 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"
"dtor_test_class global_var;\n"
"__kernel void test_dtor_ndrange(global_ptr<uint[]> output)\n"
"{\n"
" ulong gid = get_global_id(0);\n"
" 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];
#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;
#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)
#else
error = create_opencl_kernel(
context, &program, &kernel,
program_test_dtor_ndrange, "test_dtor_ndrange"
);
RETURN_ON_ERROR(error)
#endif
std::vector<cl_uint> output(count, cl_uint(0xbeefbeef));
output_buffer =
clCreateBuffer(context, 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 = clReleaseKernel(kernel);
RETURN_ON_CL_ERROR(error, "clReleaseKernel")
error = clReleaseProgram(program);
RETURN_ON_CL_ERROR(error, "clReleaseProgram")
error = clFinish(queue);
RETURN_ON_CL_ERROR(error, "clFinish")
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