• 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 
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