• 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 // CLKernelCL.cpp: Implements the class methods for CLKernelCL.
7 
8 #include "libANGLE/renderer/cl/CLKernelCL.h"
9 
10 #include "libANGLE/renderer/cl/CLCommandQueueCL.h"
11 #include "libANGLE/renderer/cl/CLContextCL.h"
12 #include "libANGLE/renderer/cl/CLDeviceCL.h"
13 #include "libANGLE/renderer/cl/CLMemoryCL.h"
14 #include "libANGLE/renderer/cl/CLSamplerCL.h"
15 
16 #include "libANGLE/CLCommandQueue.h"
17 #include "libANGLE/CLContext.h"
18 #include "libANGLE/CLKernel.h"
19 #include "libANGLE/CLMemory.h"
20 #include "libANGLE/CLPlatform.h"
21 #include "libANGLE/CLProgram.h"
22 #include "libANGLE/CLSampler.h"
23 
24 namespace rx
25 {
26 
27 namespace
28 {
29 
30 template <typename T>
GetWorkGroupInfo(cl_kernel kernel,cl_device_id device,cl::KernelWorkGroupInfo name,T & value,cl_int & errorCode)31 bool GetWorkGroupInfo(cl_kernel kernel,
32                       cl_device_id device,
33                       cl::KernelWorkGroupInfo name,
34                       T &value,
35                       cl_int &errorCode)
36 {
37     errorCode = kernel->getDispatch().clGetKernelWorkGroupInfo(kernel, device, cl::ToCLenum(name),
38                                                                sizeof(T), &value, nullptr);
39     return errorCode == CL_SUCCESS;
40 }
41 
42 template <typename T>
GetArgInfo(cl_kernel kernel,cl_uint index,cl::KernelArgInfo name,T & value,cl_int & errorCode)43 bool GetArgInfo(cl_kernel kernel,
44                 cl_uint index,
45                 cl::KernelArgInfo name,
46                 T &value,
47                 cl_int &errorCode)
48 {
49     errorCode = kernel->getDispatch().clGetKernelArgInfo(kernel, index, cl::ToCLenum(name),
50                                                          sizeof(T), &value, nullptr);
51     if (errorCode == CL_KERNEL_ARG_INFO_NOT_AVAILABLE)
52     {
53         errorCode = CL_SUCCESS;
54     }
55     return errorCode == CL_SUCCESS;
56 }
57 
58 template <typename T>
GetKernelInfo(cl_kernel kernel,cl::KernelInfo name,T & value,cl_int & errorCode)59 bool GetKernelInfo(cl_kernel kernel, cl::KernelInfo name, T &value, cl_int &errorCode)
60 {
61     errorCode = kernel->getDispatch().clGetKernelInfo(kernel, cl::ToCLenum(name), sizeof(T), &value,
62                                                       nullptr);
63     return errorCode == CL_SUCCESS;
64 }
65 
GetArgString(cl_kernel kernel,cl_uint index,cl::KernelArgInfo name,std::string & string,cl_int & errorCode)66 bool GetArgString(cl_kernel kernel,
67                   cl_uint index,
68                   cl::KernelArgInfo name,
69                   std::string &string,
70                   cl_int &errorCode)
71 {
72     size_t size = 0u;
73     errorCode   = kernel->getDispatch().clGetKernelArgInfo(kernel, index, cl::ToCLenum(name), 0u,
74                                                          nullptr, &size);
75     if (errorCode == CL_KERNEL_ARG_INFO_NOT_AVAILABLE)
76     {
77         errorCode = CL_SUCCESS;
78         return true;
79     }
80     else if (errorCode != CL_SUCCESS)
81     {
82         return false;
83     }
84     std::vector<char> valString(size, '\0');
85     errorCode = kernel->getDispatch().clGetKernelArgInfo(kernel, index, cl::ToCLenum(name), size,
86                                                          valString.data(), nullptr);
87     if (errorCode != CL_SUCCESS)
88     {
89         return false;
90     }
91     string.assign(valString.data(), valString.size() - 1u);
92     return true;
93 }
94 
GetKernelString(cl_kernel kernel,cl::KernelInfo name,std::string & string,cl_int & errorCode)95 bool GetKernelString(cl_kernel kernel, cl::KernelInfo name, std::string &string, cl_int &errorCode)
96 {
97     size_t size = 0u;
98     errorCode =
99         kernel->getDispatch().clGetKernelInfo(kernel, cl::ToCLenum(name), 0u, nullptr, &size);
100     if (errorCode != CL_SUCCESS)
101     {
102         return false;
103     }
104     std::vector<char> valString(size, '\0');
105     errorCode = kernel->getDispatch().clGetKernelInfo(kernel, cl::ToCLenum(name), size,
106                                                       valString.data(), nullptr);
107     if (errorCode != CL_SUCCESS)
108     {
109         return false;
110     }
111     string.assign(valString.data(), valString.size() - 1u);
112     return true;
113 }
114 
115 }  // namespace
116 
CLKernelCL(const cl::Kernel & kernel,cl_kernel native)117 CLKernelCL::CLKernelCL(const cl::Kernel &kernel, cl_kernel native)
118     : CLKernelImpl(kernel), mNative(native)
119 {}
120 
~CLKernelCL()121 CLKernelCL::~CLKernelCL()
122 {
123     if (mNative->getDispatch().clReleaseKernel(mNative) != CL_SUCCESS)
124     {
125         ERR() << "Error while releasing CL kernel";
126     }
127 }
128 
setArg(cl_uint argIndex,size_t argSize,const void * argValue)129 cl_int CLKernelCL::setArg(cl_uint argIndex, size_t argSize, const void *argValue)
130 {
131     void *value = nullptr;
132     if (argValue != nullptr)
133     {
134         // If argument is a CL object, fetch the mapped value
135         const CLContextCL &ctx = mKernel.getProgram().getContext().getImpl<CLContextCL>();
136         if (argSize == sizeof(cl_mem))
137         {
138             cl_mem memory = *static_cast<const cl_mem *>(argValue);
139             if (ctx.hasMemory(memory))
140             {
141                 value = memory->cast<cl::Memory>().getImpl<CLMemoryCL>().getNative();
142             }
143         }
144         if (value == nullptr && argSize == sizeof(cl_sampler))
145         {
146             cl_sampler sampler = *static_cast<const cl_sampler *>(argValue);
147             if (ctx.hasSampler(sampler))
148             {
149                 value = sampler->cast<cl::Sampler>().getImpl<CLSamplerCL>().getNative();
150             }
151         }
152         if (value == nullptr && argSize == sizeof(cl_command_queue))
153         {
154             cl_command_queue queue = *static_cast<const cl_command_queue *>(argValue);
155             if (ctx.hasDeviceQueue(queue))
156             {
157                 value = queue->cast<cl::CommandQueue>().getImpl<CLCommandQueueCL>().getNative();
158             }
159         }
160     }
161 
162     // If mapped value was found, use it instead of original value
163     if (value != nullptr)
164     {
165         argValue = &value;
166     }
167     return mNative->getDispatch().clSetKernelArg(mNative, argIndex, argSize, argValue);
168 }
169 
createInfo(cl_int & errorCode) const170 CLKernelImpl::Info CLKernelCL::createInfo(cl_int &errorCode) const
171 {
172     const cl::Context &ctx = mKernel.getProgram().getContext();
173     Info info;
174 
175     if (!GetKernelString(mNative, cl::KernelInfo::FunctionName, info.functionName, errorCode) ||
176         !GetKernelInfo(mNative, cl::KernelInfo::NumArgs, info.numArgs, errorCode) ||
177         (ctx.getPlatform().isVersionOrNewer(1u, 2u) &&
178          !GetKernelString(mNative, cl::KernelInfo::Attributes, info.attributes, errorCode)))
179     {
180         return Info{};
181     }
182 
183     info.workGroups.resize(ctx.getDevices().size());
184     for (size_t index = 0u; index < ctx.getDevices().size(); ++index)
185     {
186         const cl_device_id device = ctx.getDevices()[index]->getImpl<CLDeviceCL>().getNative();
187         WorkGroupInfo &workGroup  = info.workGroups[index];
188 
189         if ((ctx.getPlatform().isVersionOrNewer(1u, 2u) &&
190              ctx.getDevices()[index]->supportsBuiltInKernel(info.functionName) &&
191              !GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::GlobalWorkSize,
192                                workGroup.globalWorkSize, errorCode)) ||
193             !GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::WorkGroupSize,
194                               workGroup.workGroupSize, errorCode) ||
195             !GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::CompileWorkGroupSize,
196                               workGroup.compileWorkGroupSize, errorCode) ||
197             !GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::LocalMemSize,
198                               workGroup.localMemSize, errorCode) ||
199             !GetWorkGroupInfo(mNative, device,
200                               cl::KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple,
201                               workGroup.prefWorkGroupSizeMultiple, errorCode) ||
202             !GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::PrivateMemSize,
203                               workGroup.privateMemSize, errorCode))
204         {
205             return Info{};
206         }
207     }
208 
209     info.args.resize(info.numArgs);
210     if (ctx.getPlatform().isVersionOrNewer(1u, 2u))
211     {
212         for (cl_uint index = 0u; index < info.numArgs; ++index)
213         {
214             ArgInfo &arg = info.args[index];
215             if (!GetArgInfo(mNative, index, cl::KernelArgInfo::AddressQualifier,
216                             arg.addressQualifier, errorCode) ||
217                 !GetArgInfo(mNative, index, cl::KernelArgInfo::AccessQualifier, arg.accessQualifier,
218                             errorCode) ||
219                 !GetArgString(mNative, index, cl::KernelArgInfo::TypeName, arg.typeName,
220                               errorCode) ||
221                 !GetArgInfo(mNative, index, cl::KernelArgInfo::TypeQualifier, arg.typeQualifier,
222                             errorCode) ||
223                 !GetArgString(mNative, index, cl::KernelArgInfo::Name, arg.name, errorCode))
224             {
225                 return Info{};
226             }
227         }
228     }
229 
230     return info;
231 }
232 
233 }  // namespace rx
234