diff options
Diffstat (limited to 'tests/test_builtins.cpp')
-rw-r--r-- | tests/test_builtins.cpp | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/tests/test_builtins.cpp b/tests/test_builtins.cpp new file mode 100644 index 0000000..9a6d651 --- /dev/null +++ b/tests/test_builtins.cpp @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <iostream> +#include <cstdlib> + +#include "test_builtins.h" +#include "CL/cl.h" + +#include <stdint.h> + +const char sampler_source[] = + "__kernel void test_case(__global uint *rs, sampler_t sampler) {\n" + " sampler_t good_sampler = CLK_NORMALIZED_COORDS_TRUE |\n" + " CLK_ADDRESS_MIRRORED_REPEAT |\n" + " CLK_FILTER_NEAREST;\n" + "\n" + " if (sampler != good_sampler) *rs = 1;\n" + "}\n"; + +const char barrier_source[] = + "__kernel void test_case(__global uint *rs) {\n" + " *rs = 0;\n" + " int i; for (i=0; i<3; i++) barrier(0);\n" + " *rs += 1;\n" + "}\n"; + +const char image_source[] = + "__kernel void test_case(__global uint *rs, __write_only image2d_t image1,\n" + " __write_only image2d_t image2,\n" + " __read_only image2d_t image3) {\n" + " float4 fcolor;\n" + " int4 scolor;\n" + " int2 coord;\n" + " sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE |\n" + " CLK_ADDRESS_MIRRORED_REPEAT |\n" + " CLK_FILTER_NEAREST;\n" + "\n" + " if (get_image_width(image1) != 4) *rs = 1;\n" + " if (get_image_height(image1) != 4) *rs = 2;\n" + " if (get_image_channel_data_type(image2) != CLK_SIGNED_INT16) *rs = 3;\n" + " if (get_image_channel_order(image2) != CLK_RGBA) *rs = 4;\n" + "\n" + " if (*rs != 0) return;\n" + "\n" + " fcolor.x = 1.0f;\n" + " fcolor.y = 0.5f;\n" + " fcolor.z = 0.0f;\n" + " fcolor.w = 1.0f;\n" + "\n" + " scolor.x = -3057;\n" + " scolor.y = 65;\n" + " scolor.z = 0;\n" + " scolor.w = 32767;\n" + "\n" + " coord.x = 3;\n" + " coord.y = 1;\n" + "\n" + " write_imagef(image1, coord, fcolor);\n" + " write_imagei(image2, coord, scolor);\n" + "\n" + " coord.x = 1;\n" + " coord.y = 1;\n" + " fcolor = read_imagef(image3, 0, coord);\n" + " if (fcolor.x < 0.99f || fcolor.y < 0.99f || fcolor.z > 0.01f ||\n" + " fcolor.w > 0.01f) { *rs = 5; return; }\n" + "\n" + " float2 fcoords;\n" + " fcoords.x = 0.31f;\n" + " fcoords.y = 0.1415f;\n" + " fcolor = read_imagef(image3, sampler, fcoords);\n" + "}\n"; + +const char builtins_source[] = + "__kernel void test_case(__global uint *rs) {\n" + " float2 f2;\n" + " float2 f2b;\n" + "\n" + " f2.x = 1.0f;\n" + " f2.y = 0.0f;\n" + " f2b.x = -0.5f;\n" + " f2b.y = (float)M_PI;\n" + "\n" + " if (cos(f2).y != 1.0f) { *rs = 1; return; }\n" + " if (cos(0.0f) != 1.0f) { *rs = 2; return; }\n" + " if (copysign(1.0f, -0.5f) != -1.0f) { *rs = 3; return; }\n" + " if (copysign(f2, f2b).x != -1.0f) { *rs = 4; return; }\n" + " if (exp2(3.0f) != 8.0f) { *rs = 5; return; }\n" + "}\n"; + +enum TestCaseKind +{ + NormalKind, + SamplerKind, + BarrierKind, + ImageKind +}; + +/* + * To ease testing, each kernel will be a Task kernel taking a pointer to an + * integer and running built-in functions. If an error is encountered, the + * integer pointed to by the arg will be set accordingly. If the kernel succeeds, + * this integer is set to 0. + */ +static uint32_t run_kernel(const char *source, TestCaseKind kind) +{ + cl_platform_id platform = 0; + cl_device_id device; + cl_context ctx; + cl_command_queue queue; + cl_program program; + cl_int result; + cl_kernel kernel; + cl_event event; + cl_mem rs_buf; + + cl_sampler sampler; + cl_mem mem1, mem2, mem3; + cl_image_format fmt; + + unsigned char image2d_data[3*3*4] = { + 255, 0, 0, 0, 0, 255, 0, 0, 128, 128, 128, 0, + 0, 0, 255, 0, 255, 255, 0, 0, 0, 128, 0, 0, + 255, 128, 0, 0, 128, 0, 255, 0, 0, 0, 0, 0 + }; + + uint32_t rs = 0; + + result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, 0); + if (result != CL_SUCCESS) return 65536; + + ctx = clCreateContext(0, 1, &device, 0, 0, &result); + if (result != CL_SUCCESS) return 65537; + + queue = clCreateCommandQueue(ctx, device, 0, &result); + if (result != CL_SUCCESS) return 65538; + + program = clCreateProgramWithSource(ctx, 1, &source, 0, &result); + if (result != CL_SUCCESS) return 65539; + + result = clBuildProgram(program, 1, &device, "", 0, 0); + if (result != CL_SUCCESS) + { + // Print log + char *log = 0; + size_t len = 0; + + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, 0, &len); + log = (char *)std::malloc(len); + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, len, log, 0); + + std::cout << log << std::endl; + std::free(log); + + return 65540; + } + + kernel = clCreateKernel(program, "test_case", &result); + if (result != CL_SUCCESS) return 65541; + + // Create the result buffer + rs_buf = clCreateBuffer(ctx, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + sizeof(rs), &rs, &result); + if (result != CL_SUCCESS) return 65542; + + result = clSetKernelArg(kernel, 0, sizeof(cl_mem), &rs_buf); + if (result != CL_SUCCESS) return 65543; + + // Kind + switch (kind) + { + case NormalKind: + break; + + case SamplerKind: + sampler = clCreateSampler(ctx, 1, CL_ADDRESS_MIRRORED_REPEAT, CL_FILTER_NEAREST, &result); + if (result != CL_SUCCESS) return 65546; + + result = clSetKernelArg(kernel, 1, sizeof(cl_sampler), &sampler); + if (result != CL_SUCCESS) return 65547; + break; + + case ImageKind: + fmt.image_channel_data_type = CL_UNORM_INT8; + fmt.image_channel_order = CL_RGBA; + + mem1 = clCreateImage2D(ctx, CL_MEM_WRITE_ONLY, &fmt, 4, 4, 0, 0, &result); + if (result != CL_SUCCESS) return 65548; + + mem3 = clCreateImage2D(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + &fmt, 3, 3, 0, image2d_data, &result); + if (result != CL_SUCCESS) return 65548; + + fmt.image_channel_data_type = CL_SIGNED_INT16; + + mem2 = clCreateImage2D(ctx, CL_MEM_WRITE_ONLY, &fmt, 4, 4, 0, 0, &result); + if (result != CL_SUCCESS) return 65548; + + result = clSetKernelArg(kernel, 1, sizeof(cl_mem), &mem1); + if (result != CL_SUCCESS) return 65549; + + result = clSetKernelArg(kernel, 2, sizeof(cl_mem), &mem2); + if (result != CL_SUCCESS) return 65549; + + result = clSetKernelArg(kernel, 3, sizeof(cl_mem), &mem3); + if (result != CL_SUCCESS) return 65549; + break; + + default: + break; + } + + if (kind == BarrierKind) + { + size_t local_size = 64; + size_t global_size = 64; + + result = clEnqueueNDRangeKernel(queue, kernel, 1, 0, &global_size, + &local_size, 0, 0, &event); + if (result != CL_SUCCESS) return 65544; + } + else + { + result = clEnqueueTask(queue, kernel, 0, 0, &event); + if (result != CL_SUCCESS) return 65544; + } + + result = clWaitForEvents(1, &event); + if (result != CL_SUCCESS) return 65545; + + if (kind == SamplerKind) clReleaseSampler(sampler); + if (kind == ImageKind) + { + clReleaseMemObject(mem1); + clReleaseMemObject(mem2); + clReleaseMemObject(mem3); + } + clReleaseEvent(event); + clReleaseMemObject(rs_buf); + clReleaseKernel(kernel); + clReleaseProgram(program); + clReleaseCommandQueue(queue); + clReleaseContext(ctx); + + return rs; +} + +static const char *default_error(uint32_t errcode) +{ + switch (errcode) + { + case 0: + return 0; + case 65536: + return "Cannot get a device ID"; + case 65537: + return "Cannot create a context"; + case 65538: + return "Cannot create a command queue"; + case 65539: + return "Cannot create a program with given source"; + case 65540: + return "Cannot build the program"; + case 65541: + return "Cannot create the test_case kernel"; + case 65542: + return "Cannot create a buffer holding a uint32_t"; + case 65543: + return "Cannot set kernel argument"; + case 65544: + return "Cannot enqueue the kernel"; + case 65545: + return "Cannot wait for the event"; + case 65546: + return "Cannot create a sampler"; + case 65547: + return "Cannot set a sampler kernel argument"; + case 65548: + return "Cannot create an Image2D object"; + case 65549: + return "Cannot set image kernel argument"; + + default: + return "Unknown error code"; + } +} + +START_TEST (test_sampler) +{ + uint32_t rs = run_kernel(sampler_source, SamplerKind); + const char *errstr = 0; + + switch (rs) + { + case 1: + errstr = "Sampler bitfield invalid"; + break; + default: + errstr = default_error(rs); + } + + fail_if( + errstr != 0, + errstr + ); +} +END_TEST + +START_TEST (test_barrier) +{ + uint32_t rs = run_kernel(barrier_source, BarrierKind); + + fail_if( + rs != 0x40, + default_error(rs) + ); +} +END_TEST + +START_TEST (test_image) +{ + uint32_t rs = run_kernel(image_source, ImageKind); + const char *errstr = 0; + + switch (rs) + { + case 1: + errstr = "Image1 must have width of 4"; + break; + case 2: + errstr = "Image1 must have width of 4"; + break; + case 3: + errstr = "Image2 must have type SIGNED_FLOAT16"; + break; + case 4: + errstr = "Image2 must have channel order RGBA"; + break; + case 5: + errstr = "The value read from the image is not good"; + break; + default: + errstr = default_error(rs); + } + + fail_if( + errstr != 0, + errstr + ); +} +END_TEST + +START_TEST (test_builtins) +{ + uint32_t rs = run_kernel(builtins_source, NormalKind); + const char *errstr = 0; + + switch (rs) + { + case 1: + errstr = "float2 cos(float2) doesn't behave correctly"; + break; + case 2: + errstr = "float cos(float) doesn't behave correctly"; + break; + case 3: + errstr = "float copysign(float) doesn't behave correctly"; + break; + case 4: + errstr = "float2 copysign(float2) doesn't behave correctly"; + break; + case 5: + errstr = "exp2() doesn't behave correctly"; + break; + default: + errstr = default_error(rs); + } + + fail_if( + errstr != 0, + errstr + ); +} +END_TEST + +TCase *cl_builtins_tcase_create(void) +{ + TCase *tc = NULL; + tc = tcase_create("builtins"); + //tcase_add_test(tc, test_sampler); + tcase_add_test(tc, test_barrier); + //tcase_add_test(tc, test_image); + tcase_add_test(tc, test_builtins); + return tc; +} |