@@ -163,6 +163,8 @@ class VKDevice : public offloadtest::Device {
163
163
Capabilities Caps;
164
164
using LayerVector = std::vector<VkLayerProperties>;
165
165
LayerVector Layers;
166
+ using ExtensionVector = std::vector<VkExtensionProperties>;
167
+ ExtensionVector Extensions;
166
168
167
169
struct BufferRef {
168
170
VkBuffer Buffer;
@@ -226,6 +228,20 @@ class VKDevice : public offloadtest::Device {
226
228
return false ;
227
229
}
228
230
231
+ const ExtensionVector &getExtensions () {
232
+ if (Extensions.empty ())
233
+ queryExtensions ();
234
+ return Extensions;
235
+ }
236
+
237
+ bool isExtensionSupported (llvm::StringRef QueryName) {
238
+ for (const auto &Ext : getExtensions ()) {
239
+ if (Ext.extensionName == QueryName)
240
+ return true ;
241
+ }
242
+ return false ;
243
+ }
244
+
229
245
void printExtra (llvm::raw_ostream &OS) override {
230
246
OS << " Layers:\n " ;
231
247
for (auto Layer : getLayers ()) {
@@ -236,6 +252,12 @@ class VKDevice : public offloadtest::Device {
236
252
Sz = strnlen (Layer.description , VK_MAX_DESCRIPTION_SIZE);
237
253
OS << " LayerDesc: " << llvm::StringRef (Layer.description , Sz) << " \n " ;
238
254
}
255
+
256
+ OS << " Extensions:\n " ;
257
+ for (const auto &Ext : getExtensions ()) {
258
+ OS << " - ExtensionName: " << llvm::StringRef (Ext.extensionName ) << " \n " ;
259
+ OS << " SpecVersion: " << Ext.specVersion << " \n " ;
260
+ }
239
261
}
240
262
241
263
const VkPhysicalDeviceProperties &getProps () const { return Props; }
@@ -301,6 +323,19 @@ class VKDevice : public offloadtest::Device {
301
323
vkEnumerateInstanceLayerProperties (&LayerCount, Layers.data ());
302
324
}
303
325
326
+ void queryExtensions () {
327
+ assert (Extensions.empty () && " Should not be called twice!" );
328
+ uint32_t ExtCount;
329
+ vkEnumerateDeviceExtensionProperties (Device, nullptr , &ExtCount, nullptr );
330
+
331
+ if (ExtCount == 0 )
332
+ return ;
333
+
334
+ Extensions.insert (Extensions.begin (), ExtCount, VkExtensionProperties ());
335
+ vkEnumerateDeviceExtensionProperties (Device, nullptr , &ExtCount,
336
+ Extensions.data ());
337
+ }
338
+
304
339
public:
305
340
llvm::Error createDevice (InvocationState &IS) {
306
341
@@ -906,6 +941,19 @@ class VKContext {
906
941
CreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
907
942
CreateInfo.pApplicationInfo = &AppInfo;
908
943
944
+ llvm::SmallVector<const char *> Extensions;
945
+ llvm::SmallVector<const char *> Layers;
946
+ #if __APPLE__
947
+ // If we build Vulkan support for Apple platforms the VK_KHR_PORTABILITY
948
+ // extension is required, so we can just force this one on. If it fails, the
949
+ // whole device would fail anyways.
950
+ Extensions.push_back (VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
951
+ CreateInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
952
+ #endif
953
+
954
+ CreateInfo.ppEnabledExtensionNames = Extensions.data ();
955
+ CreateInfo.enabledExtensionCount = Extensions.size ();
956
+
909
957
VkResult Res = vkCreateInstance (&CreateInfo, NULL , &Instance);
910
958
if (Res == VK_ERROR_INCOMPATIBLE_DRIVER)
911
959
return llvm::createStringError (std::errc::no_such_device,
@@ -927,21 +975,26 @@ class VKContext {
927
975
{
928
976
auto TmpDev = std::make_shared<VKDevice>(PhysicalDevicesTmp[0 ]);
929
977
AppInfo.apiVersion = TmpDev->getProps ().apiVersion ;
930
- }
931
- vkDestroyInstance (Instance, NULL );
932
- Instance = VK_NULL_HANDLE;
933
978
934
- // TODO: This is a bit hacky but matches what I did in DX.
935
979
#ifndef NDEBUG
936
- const char * ValidationLayer = " VK_LAYER_KHRONOS_validation" ;
937
- CreateInfo. ppEnabledLayerNames = & ValidationLayer;
938
- CreateInfo. enabledLayerCount = 1 ;
980
+ const llvm::StringRef ValidationLayer = " VK_LAYER_KHRONOS_validation" ;
981
+ if (TmpDev-> isLayerSupported ( ValidationLayer))
982
+ Layers. push_back (ValidationLayer. data ()) ;
939
983
940
- const char * DebugUtilsExtensionName = " VK_EXT_debug_utils" ;
941
- CreateInfo. ppEnabledExtensionNames = & DebugUtilsExtensionName;
942
- CreateInfo. enabledExtensionCount = 1 ;
984
+ const llvm::StringRef DebugUtilsExtensionName = " VK_EXT_debug_utils" ;
985
+ if (TmpDev-> isExtensionSupported ( DebugUtilsExtensionName))
986
+ Extensions. push_back (DebugUtilsExtensionName. data ()) ;
943
987
#endif
988
+ CreateInfo.ppEnabledLayerNames = Layers.data ();
989
+ CreateInfo.enabledLayerCount = Layers.size ();
990
+ CreateInfo.ppEnabledExtensionNames = Extensions.data ();
991
+ CreateInfo.enabledExtensionCount = Extensions.size ();
992
+ }
993
+ vkDestroyInstance (Instance, NULL );
994
+ Instance = VK_NULL_HANDLE;
944
995
996
+ // This second creation shouldn't ever fail, but it tries to create the
997
+ // highest supported device version.
945
998
Res = vkCreateInstance (&CreateInfo, NULL , &Instance);
946
999
if (Res == VK_ERROR_INCOMPATIBLE_DRIVER)
947
1000
return llvm::createStringError (std::errc::no_such_device,
0 commit comments