xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/CLPlatformVk.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 // CLPlatformVk.cpp: Implements the class methods for CLPlatformVk.
7 
8 #include "libANGLE/renderer/vulkan/CLPlatformVk.h"
9 #include "common/vulkan/vulkan_icd.h"
10 #include "libANGLE/angletypes.h"
11 #include "libANGLE/renderer/vulkan/CLContextVk.h"
12 #include "libANGLE/renderer/vulkan/CLDeviceVk.h"
13 #include "libANGLE/renderer/vulkan/vk_renderer.h"
14 
15 #include "libANGLE/CLPlatform.h"
16 #include "libANGLE/cl_utils.h"
17 
18 #include "anglebase/no_destructor.h"
19 #include "common/angle_version_info.h"
20 #include "libANGLE/renderer/vulkan/vk_utils.h"
21 #include "vulkan/vulkan_core.h"
22 
23 namespace rx
24 {
25 
26 namespace
27 {
28 #if defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT)
29 constexpr vk::UseDebugLayers kUseDebugLayers = vk::UseDebugLayers::YesIfAvailable;
30 #else
31 constexpr vk::UseDebugLayers kUseDebugLayers = vk::UseDebugLayers::No;
32 #endif
33 }  // namespace
34 
initBackendRenderer()35 angle::Result CLPlatformVk::initBackendRenderer()
36 {
37     ASSERT(mRenderer != nullptr);
38 
39     angle::FeatureOverrides featureOverrides;
40 
41     // In memory |SizedMRUCache| does not require dual slots, supports zero sized values, and evicts
42     // minumum number of old items when storing a new item.
43     featureOverrides.disabled.push_back("useDualPipelineBlobCacheSlots");
44     featureOverrides.enabled.push_back("useEmptyBlobsToEraseOldPipelineCacheFromBlobCache");
45     featureOverrides.enabled.push_back("hasBlobCacheThatEvictsOldItemsFirst");
46     featureOverrides.disabled.push_back("verifyPipelineCacheInBlobCache");
47 
48     ANGLE_TRY(mRenderer->initialize(this, this, angle::vk::ICD::Default, 0, 0, kUseDebugLayers,
49                                     getWSIExtension(), getWSILayer(), getWindowSystem(),
50                                     featureOverrides));
51 
52     return angle::Result::Continue;
53 }
54 
~CLPlatformVk()55 CLPlatformVk::~CLPlatformVk()
56 {
57     ASSERT(mRenderer);
58     mRenderer->onDestroy(this);
59     delete mRenderer;
60 }
61 
createInfo() const62 CLPlatformImpl::Info CLPlatformVk::createInfo() const
63 {
64     NameVersionVector extList = {
65         cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_icd"},
66         cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_extended_versioning"}};
67 
68     Info info;
69     info.name.assign("ANGLE Vulkan");
70     info.profile.assign("FULL_PROFILE");
71     info.versionStr.assign(GetVersionString());
72     info.hostTimerRes = 0u;
73     info.version      = GetVersion();
74 
75     info.initializeVersionedExtensions(std::move(extList));
76     return info;
77 }
78 
createDevices() const79 CLDeviceImpl::CreateDatas CLPlatformVk::createDevices() const
80 {
81     CLDeviceImpl::CreateDatas createDatas;
82 
83     // Convert Vk device type to CL equivalent
84     cl_device_type type = CL_DEVICE_TYPE_DEFAULT;
85     switch (mRenderer->getPhysicalDeviceProperties().deviceType)
86     {
87         case VK_PHYSICAL_DEVICE_TYPE_CPU:
88             type |= CL_DEVICE_TYPE_CPU;
89             break;
90         case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
91         case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
92         case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
93             type |= CL_DEVICE_TYPE_GPU;
94             break;
95         case VK_PHYSICAL_DEVICE_TYPE_OTHER:
96         case VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM:
97             // The default OpenCL device must not be a CL_DEVICE_TYPE_CUSTOM device.
98             // Thus, we override type bitfield to custom only.
99             type = CL_DEVICE_TYPE_CUSTOM;
100             break;
101     }
102 
103     createDatas.emplace_back(type, [this](const cl::Device &device) {
104         return CLDeviceVk::Ptr(new CLDeviceVk(device, mRenderer));
105     });
106     return createDatas;
107 }
108 
createContext(cl::Context & context,const cl::DevicePtrs & devices,bool userSync,CLContextImpl::Ptr * contextOut)109 angle::Result CLPlatformVk::createContext(cl::Context &context,
110                                           const cl::DevicePtrs &devices,
111                                           bool userSync,
112                                           CLContextImpl::Ptr *contextOut)
113 {
114     *contextOut = CLContextImpl::Ptr(new (std::nothrow) CLContextVk(context, devices));
115     if (*contextOut == nullptr)
116     {
117         ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
118     }
119     return angle::Result::Continue;
120 }
121 
createContextFromType(cl::Context & context,cl::DeviceType deviceType,bool userSync,CLContextImpl::Ptr * contextOut)122 angle::Result CLPlatformVk::createContextFromType(cl::Context &context,
123                                                   cl::DeviceType deviceType,
124                                                   bool userSync,
125                                                   CLContextImpl::Ptr *contextOut)
126 {
127     const VkPhysicalDeviceType &vkPhysicalDeviceType =
128         getRenderer()->getPhysicalDeviceProperties().deviceType;
129 
130     if (deviceType.intersects(CL_DEVICE_TYPE_CPU) &&
131         vkPhysicalDeviceType != VK_PHYSICAL_DEVICE_TYPE_CPU)
132     {
133         ANGLE_CL_RETURN_ERROR(CL_DEVICE_NOT_FOUND);
134     }
135     else if (deviceType.intersects(CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_DEFAULT))
136     {
137         switch (vkPhysicalDeviceType)
138         {
139             case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
140             case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
141             case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
142                 break;
143             default:
144                 ANGLE_CL_RETURN_ERROR(CL_DEVICE_NOT_FOUND);
145         }
146     }
147     else
148     {
149         ANGLE_CL_RETURN_ERROR(CL_DEVICE_NOT_FOUND);
150     }
151 
152     cl::DevicePtrs devices;
153     for (const auto &platformDevice : mPlatform.getDevices())
154     {
155         const auto &platformDeviceInfo = platformDevice->getInfo();
156         if (platformDeviceInfo.type.intersects(deviceType))
157         {
158             devices.push_back(platformDevice);
159         }
160     }
161 
162     *contextOut = CLContextImpl::Ptr(new (std::nothrow) CLContextVk(context, devices));
163     if (*contextOut == nullptr)
164     {
165         ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
166     }
167     return angle::Result::Continue;
168 }
169 
unloadCompiler()170 angle::Result CLPlatformVk::unloadCompiler()
171 {
172     return angle::Result::Continue;
173 }
174 
Initialize(CreateFuncs & createFuncs)175 void CLPlatformVk::Initialize(CreateFuncs &createFuncs)
176 {
177     createFuncs.emplace_back([](const cl::Platform &platform) -> CLPlatformImpl::Ptr {
178         CLPlatformVk::Ptr platformVk = CLPlatformVk::Ptr(new (std::nothrow) CLPlatformVk(platform));
179         if (platformVk == nullptr || IsError(platformVk->initBackendRenderer()))
180         {
181             return Ptr(nullptr);
182         }
183         return Ptr(std::move(platformVk));
184     });
185 }
186 
GetVersionString()187 const std::string &CLPlatformVk::GetVersionString()
188 {
189     static const angle::base::NoDestructor<const std::string> sVersion(
190         "OpenCL " + std::to_string(CL_VERSION_MAJOR(GetVersion())) + "." +
191         std::to_string(CL_VERSION_MINOR(GetVersion())) + " ANGLE " +
192         angle::GetANGLEVersionString());
193     return *sVersion;
194 }
195 
CLPlatformVk(const cl::Platform & platform)196 CLPlatformVk::CLPlatformVk(const cl::Platform &platform)
197     : CLPlatformImpl(platform), vk::Context(new vk::Renderer()), mBlobCache(1024 * 1024)
198 {}
199 
handleError(VkResult result,const char * file,const char * function,unsigned int line)200 void CLPlatformVk::handleError(VkResult result,
201                                const char *file,
202                                const char *function,
203                                unsigned int line)
204 {
205     ASSERT(result != VK_SUCCESS);
206 
207     std::stringstream errorStream;
208     errorStream << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
209                 << ", in " << file << ", " << function << ":" << line << ".";
210     std::string errorString = errorStream.str();
211 
212     if (result == VK_ERROR_DEVICE_LOST)
213     {
214         WARN() << errorString;
215         mRenderer->notifyDeviceLost();
216     }
217 }
218 
getWindowSystem()219 angle::NativeWindowSystem CLPlatformVk::getWindowSystem()
220 {
221 #if defined(ANGLE_ENABLE_VULKAN)
222 #    if defined(ANGLE_PLATFORM_LINUX)
223 #        if defined(ANGLE_USE_GBM)
224     return angle::NativeWindowSystem::Gbm;
225 #        elif defined(ANGLE_USE_X11)
226     return angle::NativeWindowSystem::X11;
227 #        elif defined(ANGLE_USE_WAYLAND)
228     return angle::NativeWindowSystem::Wayland;
229 #        else
230     handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__);
231     return angle::NativeWindowSystem::Other;
232 #        endif
233 #    elif defined(ANGLE_PLATFORM_ANDROID)
234     return angle::NativeWindowSystem::Other;
235 #    else
236     handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__);
237     return angle::NativeWindowSystem::Other;
238 #    endif
239 #elif
240     UNREACHABLE();
241 #endif
242 }
243 
getWSIExtension()244 const char *CLPlatformVk::getWSIExtension()
245 {
246 #if defined(ANGLE_ENABLE_VULKAN)
247 #    if defined(ANGLE_PLATFORM_LINUX)
248 #        if defined(ANGLE_USE_GBM)
249     return nullptr;
250 #        elif defined(ANGLE_USE_X11)
251     return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
252 #        elif defined(ANGLE_USE_WAYLAND)
253     return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
254 #        else
255     handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__);
256     return nullptr;
257 #        endif
258 #    elif defined(ANGLE_PLATFORM_ANDROID)
259     return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
260 #    else
261     handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__);
262     return nullptr;
263 #    endif
264 #elif
265     UNREACHABLE();
266 #endif
267 }
268 
269 // vk::GlobalOps
putBlob(const angle::BlobCacheKey & key,const angle::MemoryBuffer & value)270 void CLPlatformVk::putBlob(const angle::BlobCacheKey &key, const angle::MemoryBuffer &value)
271 {
272     std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
273     size_t valueSize = value.size();
274     mBlobCache.put(key, std::move(const_cast<angle::MemoryBuffer &>(value)), valueSize);
275 }
276 
getBlob(const angle::BlobCacheKey & key,angle::BlobCacheValue * valueOut)277 bool CLPlatformVk::getBlob(const angle::BlobCacheKey &key, angle::BlobCacheValue *valueOut)
278 {
279     std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
280     const angle::MemoryBuffer *entry;
281     bool result = mBlobCache.get(key, &entry);
282     if (result)
283     {
284         *valueOut = angle::BlobCacheValue(entry->data(), entry->size());
285     }
286     return result;
287 }
288 
postMultiThreadWorkerTask(const std::shared_ptr<angle::Closure> & task)289 std::shared_ptr<angle::WaitableEvent> CLPlatformVk::postMultiThreadWorkerTask(
290     const std::shared_ptr<angle::Closure> &task)
291 {
292     return mPlatform.getMultiThreadPool()->postWorkerTask(task);
293 }
294 
notifyDeviceLost()295 void CLPlatformVk::notifyDeviceLost()
296 {
297     return;
298 }
299 
300 }  // namespace rx
301