nss: upgrade to release 3.73
[LibreOffice.git] / opencl / opencltest / main.cxx
bloba499032f8c05de621f581e36cb13c15afe9592df
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 using namespace std;
23 // The purpose of this separate executable is to check whether OpenCL works
24 // without crashing (asserting, etc.). Other checks can be done by LO core itself.
26 #define check(value, expected) \
27 do \
28 { \
29 auto val = (value); \
30 if (val != (expected)) \
31 { \
32 SAL_WARN("opencl", \
33 "OpenCL driver check failed: " << val << "(line " << __LINE__ << ")"); \
34 return; \
35 } \
36 } while (false);
37 #define openclcheck(value) check(value, CL_SUCCESS)
39 static void runTest(const char* deviceName, const char* devicePlatform)
41 int status = clewInit(OPENCL_DLL_NAME);
42 check(status, CLEW_SUCCESS);
44 // Find the given OpenCL device (in order to use the same one as LO core).
45 cl_uint numPlatforms;
46 openclcheck(clGetPlatformIDs(0, nullptr, &numPlatforms));
47 vector<cl_platform_id> platforms(numPlatforms);
48 openclcheck(clGetPlatformIDs(numPlatforms, platforms.data(), nullptr));
49 cl_platform_id platformId = nullptr;
50 for (cl_uint i = 0; i < numPlatforms; ++i)
52 char platformName[64];
53 if (clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 64, platformName, nullptr)
54 == CL_SUCCESS
55 && strcmp(devicePlatform, platformName) == 0)
57 platformId = platforms[i];
58 break;
61 if (platformId == nullptr)
63 SAL_WARN("opencl", "Device platform not found: " << devicePlatform);
64 assert(false);
65 return;
68 cl_uint numDevices;
69 openclcheck(clGetDeviceIDs(platformId, CL_DEVICE_TYPE_ALL, 0, nullptr, &numDevices));
70 vector<cl_device_id> devices(numDevices);
71 openclcheck(
72 clGetDeviceIDs(platformId, CL_DEVICE_TYPE_ALL, numDevices, devices.data(), nullptr));
73 cl_device_id deviceId = nullptr;
74 for (cl_uint i = 0; i < numDevices; ++i)
76 char name[1024];
77 if (clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 64, name, nullptr) == CL_SUCCESS
78 && strcmp(deviceName, name) == 0)
80 deviceId = devices[i];
81 break;
84 if (deviceId == nullptr)
86 SAL_WARN("opencl", "Device not found: " << deviceName);
87 assert(false);
88 return;
91 cl_context context;
92 cl_int state;
93 cl_context_properties cps[3];
94 cps[0] = CL_CONTEXT_PLATFORM;
95 cps[1] = reinterpret_cast<cl_context_properties>(platformId);
96 cps[2] = 0;
97 context = clCreateContext(cps, 1, &deviceId, nullptr, nullptr, &state);
98 openclcheck(state);
99 cl_command_queue queue = clCreateCommandQueue(context, deviceId, 0, &state);
100 openclcheck(state);
102 // Just a simple OpenCL program, the functionality or results do not really matter.
103 const char* source[] = { "__kernel void testFunction( __global float* input1, __global float* "
104 "input2, __global float* output )"
106 " int gid0 = get_global_id( 0 );"
107 " output[ gid0 ] = input1[ gid0 ] * input2[ gid0 ];"
108 "}" };
109 size_t sourceSize[] = { strlen(source[0]) };
110 cl_program program = clCreateProgramWithSource(context, 1, source, sourceSize, &state);
111 openclcheck(state);
112 state = clBuildProgram(program, 1, &deviceId, nullptr, nullptr, nullptr);
113 #ifdef DBG_UTIL
114 if (state != CL_SUCCESS)
116 size_t length;
117 status
118 = clGetProgramBuildInfo(program, deviceId, CL_PROGRAM_BUILD_LOG, 0, nullptr, &length);
119 vector<char> error(length + 1);
120 status = clGetProgramBuildInfo(program, deviceId, CL_PROGRAM_BUILD_LOG, length,
121 error.data(), nullptr);
122 error[length] = '\0';
123 cerr << "OpenCL driver check build error:" << error.data() << endl;
124 abort();
126 #endif
127 openclcheck(state);
128 cl_kernel kernel = clCreateKernel(program, "testFunction", &state);
129 openclcheck(state);
131 // Some random data for the program.
132 constexpr int dataSize = 1000;
133 cl_float inputData1[dataSize];
134 cl_float inputData2[dataSize];
135 cl_float outputData[dataSize];
136 for (int i = 0; i < dataSize; ++i)
138 inputData1[i] = i * 2;
139 inputData2[i] = i % 100;
141 cl_mem input1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
142 sizeof(cl_float) * dataSize, inputData1, &state);
143 openclcheck(state);
144 cl_mem input2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
145 sizeof(cl_float) * dataSize, inputData2, &state);
146 openclcheck(state);
147 cl_mem output = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
148 sizeof(cl_float) * dataSize, outputData, &state);
149 openclcheck(state);
150 state = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input1);
151 openclcheck(state);
152 state = clSetKernelArg(kernel, 1, sizeof(cl_mem), &input2);
153 openclcheck(state);
154 state = clSetKernelArg(kernel, 2, sizeof(cl_mem), &output);
155 openclcheck(state);
157 const size_t globalWorkSize[] = { dataSize };
158 const size_t localSize[1] = { 64 };
159 state = clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, globalWorkSize, localSize, 0, nullptr,
160 nullptr);
161 openclcheck(state);
162 openclcheck(clFinish(queue));
163 openclcheck(clEnqueueReadBuffer(queue, output, CL_TRUE, 0, sizeof(cl_float) * dataSize,
164 outputData, 0, nullptr, nullptr));
165 clReleaseMemObject(input1);
166 clReleaseMemObject(input2);
167 clReleaseMemObject(output);
168 clReleaseKernel(kernel);
169 clReleaseProgram(program);
170 clReleaseCommandQueue(queue);
171 clReleaseContext(context);
174 int main(int argc, char* argv[])
176 if (argc != 3)
177 return 1;
178 runTest(argv[1], argv[2]);
179 // Always return exit code 0, LO itself can do error checking better, we just care
180 // if this helper crashes or not.
181 return 0;
184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */