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 // CLKernel.cpp: Implements the cl::Kernel class.
7
8 #include "libANGLE/CLKernel.h"
9
10 #include "libANGLE/CLContext.h"
11 #include "libANGLE/CLProgram.h"
12 #include "libANGLE/cl_utils.h"
13
14 #include <cstring>
15
16 namespace cl
17 {
18
setArg(cl_uint argIndex,size_t argSize,const void * argValue)19 angle::Result Kernel::setArg(cl_uint argIndex, size_t argSize, const void *argValue)
20 {
21 ANGLE_TRY(mImpl->setArg(argIndex, argSize, argValue));
22
23 mSetArguments[argIndex] = {true, argIndex, argSize, argValue};
24 return angle::Result::Continue;
25 }
26
getInfo(KernelInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const27 angle::Result Kernel::getInfo(KernelInfo name,
28 size_t valueSize,
29 void *value,
30 size_t *valueSizeRet) const
31 {
32 cl_uint valUInt = 0u;
33 void *valPointer = nullptr;
34 const void *copyValue = nullptr;
35 size_t copySize = 0u;
36
37 switch (name)
38 {
39 case KernelInfo::FunctionName:
40 copyValue = mInfo.functionName.c_str();
41 copySize = mInfo.functionName.length() + 1u;
42 break;
43 case KernelInfo::NumArgs:
44 copyValue = &mInfo.numArgs;
45 copySize = sizeof(mInfo.numArgs);
46 break;
47 case KernelInfo::ReferenceCount:
48 valUInt = getRefCount();
49 copyValue = &valUInt;
50 copySize = sizeof(valUInt);
51 break;
52 case KernelInfo::Context:
53 valPointer = mProgram->getContext().getNative();
54 copyValue = &valPointer;
55 copySize = sizeof(valPointer);
56 break;
57 case KernelInfo::Program:
58 valPointer = mProgram->getNative();
59 copyValue = &valPointer;
60 copySize = sizeof(valPointer);
61 break;
62 case KernelInfo::Attributes:
63 copyValue = mInfo.attributes.c_str();
64 copySize = mInfo.attributes.length() + 1u;
65 break;
66 default:
67 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
68 }
69
70 if (value != nullptr)
71 {
72 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
73 // as described in the Kernel Object Queries table and param_value is not NULL.
74 if (valueSize < copySize)
75 {
76 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
77 }
78 if (copyValue != nullptr)
79 {
80 std::memcpy(value, copyValue, copySize);
81 }
82 }
83 if (valueSizeRet != nullptr)
84 {
85 *valueSizeRet = copySize;
86 }
87 return angle::Result::Continue;
88 }
89
getWorkGroupInfo(cl_device_id device,KernelWorkGroupInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const90 angle::Result Kernel::getWorkGroupInfo(cl_device_id device,
91 KernelWorkGroupInfo name,
92 size_t valueSize,
93 void *value,
94 size_t *valueSizeRet) const
95 {
96 size_t index = 0u;
97 if (device != nullptr)
98 {
99 const DevicePtrs &devices = mProgram->getContext().getDevices();
100 while (index < devices.size() && devices[index] != device)
101 {
102 ++index;
103 }
104 if (index == devices.size())
105 {
106 ANGLE_CL_RETURN_ERROR(CL_INVALID_DEVICE);
107 }
108 }
109 const rx::CLKernelImpl::WorkGroupInfo &info = mInfo.workGroups[index];
110
111 const void *copyValue = nullptr;
112 size_t copySize = 0u;
113
114 switch (name)
115 {
116 case KernelWorkGroupInfo::GlobalWorkSize:
117 copyValue = &info.globalWorkSize;
118 copySize = sizeof(info.globalWorkSize);
119 break;
120 case KernelWorkGroupInfo::WorkGroupSize:
121 copyValue = &info.workGroupSize;
122 copySize = sizeof(info.workGroupSize);
123 break;
124 case KernelWorkGroupInfo::CompileWorkGroupSize:
125 copyValue = &info.compileWorkGroupSize;
126 copySize = sizeof(info.compileWorkGroupSize);
127 break;
128 case KernelWorkGroupInfo::LocalMemSize:
129 copyValue = &info.localMemSize;
130 copySize = sizeof(info.localMemSize);
131 break;
132 case KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple:
133 copyValue = &info.prefWorkGroupSizeMultiple;
134 copySize = sizeof(info.prefWorkGroupSizeMultiple);
135 break;
136 case KernelWorkGroupInfo::PrivateMemSize:
137 copyValue = &info.privateMemSize;
138 copySize = sizeof(info.privateMemSize);
139 break;
140 default:
141 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
142 }
143
144 if (value != nullptr)
145 {
146 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
147 // as described in the Kernel Object Device Queries table and param_value is not NULL.
148 if (valueSize < copySize)
149 {
150 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
151 }
152 if (copyValue != nullptr)
153 {
154 std::memcpy(value, copyValue, copySize);
155 }
156 }
157 if (valueSizeRet != nullptr)
158 {
159 *valueSizeRet = copySize;
160 }
161 return angle::Result::Continue;
162 }
163
getArgInfo(cl_uint argIndex,KernelArgInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const164 angle::Result Kernel::getArgInfo(cl_uint argIndex,
165 KernelArgInfo name,
166 size_t valueSize,
167 void *value,
168 size_t *valueSizeRet) const
169 {
170 const rx::CLKernelImpl::ArgInfo &info = mInfo.args[argIndex];
171 const void *copyValue = nullptr;
172 size_t copySize = 0u;
173
174 switch (name)
175 {
176 case KernelArgInfo::AddressQualifier:
177 copyValue = &info.addressQualifier;
178 copySize = sizeof(info.addressQualifier);
179 break;
180 case KernelArgInfo::AccessQualifier:
181 copyValue = &info.accessQualifier;
182 copySize = sizeof(info.accessQualifier);
183 break;
184 case KernelArgInfo::TypeName:
185 copyValue = info.typeName.c_str();
186 copySize = info.typeName.length() + 1u;
187 break;
188 case KernelArgInfo::TypeQualifier:
189 copyValue = &info.typeQualifier;
190 copySize = sizeof(info.typeQualifier);
191 break;
192 case KernelArgInfo::Name:
193 copyValue = info.name.c_str();
194 copySize = info.name.length() + 1u;
195 break;
196 default:
197 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
198 }
199
200 if (value != nullptr)
201 {
202 // CL_INVALID_VALUE if size in bytes specified by param_value size is < size of return type
203 // as described in the Kernel Argument Queries table and param_value is not NULL.
204 if (valueSize < copySize)
205 {
206 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
207 }
208 if (copyValue != nullptr)
209 {
210 std::memcpy(value, copyValue, copySize);
211 }
212 }
213 if (valueSizeRet != nullptr)
214 {
215 *valueSizeRet = copySize;
216 }
217 return angle::Result::Continue;
218 }
219
clone() const220 Kernel *Kernel::clone() const
221 {
222 cl_kernel kernel = mProgram->createKernel(getName().c_str());
223
224 for (KernelArg arg : mSetArguments)
225 {
226 if (arg.isSet && IsError(kernel->cast<Kernel>().setArg(arg.index, arg.size, arg.valuePtr)))
227 {
228 ANGLE_CL_SET_ERROR(CL_OUT_OF_RESOURCES);
229 return nullptr;
230 }
231 }
232 return &kernel->cast<Kernel>();
233 }
234
~Kernel()235 Kernel::~Kernel()
236 {
237 --mProgram->mNumAttachedKernels;
238 }
239
Kernel(Program & program,const char * name)240 Kernel::Kernel(Program &program, const char *name) : mProgram(&program), mImpl(nullptr)
241 {
242 if (!IsError(program.getImpl().createKernel(*this, name, &mImpl)))
243 {
244 initImpl();
245 }
246 }
247
Kernel(Program & program,const rx::CLKernelImpl::CreateFunc & createFunc)248 Kernel::Kernel(Program &program, const rx::CLKernelImpl::CreateFunc &createFunc)
249 : mProgram(&program), mImpl(createFunc(*this))
250 {
251 if (mImpl)
252 {
253 initImpl();
254 }
255 }
256
initImpl()257 void Kernel::initImpl()
258 {
259 ANGLE_CL_IMPL_TRY(mImpl->createInfo(&mInfo));
260
261 mSetArguments.resize(mInfo.numArgs);
262 std::fill(mSetArguments.begin(), mSetArguments.end(), KernelArg{false, 0, 0, 0});
263
264 ++mProgram->mNumAttachedKernels;
265 }
266
267 } // namespace cl
268