/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include "OCLKernelBinary.h" #include #include #include #include "CL/cl.h" const static char* strKernel12 = "typedef struct ST { \n" " int i0; \n" " int i1; \n" "} ST_t; \n" " \n" "__constant ST_t STCArray[2] = { \n" " { 1, 0 }, \n" " { 2, 1 } \n" "}; \n" " \n" "__kernel void foo (__global int *p, int n) \n" "{ \n" " int s = 0; \n" " int i; \n" " for (i=0; i < n; ++i) { \n" " s += STCArray[i].i0 + STCArray[i].i1; \n" " } \n" " *p = s; \n" "} \n"; const static char* strKernel20 = "typedef struct ST { \n" " int i0; \n" " int i1; \n" "} ST_t; \n" " \n" "__constant ST_t STCArray[2] = { \n" " { -1, 0 }, \n" " { 3, -1 } \n" "}; \n" " \n" "__global int var = 1; \n" " \n" "__kernel void foo (__global int *p, int n) \n" "{ \n" " int s = 0; \n" " int i; \n" " for (i=0; i < n; ++i) { \n" " s += STCArray[i].i0 + STCArray[i].i1 + var++; \n" " } \n" " p[get_global_id(0)] = s; \n" "} \n"; OCLKernelBinary::OCLKernelBinary() { _numSubTests = 2; } OCLKernelBinary::~OCLKernelBinary() {} void OCLKernelBinary::open(unsigned int test, char* units, double& conversion, unsigned int deviceId) { OCLTestImp::open(test, units, conversion, deviceId); char strVersion[128]; error_ = _wrapper->clGetDeviceInfo(devices_[deviceId], CL_DEVICE_VERSION, sizeof(strVersion), strVersion, 0); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); if (test == 1 && strVersion[7] < '2') { program_ = NULL; return; } const char *options, *options0; const char* strKernel; switch (test) { case 0: options = ""; options0 = "-O0"; strKernel = strKernel12; break; case 1: options = "-cl-std=CL2.0"; options0 = "-cl-std=CL2.0 -O0"; strKernel = strKernel20; break; default: assert(false); return; } CHECK_RESULT((error_ != CL_SUCCESS), "Error opening test"); program_ = _wrapper->clCreateProgramWithSource(context_, 1, &strKernel, NULL, &error_); CHECK_RESULT((error_ != CL_SUCCESS), "clCreateProgramWithSource() failed"); error_ = _wrapper->clBuildProgram(program_, 1, &devices_[deviceId], options, NULL, NULL); if (error_ != CL_SUCCESS) { char programLog[1024]; _wrapper->clGetProgramBuildInfo(program_, devices_[_deviceId], CL_PROGRAM_BUILD_LOG, 1024, programLog, 0); printf("\n%s\n", programLog); fflush(stdout); } CHECK_RESULT((error_ != CL_SUCCESS), "clBuildProgram() failed"); size_t* sizes = new size_t[deviceCount_]; CHECK_RESULT(((sizes != NULL) ? false : true), "malloc()"); size_t* sizes1 = new size_t[deviceCount_]; CHECK_RESULT(((sizes1 != NULL) ? false : true), "malloc()"); size_t* sizes2 = new size_t[deviceCount_]; CHECK_RESULT(((sizes2 != NULL) ? false : true), "malloc()"); unsigned int programInfoDeviceIdIndex = 0; cl_device_id* programInfoDevices = new cl_device_id[deviceCount_]; CHECK_RESULT(((programInfoDevices != NULL) ? false : true), "malloc()"); // get an array of device Id's that relate to values order returned by // 'clGetProgramInfo' error_ = _wrapper->clGetProgramInfo( program_, CL_PROGRAM_DEVICES, sizeof(cl_device_id) * deviceCount_, programInfoDevices, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clGetProgramInfo()"); // map between the class devices_ array and the programInfoDeviceId array for (unsigned int i = 0; i < deviceCount_; i++) { if (devices_[deviceId] == programInfoDevices[i]) { programInfoDeviceIdIndex = i; } } delete[] programInfoDevices; error_ = _wrapper->clGetProgramInfo(program_, CL_PROGRAM_BINARY_SIZES, sizeof(size_t) * deviceCount_, sizes, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clGetProgramInfo()"); unsigned char** binaries = new unsigned char*[deviceCount_]; CHECK_RESULT(((binaries != NULL) ? false : true), "malloc()"); for (unsigned int i = 0; i < deviceCount_; i++) { if (sizes[i] > 0) { binaries[i] = new unsigned char[sizes[i]]; CHECK_RESULT(((binaries[i] != NULL) ? false : true), "malloc()"); } else { binaries[i] = NULL; } } error_ = _wrapper->clGetProgramInfo(program_, CL_PROGRAM_BINARIES, sizeof(unsigned char*) * deviceCount_, binaries, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clGetProgramInfo()"); error_ = _wrapper->clReleaseProgram(program_); CHECK_RESULT((error_ != CL_SUCCESS), "clReleaseProgram()"); const unsigned char* cBinary = binaries[programInfoDeviceIdIndex]; cl_int status; program_ = _wrapper->clCreateProgramWithBinary(context_, 1, &devices_[deviceId], &(sizes[programInfoDeviceIdIndex]), &cBinary, &status, &error_); CHECK_RESULT((error_ != CL_SUCCESS), "clCreateProgramWithBinary()"); for (unsigned int i = 0; i < deviceCount_; i++) { if (binaries[i] != NULL) delete[] binaries[i]; } delete[] binaries; error_ = _wrapper->clBuildProgram(program_, 1, &devices_[_deviceId], options0, NULL, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clGetProgramInfo()"); error_ = _wrapper->clGetProgramInfo(program_, CL_PROGRAM_BINARY_SIZES, sizeof(size_t) * deviceCount_, sizes1, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "1st clGetProgramInfo()"); kernel_ = _wrapper->clCreateKernel(program_, "foo", &error_); CHECK_RESULT((error_ != CL_SUCCESS), "1st clCreateKernel() failed"); _wrapper->clReleaseKernel(kernel_); CHECK_RESULT((error_ != CL_SUCCESS), "1st clReleaseKernel() failed"); error_ = _wrapper->clBuildProgram(program_, 1, &devices_[_deviceId], options0, NULL, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clGetProgramInfo()"); error_ = _wrapper->clGetProgramInfo(program_, CL_PROGRAM_BINARY_SIZES, sizeof(size_t) * deviceCount_, sizes2, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "2nd clGetProgramInfo()"); kernel_ = _wrapper->clCreateKernel(program_, "foo", &error_); CHECK_RESULT((error_ != CL_SUCCESS), "2nd clCreateKernel() failed"); cl_mem buffer; buffer = _wrapper->clCreateBuffer(context_, CL_MEM_READ_WRITE, 2 * sizeof(cl_uint), NULL, &error_); CHECK_RESULT((error_ != CL_SUCCESS), "clCreateBuffer() failed"); buffers_.push_back(buffer); delete[] sizes; delete[] sizes1; delete[] sizes2; } void OCLKernelBinary::run(void) { if (program_ == NULL) { return; } cl_mem buffer = buffers()[0]; error_ = _wrapper->clSetKernelArg(kernel_, 0, sizeof(cl_mem), &buffer); CHECK_RESULT((error_ != CL_SUCCESS), "clSetKernelArg() failed"); cl_int num = 2; error_ = _wrapper->clSetKernelArg(kernel_, 1, sizeof(cl_int), &num); CHECK_RESULT((error_ != CL_SUCCESS), "clSetKernelArg() failed"); size_t gws[1] = {2}; error_ = _wrapper->clEnqueueNDRangeKernel(cmdQueues_[_deviceId], kernel_, 1, NULL, gws, NULL, 0, NULL, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clEnqueueNDRangeKernel() failed"); cl_uint outputV[2] = {0}; error_ = _wrapper->clEnqueueReadBuffer(cmdQueues_[_deviceId], buffer, true, 0, 2 * sizeof(cl_uint), outputV, 0, NULL, NULL); CHECK_RESULT((error_ != CL_SUCCESS), "clEnqueueReadBuffer() failed"); if (outputV[0] != 4) { CHECK_RESULT(true, "Incorrect result of kernel execution!"); } } unsigned int OCLKernelBinary::close(void) { return OCLTestImp::close(); }