• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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