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
15namespace cl
16{
17
18cl_int Kernel::setArg(cl_uint argIndex, size_t argSize, const void *argValue)
19{
20    return mImpl->setArg(argIndex, argSize, argValue);
21}
22
23cl_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
83cl_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
157cl_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
213Kernel::~Kernel()
214{
215    --mProgram->mNumAttachedKernels;
216}
217
218Kernel::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
226Kernel::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