xref: /aosp_15_r20/external/angle/src/common/vulkan/vulkan_icd.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // vulkan_icd.cpp : Helper for creating vulkan instances & selecting physical device.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "common/vulkan/vulkan_icd.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include <functional>
12*8975f5c5SAndroid Build Coastguard Worker #include <vector>
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker #include "common/Optional.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "common/bitset_utils.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker namespace
20*8975f5c5SAndroid Build Coastguard Worker {
ResetEnvironmentVar(const char * variableName,const Optional<std::string> & value)21*8975f5c5SAndroid Build Coastguard Worker void ResetEnvironmentVar(const char *variableName, const Optional<std::string> &value)
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker     if (!value.valid())
24*8975f5c5SAndroid Build Coastguard Worker     {
25*8975f5c5SAndroid Build Coastguard Worker         return;
26*8975f5c5SAndroid Build Coastguard Worker     }
27*8975f5c5SAndroid Build Coastguard Worker 
28*8975f5c5SAndroid Build Coastguard Worker     if (value.value().empty())
29*8975f5c5SAndroid Build Coastguard Worker     {
30*8975f5c5SAndroid Build Coastguard Worker         angle::UnsetEnvironmentVar(variableName);
31*8975f5c5SAndroid Build Coastguard Worker     }
32*8975f5c5SAndroid Build Coastguard Worker     else
33*8975f5c5SAndroid Build Coastguard Worker     {
34*8975f5c5SAndroid Build Coastguard Worker         angle::SetEnvironmentVar(variableName, value.value().c_str());
35*8975f5c5SAndroid Build Coastguard Worker     }
36*8975f5c5SAndroid Build Coastguard Worker }
37*8975f5c5SAndroid Build Coastguard Worker }  // namespace
38*8975f5c5SAndroid Build Coastguard Worker 
39*8975f5c5SAndroid Build Coastguard Worker namespace angle
40*8975f5c5SAndroid Build Coastguard Worker {
41*8975f5c5SAndroid Build Coastguard Worker 
42*8975f5c5SAndroid Build Coastguard Worker namespace vk
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker 
45*8975f5c5SAndroid Build Coastguard Worker namespace
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker 
WrapICDEnvironment(const char * icdEnvironment)48*8975f5c5SAndroid Build Coastguard Worker [[maybe_unused]] const std::string WrapICDEnvironment(const char *icdEnvironment)
49*8975f5c5SAndroid Build Coastguard Worker {
50*8975f5c5SAndroid Build Coastguard Worker     // The libraries are bundled into the module directory
51*8975f5c5SAndroid Build Coastguard Worker     std::string moduleDir = angle::GetModuleDirectory();
52*8975f5c5SAndroid Build Coastguard Worker     std::string ret       = ConcatenatePath(moduleDir, icdEnvironment);
53*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_MACOS)
54*8975f5c5SAndroid Build Coastguard Worker     std::string moduleDirWithLibraries = ConcatenatePath(moduleDir, "Libraries");
55*8975f5c5SAndroid Build Coastguard Worker     ret += ":" + ConcatenatePath(moduleDirWithLibraries, icdEnvironment);
56*8975f5c5SAndroid Build Coastguard Worker #endif
57*8975f5c5SAndroid Build Coastguard Worker     return ret;
58*8975f5c5SAndroid Build Coastguard Worker }
59*8975f5c5SAndroid Build Coastguard Worker 
60*8975f5c5SAndroid Build Coastguard Worker [[maybe_unused]] constexpr char kLoaderLayersPathEnv[] = "VK_LAYER_PATH";
61*8975f5c5SAndroid Build Coastguard Worker [[maybe_unused]] constexpr char kLayerEnablesEnv[]     = "VK_LAYER_ENABLES";
62*8975f5c5SAndroid Build Coastguard Worker 
63*8975f5c5SAndroid Build Coastguard Worker constexpr char kLoaderICDFilenamesEnv[]              = "VK_ICD_FILENAMES";
64*8975f5c5SAndroid Build Coastguard Worker constexpr char kANGLEPreferredDeviceEnv[]            = "ANGLE_PREFERRED_DEVICE";
65*8975f5c5SAndroid Build Coastguard Worker constexpr char kValidationLayersCustomSTypeListEnv[] = "VK_LAYER_CUSTOM_STYPE_LIST";
66*8975f5c5SAndroid Build Coastguard Worker constexpr char kNoDeviceSelect[]                     = "NODEVICE_SELECT";
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kMockVendorID = 0xba5eba11;
69*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kMockDeviceID = 0xf005ba11;
70*8975f5c5SAndroid Build Coastguard Worker constexpr char kMockDeviceName[] = "Vulkan Mock Device";
71*8975f5c5SAndroid Build Coastguard Worker 
72*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kGoogleVendorID      = 0x1AE0;
73*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kSwiftShaderDeviceID = 0xC0DE;
74*8975f5c5SAndroid Build Coastguard Worker constexpr char kSwiftShaderDeviceName[] = "SwiftShader Device";
75*8975f5c5SAndroid Build Coastguard Worker 
76*8975f5c5SAndroid Build Coastguard Worker using ICDFilterFunc = std::function<bool(const VkPhysicalDeviceProperties &)>;
77*8975f5c5SAndroid Build Coastguard Worker 
GetFilterForICD(vk::ICD preferredICD)78*8975f5c5SAndroid Build Coastguard Worker ICDFilterFunc GetFilterForICD(vk::ICD preferredICD)
79*8975f5c5SAndroid Build Coastguard Worker {
80*8975f5c5SAndroid Build Coastguard Worker     switch (preferredICD)
81*8975f5c5SAndroid Build Coastguard Worker     {
82*8975f5c5SAndroid Build Coastguard Worker         case vk::ICD::Mock:
83*8975f5c5SAndroid Build Coastguard Worker             return [](const VkPhysicalDeviceProperties &deviceProperties) {
84*8975f5c5SAndroid Build Coastguard Worker                 return ((deviceProperties.vendorID == kMockVendorID) &&
85*8975f5c5SAndroid Build Coastguard Worker                         (deviceProperties.deviceID == kMockDeviceID) &&
86*8975f5c5SAndroid Build Coastguard Worker                         (strcmp(deviceProperties.deviceName, kMockDeviceName) == 0));
87*8975f5c5SAndroid Build Coastguard Worker             };
88*8975f5c5SAndroid Build Coastguard Worker         case vk::ICD::SwiftShader:
89*8975f5c5SAndroid Build Coastguard Worker             return [](const VkPhysicalDeviceProperties &deviceProperties) {
90*8975f5c5SAndroid Build Coastguard Worker                 return ((deviceProperties.vendorID == kGoogleVendorID) &&
91*8975f5c5SAndroid Build Coastguard Worker                         (deviceProperties.deviceID == kSwiftShaderDeviceID) &&
92*8975f5c5SAndroid Build Coastguard Worker                         (strncmp(deviceProperties.deviceName, kSwiftShaderDeviceName,
93*8975f5c5SAndroid Build Coastguard Worker                                  strlen(kSwiftShaderDeviceName)) == 0));
94*8975f5c5SAndroid Build Coastguard Worker             };
95*8975f5c5SAndroid Build Coastguard Worker         default:
96*8975f5c5SAndroid Build Coastguard Worker             const std::string anglePreferredDevice =
97*8975f5c5SAndroid Build Coastguard Worker                 angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv);
98*8975f5c5SAndroid Build Coastguard Worker             return [anglePreferredDevice](const VkPhysicalDeviceProperties &deviceProperties) {
99*8975f5c5SAndroid Build Coastguard Worker                 return (anglePreferredDevice == deviceProperties.deviceName);
100*8975f5c5SAndroid Build Coastguard Worker             };
101*8975f5c5SAndroid Build Coastguard Worker     }
102*8975f5c5SAndroid Build Coastguard Worker }
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker }  // namespace
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker // If we're loading the vulkan layers, we could be running from any random directory.
107*8975f5c5SAndroid Build Coastguard Worker // Change to the executable directory so we can find the layers, then change back to the
108*8975f5c5SAndroid Build Coastguard Worker // previous directory to be safe we don't disrupt the application.
ScopedVkLoaderEnvironment(bool enableDebugLayers,vk::ICD icd)109*8975f5c5SAndroid Build Coastguard Worker ScopedVkLoaderEnvironment::ScopedVkLoaderEnvironment(bool enableDebugLayers, vk::ICD icd)
110*8975f5c5SAndroid Build Coastguard Worker     : mEnableDebugLayers(enableDebugLayers),
111*8975f5c5SAndroid Build Coastguard Worker       mICD(icd),
112*8975f5c5SAndroid Build Coastguard Worker       mChangedCWD(false),
113*8975f5c5SAndroid Build Coastguard Worker       mChangedICDEnv(false),
114*8975f5c5SAndroid Build Coastguard Worker       mChangedNoDeviceSelect(false)
115*8975f5c5SAndroid Build Coastguard Worker {
116*8975f5c5SAndroid Build Coastguard Worker // Changing CWD and setting environment variables makes no sense on Android,
117*8975f5c5SAndroid Build Coastguard Worker // since this code is a part of Java application there.
118*8975f5c5SAndroid Build Coastguard Worker // Android Vulkan loader doesn't need this either.
119*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_GGP)
120*8975f5c5SAndroid Build Coastguard Worker     if (icd == vk::ICD::Mock)
121*8975f5c5SAndroid Build Coastguard Worker     {
122*8975f5c5SAndroid Build Coastguard Worker         if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_MOCK_ICD_JSON).c_str()))
123*8975f5c5SAndroid Build Coastguard Worker         {
124*8975f5c5SAndroid Build Coastguard Worker             ERR() << "Error setting environment for Mock/Null Driver.";
125*8975f5c5SAndroid Build Coastguard Worker         }
126*8975f5c5SAndroid Build Coastguard Worker     }
127*8975f5c5SAndroid Build Coastguard Worker #    if defined(ANGLE_VK_SWIFTSHADER_ICD_JSON)
128*8975f5c5SAndroid Build Coastguard Worker     else if (icd == vk::ICD::SwiftShader)
129*8975f5c5SAndroid Build Coastguard Worker     {
130*8975f5c5SAndroid Build Coastguard Worker         if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_SWIFTSHADER_ICD_JSON).c_str()))
131*8975f5c5SAndroid Build Coastguard Worker         {
132*8975f5c5SAndroid Build Coastguard Worker             ERR() << "Error setting environment for SwiftShader.";
133*8975f5c5SAndroid Build Coastguard Worker         }
134*8975f5c5SAndroid Build Coastguard Worker     }
135*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_VK_SWIFTSHADER_ICD_JSON)
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker #    if !defined(ANGLE_PLATFORM_MACOS)
138*8975f5c5SAndroid Build Coastguard Worker     if (mEnableDebugLayers || icd != vk::ICD::Default)
139*8975f5c5SAndroid Build Coastguard Worker     {
140*8975f5c5SAndroid Build Coastguard Worker         const auto &cwd = angle::GetCWD();
141*8975f5c5SAndroid Build Coastguard Worker         if (!cwd.valid())
142*8975f5c5SAndroid Build Coastguard Worker         {
143*8975f5c5SAndroid Build Coastguard Worker             ERR() << "Error getting CWD for Vulkan layers init.";
144*8975f5c5SAndroid Build Coastguard Worker             mEnableDebugLayers = false;
145*8975f5c5SAndroid Build Coastguard Worker             mICD               = vk::ICD::Default;
146*8975f5c5SAndroid Build Coastguard Worker         }
147*8975f5c5SAndroid Build Coastguard Worker         else
148*8975f5c5SAndroid Build Coastguard Worker         {
149*8975f5c5SAndroid Build Coastguard Worker             mPreviousCWD          = cwd.value();
150*8975f5c5SAndroid Build Coastguard Worker             std::string moduleDir = angle::GetModuleDirectory();
151*8975f5c5SAndroid Build Coastguard Worker             mChangedCWD           = angle::SetCWD(moduleDir.c_str());
152*8975f5c5SAndroid Build Coastguard Worker             if (!mChangedCWD)
153*8975f5c5SAndroid Build Coastguard Worker             {
154*8975f5c5SAndroid Build Coastguard Worker                 ERR() << "Error setting CWD for Vulkan layers init.";
155*8975f5c5SAndroid Build Coastguard Worker                 mEnableDebugLayers = false;
156*8975f5c5SAndroid Build Coastguard Worker                 mICD               = vk::ICD::Default;
157*8975f5c5SAndroid Build Coastguard Worker             }
158*8975f5c5SAndroid Build Coastguard Worker         }
159*8975f5c5SAndroid Build Coastguard Worker     }
160*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_PLATFORM_MACOS)
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker     // Override environment variable to use the ANGLE layers.
163*8975f5c5SAndroid Build Coastguard Worker     if (mEnableDebugLayers)
164*8975f5c5SAndroid Build Coastguard Worker     {
165*8975f5c5SAndroid Build Coastguard Worker #    if defined(ANGLE_VK_LAYERS_DIR)
166*8975f5c5SAndroid Build Coastguard Worker         if (!angle::PrependPathToEnvironmentVar(kLoaderLayersPathEnv, ANGLE_VK_LAYERS_DIR))
167*8975f5c5SAndroid Build Coastguard Worker         {
168*8975f5c5SAndroid Build Coastguard Worker             ERR() << "Error setting environment for Vulkan layers init.";
169*8975f5c5SAndroid Build Coastguard Worker             mEnableDebugLayers = false;
170*8975f5c5SAndroid Build Coastguard Worker         }
171*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_VK_LAYERS_DIR)
172*8975f5c5SAndroid Build Coastguard Worker     }
173*8975f5c5SAndroid Build Coastguard Worker #endif  // !defined(ANGLE_PLATFORM_ANDROID)
174*8975f5c5SAndroid Build Coastguard Worker 
175*8975f5c5SAndroid Build Coastguard Worker     if (IsMSan() || IsASan())
176*8975f5c5SAndroid Build Coastguard Worker     {
177*8975f5c5SAndroid Build Coastguard Worker         // device select layer cause memory sanitizer false positive, so disable
178*8975f5c5SAndroid Build Coastguard Worker         // it for msan build.
179*8975f5c5SAndroid Build Coastguard Worker         mPreviousNoDeviceSelectEnv = angle::GetEnvironmentVar(kNoDeviceSelect);
180*8975f5c5SAndroid Build Coastguard Worker         angle::SetEnvironmentVar(kNoDeviceSelect, "1");
181*8975f5c5SAndroid Build Coastguard Worker         mChangedNoDeviceSelect = true;
182*8975f5c5SAndroid Build Coastguard Worker     }
183*8975f5c5SAndroid Build Coastguard Worker }
184*8975f5c5SAndroid Build Coastguard Worker 
~ScopedVkLoaderEnvironment()185*8975f5c5SAndroid Build Coastguard Worker ScopedVkLoaderEnvironment::~ScopedVkLoaderEnvironment()
186*8975f5c5SAndroid Build Coastguard Worker {
187*8975f5c5SAndroid Build Coastguard Worker     if (mChangedCWD)
188*8975f5c5SAndroid Build Coastguard Worker     {
189*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_ANDROID)
190*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mPreviousCWD.valid());
191*8975f5c5SAndroid Build Coastguard Worker         angle::SetCWD(mPreviousCWD.value().c_str());
192*8975f5c5SAndroid Build Coastguard Worker #endif  // !defined(ANGLE_PLATFORM_ANDROID)
193*8975f5c5SAndroid Build Coastguard Worker     }
194*8975f5c5SAndroid Build Coastguard Worker     if (mChangedICDEnv)
195*8975f5c5SAndroid Build Coastguard Worker     {
196*8975f5c5SAndroid Build Coastguard Worker         ResetEnvironmentVar(kLoaderICDFilenamesEnv, mPreviousICDEnv);
197*8975f5c5SAndroid Build Coastguard Worker     }
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker     ResetEnvironmentVar(kValidationLayersCustomSTypeListEnv, mPreviousCustomExtensionsEnv);
200*8975f5c5SAndroid Build Coastguard Worker 
201*8975f5c5SAndroid Build Coastguard Worker     if (mChangedNoDeviceSelect)
202*8975f5c5SAndroid Build Coastguard Worker     {
203*8975f5c5SAndroid Build Coastguard Worker         ResetEnvironmentVar(kNoDeviceSelect, mPreviousNoDeviceSelectEnv);
204*8975f5c5SAndroid Build Coastguard Worker     }
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker 
setICDEnvironment(const char * icd)207*8975f5c5SAndroid Build Coastguard Worker bool ScopedVkLoaderEnvironment::setICDEnvironment(const char *icd)
208*8975f5c5SAndroid Build Coastguard Worker {
209*8975f5c5SAndroid Build Coastguard Worker     // Override environment variable to use built Mock ICD
210*8975f5c5SAndroid Build Coastguard Worker     // ANGLE_VK_ICD_JSON gets set to the built mock ICD in BUILD.gn
211*8975f5c5SAndroid Build Coastguard Worker     mPreviousICDEnv = angle::GetEnvironmentVar(kLoaderICDFilenamesEnv);
212*8975f5c5SAndroid Build Coastguard Worker     mChangedICDEnv  = angle::SetEnvironmentVar(kLoaderICDFilenamesEnv, icd);
213*8975f5c5SAndroid Build Coastguard Worker 
214*8975f5c5SAndroid Build Coastguard Worker     if (!mChangedICDEnv)
215*8975f5c5SAndroid Build Coastguard Worker     {
216*8975f5c5SAndroid Build Coastguard Worker         mICD = vk::ICD::Default;
217*8975f5c5SAndroid Build Coastguard Worker     }
218*8975f5c5SAndroid Build Coastguard Worker     return mChangedICDEnv;
219*8975f5c5SAndroid Build Coastguard Worker }
220*8975f5c5SAndroid Build Coastguard Worker 
ChoosePhysicalDevice(PFN_vkGetPhysicalDeviceProperties pGetPhysicalDeviceProperties,const std::vector<VkPhysicalDevice> & physicalDevices,vk::ICD preferredICD,uint32_t preferredVendorID,uint32_t preferredDeviceID,VkPhysicalDevice * physicalDeviceOut,VkPhysicalDeviceProperties * physicalDevicePropertiesOut)221*8975f5c5SAndroid Build Coastguard Worker void ChoosePhysicalDevice(PFN_vkGetPhysicalDeviceProperties pGetPhysicalDeviceProperties,
222*8975f5c5SAndroid Build Coastguard Worker                           const std::vector<VkPhysicalDevice> &physicalDevices,
223*8975f5c5SAndroid Build Coastguard Worker                           vk::ICD preferredICD,
224*8975f5c5SAndroid Build Coastguard Worker                           uint32_t preferredVendorID,
225*8975f5c5SAndroid Build Coastguard Worker                           uint32_t preferredDeviceID,
226*8975f5c5SAndroid Build Coastguard Worker                           VkPhysicalDevice *physicalDeviceOut,
227*8975f5c5SAndroid Build Coastguard Worker                           VkPhysicalDeviceProperties *physicalDevicePropertiesOut)
228*8975f5c5SAndroid Build Coastguard Worker {
229*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!physicalDevices.empty());
230*8975f5c5SAndroid Build Coastguard Worker 
231*8975f5c5SAndroid Build Coastguard Worker     ICDFilterFunc filter = GetFilterForICD(preferredICD);
232*8975f5c5SAndroid Build Coastguard Worker 
233*8975f5c5SAndroid Build Coastguard Worker     const bool shouldChooseByID = (preferredVendorID != 0 || preferredDeviceID != 0);
234*8975f5c5SAndroid Build Coastguard Worker 
235*8975f5c5SAndroid Build Coastguard Worker     for (const VkPhysicalDevice &physicalDevice : physicalDevices)
236*8975f5c5SAndroid Build Coastguard Worker     {
237*8975f5c5SAndroid Build Coastguard Worker         pGetPhysicalDeviceProperties(physicalDevice, physicalDevicePropertiesOut);
238*8975f5c5SAndroid Build Coastguard Worker 
239*8975f5c5SAndroid Build Coastguard Worker         if (physicalDevicePropertiesOut->apiVersion < kMinimumVulkanAPIVersion)
240*8975f5c5SAndroid Build Coastguard Worker         {
241*8975f5c5SAndroid Build Coastguard Worker             // Skip any devices that don't support our minimum API version. This
242*8975f5c5SAndroid Build Coastguard Worker             // takes precedence over all other considerations.
243*8975f5c5SAndroid Build Coastguard Worker             continue;
244*8975f5c5SAndroid Build Coastguard Worker         }
245*8975f5c5SAndroid Build Coastguard Worker 
246*8975f5c5SAndroid Build Coastguard Worker         if (filter(*physicalDevicePropertiesOut))
247*8975f5c5SAndroid Build Coastguard Worker         {
248*8975f5c5SAndroid Build Coastguard Worker             *physicalDeviceOut = physicalDevice;
249*8975f5c5SAndroid Build Coastguard Worker             return;
250*8975f5c5SAndroid Build Coastguard Worker         }
251*8975f5c5SAndroid Build Coastguard Worker 
252*8975f5c5SAndroid Build Coastguard Worker         if (shouldChooseByID)
253*8975f5c5SAndroid Build Coastguard Worker         {
254*8975f5c5SAndroid Build Coastguard Worker             // NOTE: If the system has multiple GPUs with the same vendor and
255*8975f5c5SAndroid Build Coastguard Worker             // device IDs, this will arbitrarily select one of them.
256*8975f5c5SAndroid Build Coastguard Worker             bool matchVendorID = true;
257*8975f5c5SAndroid Build Coastguard Worker             bool matchDeviceID = true;
258*8975f5c5SAndroid Build Coastguard Worker 
259*8975f5c5SAndroid Build Coastguard Worker             if (preferredVendorID != 0 &&
260*8975f5c5SAndroid Build Coastguard Worker                 preferredVendorID != physicalDevicePropertiesOut->vendorID)
261*8975f5c5SAndroid Build Coastguard Worker             {
262*8975f5c5SAndroid Build Coastguard Worker                 matchVendorID = false;
263*8975f5c5SAndroid Build Coastguard Worker             }
264*8975f5c5SAndroid Build Coastguard Worker 
265*8975f5c5SAndroid Build Coastguard Worker             if (preferredDeviceID != 0 &&
266*8975f5c5SAndroid Build Coastguard Worker                 preferredDeviceID != physicalDevicePropertiesOut->deviceID)
267*8975f5c5SAndroid Build Coastguard Worker             {
268*8975f5c5SAndroid Build Coastguard Worker                 matchDeviceID = false;
269*8975f5c5SAndroid Build Coastguard Worker             }
270*8975f5c5SAndroid Build Coastguard Worker 
271*8975f5c5SAndroid Build Coastguard Worker             if (matchVendorID && matchDeviceID)
272*8975f5c5SAndroid Build Coastguard Worker             {
273*8975f5c5SAndroid Build Coastguard Worker                 *physicalDeviceOut = physicalDevice;
274*8975f5c5SAndroid Build Coastguard Worker                 return;
275*8975f5c5SAndroid Build Coastguard Worker             }
276*8975f5c5SAndroid Build Coastguard Worker         }
277*8975f5c5SAndroid Build Coastguard Worker     }
278*8975f5c5SAndroid Build Coastguard Worker 
279*8975f5c5SAndroid Build Coastguard Worker     Optional<VkPhysicalDevice> integratedDevice;
280*8975f5c5SAndroid Build Coastguard Worker     VkPhysicalDeviceProperties integratedDeviceProperties;
281*8975f5c5SAndroid Build Coastguard Worker     for (const VkPhysicalDevice &physicalDevice : physicalDevices)
282*8975f5c5SAndroid Build Coastguard Worker     {
283*8975f5c5SAndroid Build Coastguard Worker         pGetPhysicalDeviceProperties(physicalDevice, physicalDevicePropertiesOut);
284*8975f5c5SAndroid Build Coastguard Worker 
285*8975f5c5SAndroid Build Coastguard Worker         if (physicalDevicePropertiesOut->apiVersion < kMinimumVulkanAPIVersion)
286*8975f5c5SAndroid Build Coastguard Worker         {
287*8975f5c5SAndroid Build Coastguard Worker             // Skip any devices that don't support our minimum API version. This
288*8975f5c5SAndroid Build Coastguard Worker             // takes precedence over all other considerations.
289*8975f5c5SAndroid Build Coastguard Worker             continue;
290*8975f5c5SAndroid Build Coastguard Worker         }
291*8975f5c5SAndroid Build Coastguard Worker 
292*8975f5c5SAndroid Build Coastguard Worker         // If discrete GPU exists, uses it by default.
293*8975f5c5SAndroid Build Coastguard Worker         if (physicalDevicePropertiesOut->deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
294*8975f5c5SAndroid Build Coastguard Worker         {
295*8975f5c5SAndroid Build Coastguard Worker             *physicalDeviceOut = physicalDevice;
296*8975f5c5SAndroid Build Coastguard Worker             return;
297*8975f5c5SAndroid Build Coastguard Worker         }
298*8975f5c5SAndroid Build Coastguard Worker         if (physicalDevicePropertiesOut->deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU &&
299*8975f5c5SAndroid Build Coastguard Worker             !integratedDevice.valid())
300*8975f5c5SAndroid Build Coastguard Worker         {
301*8975f5c5SAndroid Build Coastguard Worker             integratedDevice           = physicalDevice;
302*8975f5c5SAndroid Build Coastguard Worker             integratedDeviceProperties = *physicalDevicePropertiesOut;
303*8975f5c5SAndroid Build Coastguard Worker             continue;
304*8975f5c5SAndroid Build Coastguard Worker         }
305*8975f5c5SAndroid Build Coastguard Worker     }
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker     // If only integrated GPU exists, use it by default.
308*8975f5c5SAndroid Build Coastguard Worker     if (integratedDevice.valid())
309*8975f5c5SAndroid Build Coastguard Worker     {
310*8975f5c5SAndroid Build Coastguard Worker         *physicalDeviceOut           = integratedDevice.value();
311*8975f5c5SAndroid Build Coastguard Worker         *physicalDevicePropertiesOut = integratedDeviceProperties;
312*8975f5c5SAndroid Build Coastguard Worker         return;
313*8975f5c5SAndroid Build Coastguard Worker     }
314*8975f5c5SAndroid Build Coastguard Worker 
315*8975f5c5SAndroid Build Coastguard Worker     WARN() << "Preferred device ICD not found. Using default physicalDevice instead.";
316*8975f5c5SAndroid Build Coastguard Worker     // Fallback to the first device.
317*8975f5c5SAndroid Build Coastguard Worker     *physicalDeviceOut = physicalDevices[0];
318*8975f5c5SAndroid Build Coastguard Worker     pGetPhysicalDeviceProperties(*physicalDeviceOut, physicalDevicePropertiesOut);
319*8975f5c5SAndroid Build Coastguard Worker }
320*8975f5c5SAndroid Build Coastguard Worker 
321*8975f5c5SAndroid Build Coastguard Worker }  // namespace vk
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker }  // namespace angle
324