android: Update app-specific/MIME type icons
[LibreOffice.git] / opencl / opencltest / main.cxx
blob0db18b0042d15887c9e2f4e244667c486bded796
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <clew/clew.h>
12 #include <vector>
13 #include <cassert>
14 #include <cstring>
15 #include <iostream>
17 #include <sal/log.hxx>
19 #include <clew_setup.hxx>
21 // The purpose of this separate executable is to check whether OpenCL works
22 // without crashing (asserting, etc.). Other checks can be done by LO core itself.
24 #define check(value, expected) \
25 do \
26 { \
27 auto val = (value); \
28 if (val != (expected)) \
29 { \
30 SAL_WARN("opencl", \
31 "OpenCL driver check failed: " << val << "(line " << __LINE__ << ")"); \
32 return; \
33 } \
34 } while (false);
35 #define openclcheck(value) check(value, CL_SUCCESS)
37 static void runTest(const char* deviceName, const char* devicePlatform)
39 int status = clewInit(OPENCL_DLL_NAME);
40 check(status, CLEW_SUCCESS);
42 // Find the given OpenCL device (in order to use the same one as LO core).
43 cl_uint numPlatforms;
44 openclcheck(clGetPlatformIDs(0, nullptr, &numPlatforms));
45 std::vector<cl_platform_id> platforms(numPlatforms);
46 openclcheck(clGetPlatformIDs(numPlatforms, platforms.data(), nullptr));
47 cl_platform_id platformId = nullptr;
48 for (cl_uint i = 0; i < numPlatforms; ++i)
50 char platformName[64];
51 if (clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 64, platformName, nullptr)
52 == CL_SUCCESS
53 && strcmp(devicePlatform, platformName) == 0)
55 platformId = platforms[i];
56 break;
59 if (platformId == nullptr)
61 SAL_WARN("opencl", "Device platform not found: " << devicePlatform);
62 assert(false);
63 return;
66 cl_uint numDevices;
67 openclcheck(clGetDeviceIDs(platformId, CL_DEVICE_TYPE_ALL, 0, nullptr, &numDevices));
68 std::vector<cl_device_id> devices(numDevices);
69 openclcheck(
70 clGetDeviceIDs(platformId, CL_DEVICE_TYPE_ALL, numDevices, devices.data(), nullptr));
71 cl_device_id deviceId = nullptr;
72 for (cl_uint i = 0; i < numDevices; ++i)
74 char name[1024];
75 if (clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 64, name, nullptr) == CL_SUCCESS
76 && strcmp(deviceName, name) == 0)
78 deviceId = devices[i];
79 break;
82 if (deviceId == nullptr)
84 SAL_WARN("opencl", "Device not found: " << deviceName);
85 assert(false);
86 return;
89 cl_context context;
90 cl_int state;
91 cl_context_properties cps[3];
92 cps[0] = CL_CONTEXT_PLATFORM;
93 cps[1] = reinterpret_cast<cl_context_properties>(platformId);
94 cps[2] = 0;
95 context = clCreateContext(cps, 1, &deviceId, nullptr, nullptr, &state);
96 openclcheck(state);
97 cl_command_queue queue = clCreateCommandQueue(context, deviceId, 0, &state);
98 openclcheck(state);
100 // Just a simple OpenCL program, the functionality or results do not really matter.
101 const char* source[] = { "__kernel void testFunction( __global float* input1, __global float* "
102 "input2, __global float* output )"
104 " int gid0 = get_global_id( 0 );"
105 " output[ gid0 ] = input1[ gid0 ] * input2[ gid0 ];"
106 "}" };
107 size_t sourceSize[] = { strlen(source[0]) };
108 cl_program program = clCreateProgramWithSource(context, 1, source, sourceSize, &state);
109 openclcheck(state);
110 state = clBuildProgram(program, 1, &deviceId, nullptr, nullptr, nullptr);
111 #ifdef DBG_UTIL
112 if (state != CL_SUCCESS)
114 size_t length;
115 status
116 = clGetProgramBuildInfo(program, deviceId, CL_PROGRAM_BUILD_LOG, 0, nullptr, &length);
117 std::vector<char> error(length + 1);
118 status = clGetProgramBuildInfo(program, deviceId, CL_PROGRAM_BUILD_LOG, length,
119 error.data(), nullptr);
120 error[length] = '\0';
121 std::cerr << "OpenCL driver check build error:" << error.data() << std::endl;
122 abort();
124 #endif
125 openclcheck(state);
126 cl_kernel kernel = clCreateKernel(program, "testFunction", &state);
127 openclcheck(state);
129 // Some random data for the program.
130 constexpr int dataSize = 1000;
131 cl_float inputData1[dataSize];
132 cl_float inputData2[dataSize];
133 cl_float outputData[dataSize];
134 for (int i = 0; i < dataSize; ++i)
136 inputData1[i] = i * 2;
137 inputData2[i] = i % 100;
139 cl_mem input1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
140 sizeof(cl_float) * dataSize, inputData1, &state);
141 openclcheck(state);
142 cl_mem input2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
143 sizeof(cl_float) * dataSize, inputData2, &state);
144 openclcheck(state);
145 cl_mem output = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
146 sizeof(cl_float) * dataSize, outputData, &state);
147 openclcheck(state);
148 state = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input1);
149 openclcheck(state);
150 state = clSetKernelArg(kernel, 1, sizeof(cl_mem), &input2);
151 openclcheck(state);
152 state = clSetKernelArg(kernel, 2, sizeof(cl_mem), &output);
153 openclcheck(state);
155 const size_t globalWorkSize[] = { dataSize };
156 const size_t localSize[1] = { 64 };
157 state = clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, globalWorkSize, localSize, 0, nullptr,
158 nullptr);
159 openclcheck(state);
160 openclcheck(clFinish(queue));
161 openclcheck(clEnqueueReadBuffer(queue, output, CL_TRUE, 0, sizeof(cl_float) * dataSize,
162 outputData, 0, nullptr, nullptr));
163 clReleaseMemObject(input1);
164 clReleaseMemObject(input2);
165 clReleaseMemObject(output);
166 clReleaseKernel(kernel);
167 clReleaseProgram(program);
168 clReleaseCommandQueue(queue);
169 clReleaseContext(context);
172 int main(int argc, char* argv[])
174 if (argc != 3)
175 return 1;
176 runTest(argv[1], argv[2]);
177 // Always return exit code 0, LO itself can do error checking better, we just care
178 // if this helper crashes or not.
179 return 0;
182 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */