1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/helpers/get_info.h"
9 
10 #include "shared/source/device/device.h"
11 #include "shared/source/program/kernel_info.h"
12 
13 #include "opencl/source/cl_device/cl_device.h"
14 #include "opencl/source/context/context.h"
15 #include "opencl/source/helpers/base_object.h"
16 #include "opencl/source/helpers/cl_validators.h"
17 #include "opencl/source/helpers/get_info_status_mapper.h"
18 
19 #include "program.h"
20 
21 namespace NEO {
22 
getInfo(cl_program_info paramName,size_t paramValueSize,void * paramValue,size_t * paramValueSizeRet)23 cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
24                         void *paramValue, size_t *paramValueSizeRet) {
25     cl_int retVal = CL_SUCCESS;
26     const void *pSrc = nullptr;
27     size_t srcSize = GetInfo::invalidSourceSize;
28     size_t retSize = 0;
29     std::string kernelNamesString;
30     cl_uint refCount = 0;
31     size_t numKernels;
32     cl_context clContext = context;
33     cl_uint clFalse = CL_FALSE;
34     std::vector<cl_device_id> devicesToExpose;
35     StackVec<size_t, 1> binarySizes;
36     uint32_t numDevices = static_cast<uint32_t>(clDevices.size());
37 
38     switch (paramName) {
39     case CL_PROGRAM_CONTEXT:
40         pSrc = &clContext;
41         retSize = srcSize = sizeof(clContext);
42         break;
43 
44     case CL_PROGRAM_BINARIES: {
45         auto requiredSize = clDevices.size() * sizeof(const unsigned char **);
46         if (!paramValue) {
47             retSize = requiredSize;
48             srcSize = 0u;
49             break;
50         }
51         if (paramValueSize < requiredSize) {
52             retVal = CL_INVALID_VALUE;
53             break;
54         }
55         auto outputBinaries = reinterpret_cast<unsigned char **>(paramValue);
56         for (auto i = 0u; i < clDevices.size(); i++) {
57             if (outputBinaries[i] == nullptr) {
58                 continue;
59             }
60             auto rootDeviceIndex = clDevices[i]->getRootDeviceIndex();
61             auto binarySize = buildInfos[rootDeviceIndex].packedDeviceBinarySize;
62             memcpy_s(outputBinaries[i], binarySize, buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize);
63         }
64         GetInfo::setParamValueReturnSize(paramValueSizeRet, requiredSize, GetInfoStatus::SUCCESS);
65         return CL_SUCCESS;
66     } break;
67 
68     case CL_PROGRAM_BINARY_SIZES:
69         for (auto i = 0u; i < clDevices.size(); i++) {
70             auto rootDeviceIndex = clDevices[i]->getRootDeviceIndex();
71             packDeviceBinary(*clDevices[i]);
72             binarySizes.push_back(buildInfos[rootDeviceIndex].packedDeviceBinarySize);
73         }
74 
75         pSrc = binarySizes.data();
76         retSize = srcSize = binarySizes.size() * sizeof(cl_device_id);
77         break;
78 
79     case CL_PROGRAM_KERNEL_NAMES:
80         kernelNamesString = concatenateKernelNames(buildInfos[clDevices[0]->getRootDeviceIndex()].kernelInfoArray);
81         pSrc = kernelNamesString.c_str();
82         retSize = srcSize = kernelNamesString.length() + 1;
83 
84         if (!isBuilt()) {
85             retVal = CL_INVALID_PROGRAM_EXECUTABLE;
86         }
87         break;
88 
89     case CL_PROGRAM_NUM_KERNELS:
90         numKernels = getNumKernels();
91         pSrc = &numKernels;
92         retSize = srcSize = sizeof(numKernels);
93 
94         if (!isBuilt()) {
95             retVal = CL_INVALID_PROGRAM_EXECUTABLE;
96         }
97         break;
98 
99     case CL_PROGRAM_NUM_DEVICES:
100         pSrc = &numDevices;
101         retSize = srcSize = sizeof(cl_uint);
102         break;
103 
104     case CL_PROGRAM_DEVICES:
105         clDevices.toDeviceIDs(devicesToExpose);
106         pSrc = devicesToExpose.data();
107         retSize = srcSize = devicesToExpose.size() * sizeof(cl_device_id);
108         break;
109 
110     case CL_PROGRAM_REFERENCE_COUNT:
111         refCount = static_cast<cl_uint>(this->getReference());
112         retSize = srcSize = sizeof(refCount);
113         pSrc = &refCount;
114         break;
115 
116     case CL_PROGRAM_SOURCE:
117         if (createdFrom == CreatedFrom::SOURCE) {
118             pSrc = sourceCode.c_str();
119             retSize = srcSize = strlen(sourceCode.c_str()) + 1;
120         } else {
121             if (paramValueSizeRet) {
122                 *paramValueSizeRet = 0;
123             }
124             return CL_SUCCESS;
125         }
126         break;
127 
128     case CL_PROGRAM_IL:
129         if (createdFrom != CreatedFrom::IL) {
130             if (paramValueSizeRet) {
131                 *paramValueSizeRet = 0;
132             }
133             return CL_SUCCESS;
134         }
135         pSrc = irBinary.get();
136         retSize = srcSize = irBinarySize;
137         break;
138 
139     case CL_PROGRAM_DEBUG_INFO_SIZES_INTEL:
140         retSize = srcSize = sizeof(debugDataSize);
141         pSrc = &debugDataSize;
142         break;
143 
144     case CL_PROGRAM_DEBUG_INFO_INTEL:
145         pSrc = debugData.get();
146         retSize = numDevices * sizeof(void **);
147         srcSize = debugDataSize;
148         if (paramValue != nullptr) {
149             if (paramValueSize < retSize) {
150                 retVal = CL_INVALID_VALUE;
151                 break;
152             }
153             paramValueSize = srcSize;
154             paramValue = *(void **)paramValue;
155         }
156         break;
157 
158     case CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT:
159     case CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT:
160         retSize = srcSize = sizeof(clFalse);
161         pSrc = &clFalse;
162         break;
163 
164     default:
165         retVal = CL_INVALID_VALUE;
166         break;
167     }
168 
169     auto getInfoStatus = GetInfoStatus::INVALID_VALUE;
170     if (retVal == CL_SUCCESS) {
171         getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, pSrc, srcSize);
172         retVal = changeGetInfoStatusToCLResultType(getInfoStatus);
173     }
174     GetInfo::setParamValueReturnSize(paramValueSizeRet, retSize, getInfoStatus);
175     return retVal;
176 }
177 
getBuildInfo(cl_device_id device,cl_program_build_info paramName,size_t paramValueSize,void * paramValue,size_t * paramValueSizeRet) const178 cl_int Program::getBuildInfo(cl_device_id device, cl_program_build_info paramName,
179                              size_t paramValueSize, void *paramValue, size_t *paramValueSizeRet) const {
180     cl_int retVal = CL_SUCCESS;
181     const void *pSrc = nullptr;
182     size_t srcSize = GetInfo::invalidSourceSize;
183     size_t retSize = 0;
184 
185     auto pClDev = castToObject<ClDevice>(device);
186     auto rootDeviceIndex = pClDev->getRootDeviceIndex();
187 
188     switch (paramName) {
189     case CL_PROGRAM_BUILD_STATUS:
190         srcSize = retSize = sizeof(cl_build_status);
191         pSrc = &deviceBuildInfos.at(pClDev).buildStatus;
192         break;
193 
194     case CL_PROGRAM_BUILD_OPTIONS:
195         srcSize = retSize = strlen(options.c_str()) + 1;
196         pSrc = options.c_str();
197         break;
198 
199     case CL_PROGRAM_BUILD_LOG: {
200         const char *pBuildLog = getBuildLog(pClDev->getRootDeviceIndex());
201 
202         pSrc = pBuildLog;
203         srcSize = retSize = strlen(pBuildLog) + 1;
204     } break;
205 
206     case CL_PROGRAM_BINARY_TYPE:
207         srcSize = retSize = sizeof(cl_program_binary_type);
208         pSrc = &deviceBuildInfos.at(pClDev).programBinaryType;
209         break;
210 
211     case CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE:
212         pSrc = &buildInfos[rootDeviceIndex].globalVarTotalSize;
213         retSize = srcSize = sizeof(size_t);
214         break;
215 
216     default:
217         retVal = CL_INVALID_VALUE;
218         break;
219     }
220 
221     auto getInfoStatus = GetInfoStatus::INVALID_VALUE;
222     if (retVal == CL_SUCCESS) {
223         getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, pSrc, srcSize);
224         retVal = changeGetInfoStatusToCLResultType(getInfoStatus);
225     }
226     GetInfo::setParamValueReturnSize(paramValueSizeRet, retSize, getInfoStatus);
227 
228     return retVal;
229 }
230 } // namespace NEO
231