xref: /aosp_15_r20/external/angle/src/libANGLE/CLKernel.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 // 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