1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CLProgram.cpp: Implements the cl::Program class.
7
8 #include "libANGLE/CLProgram.h"
9
10 #include "libANGLE/CLContext.h"
11 #include "libANGLE/CLPlatform.h"
12
13 #include <cstring>
14
15 namespace cl
16 {
17
build(cl_uint numDevices,const cl_device_id * deviceList,const char * options,ProgramCB pfnNotify,void * userData)18 cl_int Program::build(cl_uint numDevices,
19 const cl_device_id *deviceList,
20 const char *options,
21 ProgramCB pfnNotify,
22 void *userData)
23 {
24 DevicePtrs devices;
25 devices.reserve(numDevices);
26 while (numDevices-- != 0u)
27 {
28 devices.emplace_back(&(*deviceList++)->cast<Device>());
29 }
30 Program *notify = nullptr;
31 if (pfnNotify != nullptr)
32 {
33 // This program has to be retained until the notify callback is called.
34 retain();
35 *mCallback = CallbackData(pfnNotify, userData);
36 notify = this;
37 }
38 return mImpl->build(devices, options, notify);
39 }
40
compile(cl_uint numDevices,const cl_device_id * deviceList,const char * options,cl_uint numInputHeaders,const cl_program * inputHeaders,const char ** headerIncludeNames,ProgramCB pfnNotify,void * userData)41 cl_int Program::compile(cl_uint numDevices,
42 const cl_device_id *deviceList,
43 const char *options,
44 cl_uint numInputHeaders,
45 const cl_program *inputHeaders,
46 const char **headerIncludeNames,
47 ProgramCB pfnNotify,
48 void *userData)
49 {
50 DevicePtrs devices;
51 devices.reserve(numDevices);
52 while (numDevices-- != 0u)
53 {
54 devices.emplace_back(&(*deviceList++)->cast<Device>());
55 }
56 ProgramPtrs programs;
57 programs.reserve(numInputHeaders);
58 while (numInputHeaders-- != 0u)
59 {
60 programs.emplace_back(&(*inputHeaders++)->cast<Program>());
61 }
62 Program *notify = nullptr;
63 if (pfnNotify != nullptr)
64 {
65 // This program has to be retained until the notify callback is called.
66 retain();
67 *mCallback = CallbackData(pfnNotify, userData);
68 notify = this;
69 }
70 return mImpl->compile(devices, options, programs, headerIncludeNames, notify);
71 }
72
getInfo(ProgramInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const73 cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
74 {
75 std::vector<cl_device_id> devices;
76 cl_uint valUInt = 0u;
77 void *valPointer = nullptr;
78 const void *copyValue = nullptr;
79 size_t copySize = 0u;
80
81 switch (name)
82 {
83 case ProgramInfo::ReferenceCount:
84 valUInt = getRefCount();
85 copyValue = &valUInt;
86 copySize = sizeof(valUInt);
87 break;
88 case ProgramInfo::Context:
89 valPointer = mContext->getNative();
90 copyValue = &valPointer;
91 copySize = sizeof(valPointer);
92 break;
93 case ProgramInfo::NumDevices:
94 valUInt = static_cast<decltype(valUInt)>(mDevices.size());
95 copyValue = &valUInt;
96 copySize = sizeof(valUInt);
97 break;
98 case ProgramInfo::Devices:
99 devices.reserve(mDevices.size());
100 for (const DevicePtr &device : mDevices)
101 {
102 devices.emplace_back(device->getNative());
103 }
104 copyValue = devices.data();
105 copySize = devices.size() * sizeof(decltype(devices)::value_type);
106 break;
107 case ProgramInfo::Source:
108 copyValue = mSource.c_str();
109 copySize = mSource.length() + 1u;
110 break;
111 case ProgramInfo::IL:
112 copyValue = mIL.c_str();
113 copySize = mIL.length() + 1u;
114 break;
115 case ProgramInfo::BinarySizes:
116 case ProgramInfo::Binaries:
117 case ProgramInfo::NumKernels:
118 case ProgramInfo::KernelNames:
119 case ProgramInfo::ScopeGlobalCtorsPresent:
120 case ProgramInfo::ScopeGlobalDtorsPresent:
121 return mImpl->getInfo(name, valueSize, value, valueSizeRet);
122 default:
123 return CL_INVALID_VALUE;
124 }
125
126 if (value != nullptr)
127 {
128 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
129 // as described in the Program Object Queries table and param_value is not NULL.
130 if (valueSize < copySize)
131 {
132 return CL_INVALID_VALUE;
133 }
134 if (copyValue != nullptr)
135 {
136 std::memcpy(value, copyValue, copySize);
137 }
138 }
139 if (valueSizeRet != nullptr)
140 {
141 *valueSizeRet = copySize;
142 }
143 return CL_SUCCESS;
144 }
145
getBuildInfo(cl_device_id device,ProgramBuildInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const146 cl_int Program::getBuildInfo(cl_device_id device,
147 ProgramBuildInfo name,
148 size_t valueSize,
149 void *value,
150 size_t *valueSizeRet) const
151 {
152 return mImpl->getBuildInfo(device->cast<Device>(), name, valueSize, value, valueSizeRet);
153 }
154
createKernel(const char * kernel_name,cl_int & errorCode)155 cl_kernel Program::createKernel(const char *kernel_name, cl_int &errorCode)
156 {
157 return Object::Create<Kernel>(errorCode, *this, kernel_name);
158 }
159
createKernels(cl_uint numKernels,cl_kernel * kernels,cl_uint * numKernelsRet)160 cl_int Program::createKernels(cl_uint numKernels, cl_kernel *kernels, cl_uint *numKernelsRet)
161 {
162 if (kernels == nullptr)
163 {
164 numKernels = 0u;
165 }
166 rx::CLKernelImpl::CreateFuncs createFuncs;
167 cl_int errorCode = mImpl->createKernels(numKernels, createFuncs, numKernelsRet);
168 if (errorCode == CL_SUCCESS)
169 {
170 KernelPtrs krnls;
171 krnls.reserve(createFuncs.size());
172 while (!createFuncs.empty())
173 {
174 krnls.emplace_back(new Kernel(*this, createFuncs.front(), errorCode));
175 if (errorCode != CL_SUCCESS)
176 {
177 return CL_INVALID_VALUE;
178 }
179 createFuncs.pop_front();
180 }
181 for (KernelPtr &kernel : krnls)
182 {
183 *kernels++ = kernel.release();
184 }
185 }
186 return errorCode;
187 }
188
189 Program::~Program() = default;
190
callback()191 void Program::callback()
192 {
193 CallbackData callbackData;
194 mCallback->swap(callbackData);
195 const ProgramCB callback = callbackData.first;
196 void *const userData = callbackData.second;
197 ASSERT(callback != nullptr);
198 callback(this, userData);
199 // This program can be released after the callback was called.
200 if (release())
201 {
202 delete this;
203 }
204 }
205
Program(Context & context,std::string && source,cl_int & errorCode)206 Program::Program(Context &context, std::string &&source, cl_int &errorCode)
207 : mContext(&context),
208 mDevices(context.getDevices()),
209 mNumAttachedKernels(0u),
210 mImpl(context.getImpl().createProgramWithSource(*this, source, errorCode)),
211 mSource(std::move(source))
212 {}
213
Program(Context & context,const void * il,size_t length,cl_int & errorCode)214 Program::Program(Context &context, const void *il, size_t length, cl_int &errorCode)
215 : mContext(&context),
216 mDevices(context.getDevices()),
217 mIL(static_cast<const char *>(il), length),
218 mNumAttachedKernels(0u),
219 mImpl(context.getImpl().createProgramWithIL(*this, il, length, errorCode)),
220 mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
221 {}
222
Program(Context & context,DevicePtrs && devices,const size_t * lengths,const unsigned char ** binaries,cl_int * binaryStatus,cl_int & errorCode)223 Program::Program(Context &context,
224 DevicePtrs &&devices,
225 const size_t *lengths,
226 const unsigned char **binaries,
227 cl_int *binaryStatus,
228 cl_int &errorCode)
229 : mContext(&context),
230 mDevices(std::move(devices)),
231 mNumAttachedKernels(0u),
232 mImpl(context.getImpl()
233 .createProgramWithBinary(*this, lengths, binaries, binaryStatus, errorCode)),
234 mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
235 {}
236
Program(Context & context,DevicePtrs && devices,const char * kernelNames,cl_int & errorCode)237 Program::Program(Context &context, DevicePtrs &&devices, const char *kernelNames, cl_int &errorCode)
238 : mContext(&context),
239 mDevices(std::move(devices)),
240 mNumAttachedKernels(0u),
241 mImpl(context.getImpl().createProgramWithBuiltInKernels(*this, kernelNames, errorCode)),
242 mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
243 {}
244
Program(Context & context,const DevicePtrs & devices,const char * options,const cl::ProgramPtrs & inputPrograms,ProgramCB pfnNotify,void * userData,cl_int & errorCode)245 Program::Program(Context &context,
246 const DevicePtrs &devices,
247 const char *options,
248 const cl::ProgramPtrs &inputPrograms,
249 ProgramCB pfnNotify,
250 void *userData,
251 cl_int &errorCode)
252 : mContext(&context),
253 mDevices(!devices.empty() ? devices : context.getDevices()),
254 // This program has to be retained until the notify callback is called.
255 mCallback(pfnNotify != nullptr ? (retain(), CallbackData(pfnNotify, userData))
256 : CallbackData()),
257 mNumAttachedKernels(0u),
258 mImpl(context.getImpl().linkProgram(*this,
259 devices,
260 options,
261 inputPrograms,
262 pfnNotify != nullptr ? this : nullptr,
263 errorCode)),
264 mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
265 {}
266
267 } // namespace cl
268