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 // CLDeviceVk.cpp: Implements the class methods for CLDeviceVk.
7
8 #include "libANGLE/renderer/vulkan/CLDeviceVk.h"
9 #include "libANGLE/renderer/vulkan/CLPlatformVk.h"
10 #include "libANGLE/renderer/vulkan/vk_renderer.h"
11
12 #include "libANGLE/Display.h"
13 #include "libANGLE/cl_utils.h"
14
15 namespace rx
16 {
17
CLDeviceVk(const cl::Device & device,vk::Renderer * renderer)18 CLDeviceVk::CLDeviceVk(const cl::Device &device, vk::Renderer *renderer)
19 : CLDeviceImpl(device), mRenderer(renderer)
20 {
21 const VkPhysicalDeviceProperties &props = mRenderer->getPhysicalDeviceProperties();
22
23 // Setup initial device mInfo fields
24 // TODO(aannestrand) Create cl::Caps and use for device creation
25 // http://anglebug.com/8529
26 mInfoString = {
27 {cl::DeviceInfo::Name, std::string(props.deviceName)},
28 {cl::DeviceInfo::Vendor, mRenderer->getVendorString()},
29 {cl::DeviceInfo::DriverVersion, mRenderer->getVersionString(true)},
30 {cl::DeviceInfo::Version, std::string("OpenCL 3.0 " + mRenderer->getVersionString(true))},
31 {cl::DeviceInfo::Profile, std::string("FULL_PROFILE")},
32 {cl::DeviceInfo::OpenCL_C_Version, std::string("OpenCL C 3.0 ")},
33 {cl::DeviceInfo::LatestConformanceVersionPassed, std::string("FIXME")}};
34 mInfoSizeT = {
35 {cl::DeviceInfo::MaxWorkGroupSize, props.limits.maxComputeWorkGroupInvocations},
36 {cl::DeviceInfo::MaxGlobalVariableSize, 0},
37 {cl::DeviceInfo::GlobalVariablePreferredTotalSize, 0},
38
39 // TODO(aannestrand) Update these hardcoded platform/device queries
40 // http://anglebug.com/8511
41 {cl::DeviceInfo::MaxParameterSize, 1024},
42 {cl::DeviceInfo::ProfilingTimerResolution, 1},
43 {cl::DeviceInfo::PrintfBufferSize, 1024 * 1024},
44 {cl::DeviceInfo::PreferredWorkGroupSizeMultiple, 16},
45 };
46 mInfoULong = {
47 {cl::DeviceInfo::LocalMemSize, props.limits.maxComputeSharedMemorySize},
48 {cl::DeviceInfo::SVM_Capabilities, 0},
49 {cl::DeviceInfo::QueueOnDeviceProperties, 0},
50 {cl::DeviceInfo::PartitionAffinityDomain, 0},
51 {cl::DeviceInfo::DeviceEnqueueCapabilities, 0},
52 {cl::DeviceInfo::QueueOnHostProperties, CL_QUEUE_PROFILING_ENABLE},
53
54 // TODO(aannestrand) Update these hardcoded platform/device queries
55 // http://anglebug.com/8511
56 {cl::DeviceInfo::HalfFpConfig, 0},
57 {cl::DeviceInfo::DoubleFpConfig, 0},
58 {cl::DeviceInfo::GlobalMemCacheSize, 0},
59 {cl::DeviceInfo::GlobalMemSize, 1024 * 1024 * 1024},
60 {cl::DeviceInfo::MaxConstantBufferSize, 64 * 1024},
61 {cl::DeviceInfo::SingleFpConfig, CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN | CL_FP_FMA},
62 {cl::DeviceInfo::AtomicMemoryCapabilities,
63 CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP},
64 {cl::DeviceInfo::AtomicFenceCapabilities, CL_DEVICE_ATOMIC_ORDER_RELAXED |
65 CL_DEVICE_ATOMIC_SCOPE_WORK_ITEM |
66 CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP},
67 };
68 mInfoUInt = {
69 {cl::DeviceInfo::VendorID, props.vendorID},
70 {cl::DeviceInfo::MaxReadImageArgs, props.limits.maxPerStageDescriptorSampledImages},
71 {cl::DeviceInfo::MaxWriteImageArgs, props.limits.maxPerStageDescriptorStorageImages},
72 {cl::DeviceInfo::MaxReadWriteImageArgs, props.limits.maxPerStageDescriptorStorageImages},
73 {cl::DeviceInfo::GlobalMemCachelineSize,
74 static_cast<cl_uint>(props.limits.nonCoherentAtomSize)},
75 {cl::DeviceInfo::Available, CL_TRUE},
76 {cl::DeviceInfo::LinkerAvailable, CL_TRUE},
77 {cl::DeviceInfo::CompilerAvailable, CL_TRUE},
78 {cl::DeviceInfo::MaxOnDeviceQueues, 0},
79 {cl::DeviceInfo::MaxOnDeviceEvents, 0},
80 {cl::DeviceInfo::QueueOnDeviceMaxSize, 0},
81 {cl::DeviceInfo::QueueOnDevicePreferredSize, 0},
82 {cl::DeviceInfo::MaxPipeArgs, 0},
83 {cl::DeviceInfo::PipeMaxPacketSize, 0},
84 {cl::DeviceInfo::PipeSupport, CL_FALSE},
85 {cl::DeviceInfo::PipeMaxActiveReservations, 0},
86 {cl::DeviceInfo::ErrorCorrectionSupport, CL_FALSE},
87 {cl::DeviceInfo::PreferredInteropUserSync, CL_TRUE},
88 {cl::DeviceInfo::ExecutionCapabilities, CL_EXEC_KERNEL},
89
90 // TODO(aannestrand) Update these hardcoded platform/device queries
91 // http://anglebug.com/8511
92 {cl::DeviceInfo::AddressBits, 64},
93 {cl::DeviceInfo::EndianLittle, CL_TRUE},
94 {cl::DeviceInfo::LocalMemType, CL_LOCAL},
95 {cl::DeviceInfo::MaxSamplers, 0},
96 {cl::DeviceInfo::MaxConstantArgs, 8},
97 {cl::DeviceInfo::MaxNumSubGroups, 0},
98 {cl::DeviceInfo::MaxComputeUnits, 4},
99 {cl::DeviceInfo::MaxClockFrequency, 555},
100 {cl::DeviceInfo::MaxWorkItemDimensions, 3},
101 {cl::DeviceInfo::MinDataTypeAlignSize, 128},
102 {cl::DeviceInfo::GlobalMemCacheType, CL_NONE},
103 {cl::DeviceInfo::HostUnifiedMemory, CL_TRUE},
104 {cl::DeviceInfo::NativeVectorWidthChar, 4},
105 {cl::DeviceInfo::NativeVectorWidthShort, 2},
106 {cl::DeviceInfo::NativeVectorWidthInt, 1},
107 {cl::DeviceInfo::NativeVectorWidthLong, 1},
108 {cl::DeviceInfo::NativeVectorWidthFloat, 1},
109 {cl::DeviceInfo::NativeVectorWidthDouble, 1},
110 {cl::DeviceInfo::NativeVectorWidthHalf, 0},
111 {cl::DeviceInfo::PartitionMaxSubDevices, 0},
112 {cl::DeviceInfo::PreferredVectorWidthInt, 1},
113 {cl::DeviceInfo::PreferredVectorWidthLong, 1},
114 {cl::DeviceInfo::PreferredVectorWidthChar, 4},
115 {cl::DeviceInfo::PreferredVectorWidthHalf, 0},
116 {cl::DeviceInfo::PreferredVectorWidthShort, 2},
117 {cl::DeviceInfo::PreferredVectorWidthFloat, 1},
118 {cl::DeviceInfo::PreferredVectorWidthDouble, 0},
119 {cl::DeviceInfo::PreferredLocalAtomicAlignment, 0},
120 {cl::DeviceInfo::PreferredGlobalAtomicAlignment, 0},
121 {cl::DeviceInfo::PreferredPlatformAtomicAlignment, 0},
122 {cl::DeviceInfo::NonUniformWorkGroupSupport, CL_TRUE},
123 {cl::DeviceInfo::GenericAddressSpaceSupport, CL_FALSE},
124 {cl::DeviceInfo::SubGroupIndependentForwardProgress, CL_FALSE},
125 {cl::DeviceInfo::WorkGroupCollectiveFunctionsSupport, CL_FALSE},
126 };
127 }
128
129 CLDeviceVk::~CLDeviceVk() = default;
130
createInfo(cl::DeviceType type) const131 CLDeviceImpl::Info CLDeviceVk::createInfo(cl::DeviceType type) const
132 {
133 Info info(type);
134
135 const VkPhysicalDeviceProperties &properties = mRenderer->getPhysicalDeviceProperties();
136
137 info.maxWorkItemSizes.push_back(properties.limits.maxComputeWorkGroupSize[0]);
138 info.maxWorkItemSizes.push_back(properties.limits.maxComputeWorkGroupSize[1]);
139 info.maxWorkItemSizes.push_back(properties.limits.maxComputeWorkGroupSize[2]);
140
141 // TODO(aannestrand) Update these hardcoded platform/device queries
142 // http://anglebug.com/8511
143 info.maxMemAllocSize = 1 << 30;
144 info.memBaseAddrAlign = 1024;
145
146 // TODO(aannestrand) Add image and sampler support later
147 // http://anglebug.com/8512
148 info.imageSupport = CL_FALSE;
149
150 info.image2D_MaxWidth = properties.limits.maxImageDimension2D;
151 info.image2D_MaxHeight = properties.limits.maxImageDimension2D;
152 info.image3D_MaxWidth = properties.limits.maxImageDimension3D;
153 info.image3D_MaxHeight = properties.limits.maxImageDimension3D;
154 info.image3D_MaxDepth = properties.limits.maxImageDimension3D;
155 info.imageMaxBufferSize = properties.limits.maxImageDimension1D;
156 info.imageMaxArraySize = properties.limits.maxImageArrayLayers;
157 info.imagePitchAlignment = 0u;
158 info.imageBaseAddressAlignment = 0u;
159
160 info.execCapabilities = CL_EXEC_KERNEL;
161 info.queueOnDeviceMaxSize = 0u;
162 info.builtInKernels = "";
163 info.version = CL_MAKE_VERSION(3, 0, 0);
164 info.versionStr = "OpenCL 3.0 " + mRenderer->getVersionString(true);
165 info.OpenCL_C_AllVersions = {{CL_MAKE_VERSION(3, 0, 0), "OpenCL C"},
166 {CL_MAKE_VERSION(2, 0, 0), "OpenCL C"},
167 {CL_MAKE_VERSION(1, 2, 0), "OpenCL C"},
168 {CL_MAKE_VERSION(1, 1, 0), "OpenCL C"},
169 {CL_MAKE_VERSION(1, 0, 0), "OpenCL C"}};
170
171 info.OpenCL_C_Features = {};
172 info.extensionsWithVersion = {};
173 info.ILsWithVersion = {};
174 info.builtInKernelsWithVersion = {};
175 info.partitionProperties = {};
176 info.partitionType = {};
177 info.IL_Version = "";
178
179 // Below extensions are required as of OpenCL 1.1
180 info.extensions =
181 "cl_khr_byte_addressable_store "
182 "cl_khr_global_int32_base_atomics "
183 "cl_khr_global_int32_extended_atomics "
184 "cl_khr_local_int32_base_atomics "
185 "cl_khr_local_int32_extended_atomics ";
186
187 return info;
188 }
189
getInfoUInt(cl::DeviceInfo name,cl_uint * value) const190 angle::Result CLDeviceVk::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const
191 {
192 if (mInfoUInt.count(name))
193 {
194 *value = mInfoUInt.at(name);
195 return angle::Result::Continue;
196 }
197 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
198 }
199
getInfoULong(cl::DeviceInfo name,cl_ulong * value) const200 angle::Result CLDeviceVk::getInfoULong(cl::DeviceInfo name, cl_ulong *value) const
201 {
202 if (mInfoULong.count(name))
203 {
204 *value = mInfoULong.at(name);
205 return angle::Result::Continue;
206 }
207 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
208 }
209
getInfoSizeT(cl::DeviceInfo name,size_t * value) const210 angle::Result CLDeviceVk::getInfoSizeT(cl::DeviceInfo name, size_t *value) const
211 {
212 if (mInfoSizeT.count(name))
213 {
214 *value = mInfoSizeT.at(name);
215 return angle::Result::Continue;
216 }
217 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
218 }
219
getInfoStringLength(cl::DeviceInfo name,size_t * value) const220 angle::Result CLDeviceVk::getInfoStringLength(cl::DeviceInfo name, size_t *value) const
221 {
222 if (mInfoString.count(name))
223 {
224 *value = mInfoString.at(name).length() + 1;
225 return angle::Result::Continue;
226 }
227 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
228 }
229
getInfoString(cl::DeviceInfo name,size_t size,char * value) const230 angle::Result CLDeviceVk::getInfoString(cl::DeviceInfo name, size_t size, char *value) const
231 {
232 if (mInfoString.count(name))
233 {
234 std::strcpy(value, mInfoString.at(name).c_str());
235 return angle::Result::Continue;
236 }
237 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
238 }
239
createSubDevices(const cl_device_partition_property * properties,cl_uint numDevices,CreateFuncs & subDevices,cl_uint * numDevicesRet)240 angle::Result CLDeviceVk::createSubDevices(const cl_device_partition_property *properties,
241 cl_uint numDevices,
242 CreateFuncs &subDevices,
243 cl_uint *numDevicesRet)
244 {
245 UNIMPLEMENTED();
246 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
247 }
248
selectWorkGroupSize(const cl::NDRange & ndrange) const249 cl::WorkgroupSize CLDeviceVk::selectWorkGroupSize(const cl::NDRange &ndrange) const
250 {
251 // Limit total work-group size to the Vulkan device's limit
252 const VkPhysicalDeviceProperties &props = mRenderer->getPhysicalDeviceProperties();
253 uint32_t maxSize = static_cast<uint32_t>(mInfoSizeT.at(cl::DeviceInfo::MaxWorkGroupSize));
254 maxSize = std::min(maxSize, 64u);
255
256 bool keepIncreasing = false;
257 cl::WorkgroupSize localSize = {1, 1, 1};
258 do
259 {
260 keepIncreasing = false;
261 for (cl_uint i = 0; i < ndrange.workDimensions; i++)
262 {
263 cl::WorkgroupSize newLocalSize = localSize;
264 newLocalSize[i] *= 2;
265
266 // TODO: Add support for non-uniform WGS
267 // http://anglebug.com/8631
268 if (ndrange.globalWorkSize[i] % newLocalSize[i] == 0 &&
269 newLocalSize[i] <= props.limits.maxComputeWorkGroupCount[i] &&
270 newLocalSize[0] * newLocalSize[1] * newLocalSize[2] <= maxSize)
271 {
272 localSize = newLocalSize;
273 keepIncreasing = true;
274 }
275 }
276 } while (keepIncreasing);
277
278 return localSize;
279 }
280
281 } // namespace rx
282