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 
13 #include <cstring>
14 
15 namespace cl
16 {
17 
setArg(cl_uint argIndex, size_t argSize, const void *argValue)18 cl_int Kernel::setArg(cl_uint argIndex, size_t argSize, const void *argValue)
19 {
20     return mImpl->setArg(argIndex, argSize, argValue);
21 }
22 
getInfo(KernelInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const23 cl_int Kernel::getInfo(KernelInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
24 {
25     cl_uint valUInt       = 0u;
26     void *valPointer      = nullptr;
27     const void *copyValue = nullptr;
28     size_t copySize       = 0u;
29 
30     switch (name)
31     {
32         case KernelInfo::FunctionName:
33             copyValue = mInfo.functionName.c_str();
34             copySize  = mInfo.functionName.length() + 1u;
35             break;
36         case KernelInfo::NumArgs:
37             copyValue = &mInfo.numArgs;
38             copySize  = sizeof(mInfo.numArgs);
39             break;
40         case KernelInfo::ReferenceCount:
41             valUInt   = getRefCount();
42             copyValue = &valUInt;
43             copySize  = sizeof(valUInt);
44             break;
45         case KernelInfo::Context:
46             valPointer = mProgram->getContext().getNative();
47             copyValue  = &valPointer;
48             copySize   = sizeof(valPointer);
49             break;
50         case KernelInfo::Program:
51             valPointer = mProgram->getNative();
52             copyValue  = &valPointer;
53             copySize   = sizeof(valPointer);
54             break;
55         case KernelInfo::Attributes:
56             copyValue = mInfo.attributes.c_str();
57             copySize  = mInfo.attributes.length() + 1u;
58             break;
59         default:
60             return CL_INVALID_VALUE;
61     }
62 
63     if (value != nullptr)
64     {
65         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
66         // as described in the Kernel Object Queries table and param_value is not NULL.
67         if (valueSize < copySize)
68         {
69             return CL_INVALID_VALUE;
70         }
71         if (copyValue != nullptr)
72         {
73             std::memcpy(value, copyValue, copySize);
74         }
75     }
76     if (valueSizeRet != nullptr)
77     {
78         *valueSizeRet = copySize;
79     }
80     return CL_SUCCESS;
81 }
82 
getWorkGroupInfo(cl_device_id device, KernelWorkGroupInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const83 cl_int Kernel::getWorkGroupInfo(cl_device_id device,
84                                 KernelWorkGroupInfo name,
85                                 size_t valueSize,
86                                 void *value,
87                                 size_t *valueSizeRet) const
88 {
89     size_t index = 0u;
90     if (device != nullptr)
91     {
92         const DevicePtrs &devices = mProgram->getContext().getDevices();
93         while (index < devices.size() && devices[index] != device)
94         {
95             ++index;
96         }
97         if (index == devices.size())
98         {
99             return CL_INVALID_DEVICE;
100         }
101     }
102     const rx::CLKernelImpl::WorkGroupInfo &info = mInfo.workGroups[index];
103 
104     const void *copyValue = nullptr;
105     size_t copySize       = 0u;
106 
107     switch (name)
108     {
109         case KernelWorkGroupInfo::GlobalWorkSize:
110             copyValue = &info.globalWorkSize;
111             copySize  = sizeof(info.globalWorkSize);
112             break;
113         case KernelWorkGroupInfo::WorkGroupSize:
114             copyValue = &info.workGroupSize;
115             copySize  = sizeof(info.workGroupSize);
116             break;
117         case KernelWorkGroupInfo::CompileWorkGroupSize:
118             copyValue = &info.compileWorkGroupSize;
119             copySize  = sizeof(info.compileWorkGroupSize);
120             break;
121         case KernelWorkGroupInfo::LocalMemSize:
122             copyValue = &info.localMemSize;
123             copySize  = sizeof(info.localMemSize);
124             break;
125         case KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple:
126             copyValue = &info.prefWorkGroupSizeMultiple;
127             copySize  = sizeof(info.prefWorkGroupSizeMultiple);
128             break;
129         case KernelWorkGroupInfo::PrivateMemSize:
130             copyValue = &info.privateMemSize;
131             copySize  = sizeof(info.privateMemSize);
132             break;
133         default:
134             return CL_INVALID_VALUE;
135     }
136 
137     if (value != nullptr)
138     {
139         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
140         // as described in the Kernel Object Device Queries table and param_value is not NULL.
141         if (valueSize < copySize)
142         {
143             return CL_INVALID_VALUE;
144         }
145         if (copyValue != nullptr)
146         {
147             std::memcpy(value, copyValue, copySize);
148         }
149     }
150     if (valueSizeRet != nullptr)
151     {
152         *valueSizeRet = copySize;
153     }
154     return CL_SUCCESS;
155 }
156 
getArgInfo(cl_uint argIndex, KernelArgInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const157 cl_int Kernel::getArgInfo(cl_uint argIndex,
158                           KernelArgInfo name,
159                           size_t valueSize,
160                           void *value,
161                           size_t *valueSizeRet) const
162 {
163     const rx::CLKernelImpl::ArgInfo &info = mInfo.args[argIndex];
164     const void *copyValue                 = nullptr;
165     size_t copySize                       = 0u;
166 
167     switch (name)
168     {
169         case KernelArgInfo::AddressQualifier:
170             copyValue = &info.addressQualifier;
171             copySize  = sizeof(info.addressQualifier);
172             break;
173         case KernelArgInfo::AccessQualifier:
174             copyValue = &info.accessQualifier;
175             copySize  = sizeof(info.accessQualifier);
176             break;
177         case KernelArgInfo::TypeName:
178             copyValue = info.typeName.c_str();
179             copySize  = info.typeName.length() + 1u;
180             break;
181         case KernelArgInfo::TypeQualifier:
182             copyValue = &info.typeQualifier;
183             copySize  = sizeof(info.typeQualifier);
184             break;
185         case KernelArgInfo::Name:
186             copyValue = info.name.c_str();
187             copySize  = info.name.length() + 1u;
188             break;
189         default:
190             return CL_INVALID_VALUE;
191     }
192 
193     if (value != nullptr)
194     {
195         // CL_INVALID_VALUE if size in bytes specified by param_value size is < size of return type
196         // as described in the Kernel Argument Queries table and param_value is not NULL.
197         if (valueSize < copySize)
198         {
199             return CL_INVALID_VALUE;
200         }
201         if (copyValue != nullptr)
202         {
203             std::memcpy(value, copyValue, copySize);
204         }
205     }
206     if (valueSizeRet != nullptr)
207     {
208         *valueSizeRet = copySize;
209     }
210     return CL_SUCCESS;
211 }
212 
~Kernel()213 Kernel::~Kernel()
214 {
215     --mProgram->mNumAttachedKernels;
216 }
217 
Kernel(Program &program, const char *name, cl_int &errorCode)218 Kernel::Kernel(Program &program, const char *name, cl_int &errorCode)
219     : mProgram(&program),
220       mImpl(program.getImpl().createKernel(*this, name, errorCode)),
221       mInfo(mImpl ? mImpl->createInfo(errorCode) : rx::CLKernelImpl::Info{})
222 {
223     ++mProgram->mNumAttachedKernels;
224 }
225 
Kernel(Program &program, const rx::CLKernelImpl::CreateFunc &createFunc, cl_int &errorCode)226 Kernel::Kernel(Program &program, const rx::CLKernelImpl::CreateFunc &createFunc, cl_int &errorCode)
227     : mProgram(&program), mImpl(createFunc(*this)), mInfo(mImpl->createInfo(errorCode))
228 {
229     ++mProgram->mNumAttachedKernels;
230 }
231 
232 }  // namespace cl
233