Skip to content

Commit f3a594a

Browse files
committed
Add support for querying extensions
This adds extensions as a queryable capability through the device interface for Vulkan. This also gates adding extensions that we had previously been using based on their availabiltiy. As a last bit, this does include one small line added in the Changes to enable MoltenVK on Apple. When targeting Apple platforms the VK_KHR_PORTABILITY is always enabled. That extension is always required on Apple platforms so we can hard code that one.
1 parent 5b2eba7 commit f3a594a

File tree

1 file changed

+63
-10
lines changed

1 file changed

+63
-10
lines changed

lib/API/VK/Device.cpp

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ class VKDevice : public offloadtest::Device {
163163
Capabilities Caps;
164164
using LayerVector = std::vector<VkLayerProperties>;
165165
LayerVector Layers;
166+
using ExtensionVector = std::vector<VkExtensionProperties>;
167+
ExtensionVector Extensions;
166168

167169
struct BufferRef {
168170
VkBuffer Buffer;
@@ -226,6 +228,20 @@ class VKDevice : public offloadtest::Device {
226228
return false;
227229
}
228230

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+
229245
void printExtra(llvm::raw_ostream &OS) override {
230246
OS << " Layers:\n";
231247
for (auto Layer : getLayers()) {
@@ -236,6 +252,12 @@ class VKDevice : public offloadtest::Device {
236252
Sz = strnlen(Layer.description, VK_MAX_DESCRIPTION_SIZE);
237253
OS << " LayerDesc: " << llvm::StringRef(Layer.description, Sz) << "\n";
238254
}
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+
}
239261
}
240262

241263
const VkPhysicalDeviceProperties &getProps() const { return Props; }
@@ -301,6 +323,19 @@ class VKDevice : public offloadtest::Device {
301323
vkEnumerateInstanceLayerProperties(&LayerCount, Layers.data());
302324
}
303325

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+
304339
public:
305340
llvm::Error createDevice(InvocationState &IS) {
306341

@@ -906,6 +941,19 @@ class VKContext {
906941
CreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
907942
CreateInfo.pApplicationInfo = &AppInfo;
908943

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+
909957
VkResult Res = vkCreateInstance(&CreateInfo, NULL, &Instance);
910958
if (Res == VK_ERROR_INCOMPATIBLE_DRIVER)
911959
return llvm::createStringError(std::errc::no_such_device,
@@ -927,21 +975,26 @@ class VKContext {
927975
{
928976
auto TmpDev = std::make_shared<VKDevice>(PhysicalDevicesTmp[0]);
929977
AppInfo.apiVersion = TmpDev->getProps().apiVersion;
930-
}
931-
vkDestroyInstance(Instance, NULL);
932-
Instance = VK_NULL_HANDLE;
933978

934-
// TODO: This is a bit hacky but matches what I did in DX.
935979
#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());
939983

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());
943987
#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;
944995

996+
// This second creation shouldn't ever fail, but it tries to create the
997+
// highest supported device version.
945998
Res = vkCreateInstance(&CreateInfo, NULL, &Instance);
946999
if (Res == VK_ERROR_INCOMPATIBLE_DRIVER)
9471000
return llvm::createStringError(std::errc::no_such_device,

0 commit comments

Comments
 (0)