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