xref: /aosp_15_r20/external/angle/src/libANGLE/CLProgram.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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             if (!mSource.empty())
113             {
114                 copyValue = mSource.c_str();
115                 copySize  = mSource.length() + 1u;
116             }
117             break;
118         case ProgramInfo::IL:
119             if (!mIL.empty())
120             {
121                 copyValue = mIL.c_str();
122                 copySize  = mIL.length() + 1u;
123             }
124             break;
125         case ProgramInfo::BinarySizes:
126         case ProgramInfo::Binaries:
127         case ProgramInfo::NumKernels:
128         case ProgramInfo::KernelNames:
129         case ProgramInfo::ScopeGlobalCtorsPresent:
130         case ProgramInfo::ScopeGlobalDtorsPresent:
131             return mImpl->getInfo(name, valueSize, value, valueSizeRet);
132         default:
133             ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
134     }
135 
136     if (value != nullptr)
137     {
138         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
139         // as described in the Program Object Queries table and param_value is not NULL.
140         if (valueSize < copySize)
141         {
142             ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
143         }
144         if (copyValue != nullptr)
145         {
146             std::memcpy(value, copyValue, copySize);
147         }
148     }
149     if (valueSizeRet != nullptr)
150     {
151         *valueSizeRet = copySize;
152     }
153     return angle::Result::Continue;
154 }
155 
getBuildInfo(cl_device_id device,ProgramBuildInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const156 angle::Result Program::getBuildInfo(cl_device_id device,
157                                     ProgramBuildInfo name,
158                                     size_t valueSize,
159                                     void *value,
160                                     size_t *valueSizeRet) const
161 {
162     return mImpl->getBuildInfo(device->cast<Device>(), name, valueSize, value, valueSizeRet);
163 }
164 
createKernel(const char * kernel_name)165 cl_kernel Program::createKernel(const char *kernel_name)
166 {
167     return Object::Create<Kernel>(*this, kernel_name);
168 }
169 
createKernels(cl_uint numKernels,cl_kernel * kernels,cl_uint * numKernelsRet)170 angle::Result Program::createKernels(cl_uint numKernels, cl_kernel *kernels, cl_uint *numKernelsRet)
171 {
172     if (kernels == nullptr)
173     {
174         numKernels = 0u;
175     }
176     rx::CLKernelImpl::CreateFuncs createFuncs;
177     ANGLE_TRY(mImpl->createKernels(numKernels, createFuncs, numKernelsRet));
178     KernelPtrs krnls;
179     krnls.reserve(createFuncs.size());
180     while (!createFuncs.empty())
181     {
182         krnls.emplace_back(new Kernel(*this, createFuncs.front()));
183         if (krnls.back()->mImpl == nullptr)
184         {
185             return angle::Result::Stop;
186         }
187         createFuncs.pop_front();
188     }
189     for (KernelPtr &kernel : krnls)
190     {
191         *kernels++ = kernel.release();
192     }
193     return angle::Result::Continue;
194 }
195 
196 Program::~Program() = default;
197 
callback()198 void Program::callback()
199 {
200     CallbackData callbackData;
201     mCallback->swap(callbackData);
202     const ProgramCB callback = callbackData.first;
203     void *const userData     = callbackData.second;
204     ASSERT(callback != nullptr);
205     callback(this, userData);
206     // This program can be released after the callback was called.
207     if (release())
208     {
209         delete this;
210     }
211 }
212 
Program(Context & context,std::string && source)213 Program::Program(Context &context, std::string &&source)
214     : mContext(&context),
215       mDevices(context.getDevices()),
216       mNumAttachedKernels(0u),
217       mImpl(nullptr),
218       mSource(std::move(source))
219 {
220     ANGLE_CL_IMPL_TRY(context.getImpl().createProgramWithSource(*this, mSource, &mImpl));
221 }
222 
Program(Context & context,const void * il,size_t length)223 Program::Program(Context &context, const void *il, size_t length)
224     : mContext(&context),
225       mDevices(context.getDevices()),
226       mIL(static_cast<const char *>(il), length),
227       mNumAttachedKernels(0u),
228       mImpl(nullptr)
229 {
230     ANGLE_CL_IMPL_TRY(context.getImpl().createProgramWithIL(*this, il, length, &mImpl));
231 }
232 
Program(Context & context,DevicePtrs && devices,const size_t * lengths,const unsigned char ** binaries,cl_int * binaryStatus)233 Program::Program(Context &context,
234                  DevicePtrs &&devices,
235                  const size_t *lengths,
236                  const unsigned char **binaries,
237                  cl_int *binaryStatus)
238     : mContext(&context), mDevices(std::move(devices)), mNumAttachedKernels(0u), mImpl(nullptr)
239 {
240     ANGLE_CL_IMPL_TRY(
241         context.getImpl().createProgramWithBinary(*this, lengths, binaries, binaryStatus, &mImpl));
242 }
243 
Program(Context & context,DevicePtrs && devices,const char * kernelNames)244 Program::Program(Context &context, DevicePtrs &&devices, const char *kernelNames)
245     : mContext(&context), mDevices(std::move(devices)), mNumAttachedKernels(0u), mImpl(nullptr)
246 {
247     ANGLE_CL_IMPL_TRY(
248         context.getImpl().createProgramWithBuiltInKernels(*this, kernelNames, &mImpl));
249 }
250 
Program(Context & context,const DevicePtrs & devices,const char * options,const cl::ProgramPtrs & inputPrograms,ProgramCB pfnNotify,void * userData)251 Program::Program(Context &context,
252                  const DevicePtrs &devices,
253                  const char *options,
254                  const cl::ProgramPtrs &inputPrograms,
255                  ProgramCB pfnNotify,
256                  void *userData)
257     : mContext(&context),
258       mDevices(!devices.empty() ? devices : context.getDevices()),
259       mNumAttachedKernels(0u),
260       mImpl(nullptr)
261 {
262     if (pfnNotify != nullptr)
263     {
264         // This program has to be retained until the notify callback is called.
265         retain();
266         *mCallback = CallbackData(pfnNotify, userData);
267     }
268     else
269     {
270         *mCallback = CallbackData();
271     }
272     ANGLE_CL_IMPL_TRY(context.getImpl().linkProgram(*this, mDevices, options, inputPrograms,
273                                                     pfnNotify != nullptr ? this : nullptr, &mImpl));
274 }
275 
276 }  // namespace cl
277