libvulkan: Only load driver functions for enabled extensions
Change-Id: I4105291bd42583a10420681b729f03ecd7a91724
(cherry picked from commit 1c77ae2acda376b791932beffcb931c378e8ee36)
diff --git a/vulkan/libvulkan/dispatch.tmpl b/vulkan/libvulkan/dispatch.tmpl
index 2770538..11ec697 100644
--- a/vulkan/libvulkan/dispatch.tmpl
+++ b/vulkan/libvulkan/dispatch.tmpl
@@ -319,19 +319,27 @@
¶
bool LoadDriverDispatchTable(VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc_addr,
+ const InstanceExtensionSet& extensions,
DriverDispatchTable& dispatch) {«
bool success = true;
// clang-format off
{{range $f := AllCommands $}}
{{if (Macro "IsInstanceDispatched" $f)}}
{{if not (Macro "IsLoaderFunction" $f)}}
- dispatch.{{Macro "BaseName" $f}} = §
- reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
- get_proc_addr(instance, "{{$f.Name}}"));
- if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
- ALOGE("missing driver proc: %s", "{{$f.Name}}");
- success = false;
+ {{$ext := GetAnnotation $f "extension"}}
+ {{if $ext}}
+ if (extensions[{{Macro "ExtensionConstant" $ext}}]) {
+ {{end}}
+ dispatch.{{Macro "BaseName" $f}} = §
+ reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
+ get_proc_addr(instance, "{{$f.Name}}"));
+ if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
+ ALOGE("missing driver proc: %s", "{{$f.Name}}");
+ success = false;
+ }
+ {{if $ext}}
}
+ {{end}}
{{end}}
{{end}}
{{end}}
@@ -407,6 +415,20 @@
{{/*
-------------------------------------------------------------------------------
+ Map an extension name to InstanceExtension or DeviceExtension enum value
+-------------------------------------------------------------------------------
+*/}}
+{{define "ExtensionConstant"}}
+ {{$name := index $.Arguments 0}}
+ {{ if (eq $name "VK_KHR_surface")}}kKHR_surface
+ {{else if (eq $name "VK_KHR_android_surface")}}kKHR_android_surface
+ {{else if (eq $name "VK_EXT_debug_report")}}kEXT_debug_report
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
Emits a function name without the "vk" prefix.
-------------------------------------------------------------------------------
*/}}
diff --git a/vulkan/libvulkan/dispatch_gen.cpp b/vulkan/libvulkan/dispatch_gen.cpp
index bf9b38f..ebdf0da 100644
--- a/vulkan/libvulkan/dispatch_gen.cpp
+++ b/vulkan/libvulkan/dispatch_gen.cpp
@@ -1198,6 +1198,7 @@
bool LoadDriverDispatchTable(VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc_addr,
+ const InstanceExtensionSet& extensions,
DriverDispatchTable& dispatch) {
bool success = true;
// clang-format off
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 2c1b182..f302307 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -265,4 +265,14 @@
: nullptr;
}
+InstanceExtension InstanceExtensionFromName(const char* name) {
+ if (strcmp(name, VK_KHR_SURFACE_EXTENSION_NAME) == 0)
+ return kKHR_surface;
+ if (strcmp(name, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0)
+ return kKHR_android_surface;
+ if (strcmp(name, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0)
+ return kEXT_debug_report;
+ return kInstanceExtensionCount;
+}
+
} // namespace vulkan
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index 48fc923..079352b 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -178,6 +178,8 @@
// Global Data and Initialization
hwvulkan_device_t* g_hwdevice = nullptr;
+InstanceExtensionSet g_driver_instance_extensions;
+
void LoadVulkanHAL() {
static const hwvulkan_module_t* module;
int result =
@@ -195,6 +197,41 @@
module = nullptr;
return;
}
+
+ VkResult vkresult;
+ uint32_t count;
+ if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
+ nullptr, &count, nullptr)) != VK_SUCCESS) {
+ ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
+ vkresult);
+ g_hwdevice->common.close(&g_hwdevice->common);
+ g_hwdevice = nullptr;
+ module = nullptr;
+ return;
+ }
+ VkExtensionProperties* extensions = static_cast<VkExtensionProperties*>(
+ alloca(count * sizeof(VkExtensionProperties)));
+ if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
+ nullptr, &count, extensions)) != VK_SUCCESS) {
+ ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
+ vkresult);
+ g_hwdevice->common.close(&g_hwdevice->common);
+ g_hwdevice = nullptr;
+ module = nullptr;
+ return;
+ }
+ ALOGV_IF(count > 0, "Driver-supported instance extensions:");
+ for (uint32_t i = 0; i < count; i++) {
+ ALOGV(" %s (v%u)", extensions[i].extensionName,
+ extensions[i].specVersion);
+ InstanceExtension id =
+ InstanceExtensionFromName(extensions[i].extensionName);
+ if (id != kInstanceExtensionCount)
+ g_driver_instance_extensions.set(id);
+ }
+ // Ignore driver attempts to support loader extensions
+ g_driver_instance_extensions.reset(kKHR_surface);
+ g_driver_instance_extensions.reset(kKHR_android_surface);
}
bool EnsureInitialized() {
@@ -244,6 +281,7 @@
struct {
VkInstance instance;
+ InstanceExtensionSet supported_extensions;
DriverDispatchTable dispatch;
uint32_t num_physical_devices;
} drv; // may eventually be an array
@@ -475,13 +513,27 @@
VkInstanceCreateInfo driver_create_info = *create_info;
driver_create_info.enabledLayerCount = 0;
driver_create_info.ppEnabledLayerNames = nullptr;
- // TODO(jessehall): We currently only enumerate the VK_KHR_surface and
- // VK_KHR_android_surface extensions, which we don't allow drivers to
- // support. As soon as we enumerate instance extensions supported by the
- // driver, we should instead filter the requested extension list here to
- // only the extensions supported by the driver.
+
+ InstanceExtensionSet enabled_extensions;
driver_create_info.enabledExtensionCount = 0;
driver_create_info.ppEnabledExtensionNames = nullptr;
+ size_t max_names = std::min(create_info->enabledExtensionCount,
+ g_driver_instance_extensions.count());
+ if (max_names > 0) {
+ const char** names =
+ static_cast<const char**>(alloca(max_names * sizeof(char*)));
+ for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
+ InstanceExtension id = InstanceExtensionFromName(
+ create_info->ppEnabledExtensionNames[i]);
+ if (id != kInstanceExtensionCount &&
+ g_driver_instance_extensions[id]) {
+ names[driver_create_info.enabledExtensionCount++] =
+ create_info->ppEnabledExtensionNames[i];
+ enabled_extensions.set(id);
+ }
+ }
+ driver_create_info.ppEnabledExtensionNames = names;
+ }
result = g_hwdevice->CreateInstance(&driver_create_info, instance.alloc,
&instance.drv.instance);
@@ -492,7 +544,7 @@
if (!LoadDriverDispatchTable(instance.drv.instance,
g_hwdevice->GetInstanceProcAddr,
- instance.drv.dispatch)) {
+ enabled_extensions, instance.drv.dispatch)) {
DestroyInstance_Bottom(instance.handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -834,19 +886,22 @@
if (layer_name) {
GetLayerExtensions(layer_name, &extensions, &num_extensions);
} else {
- static const VkExtensionProperties kInstanceExtensions[] = {
- {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
- {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
- VK_KHR_ANDROID_SURFACE_SPEC_VERSION}};
- extensions = kInstanceExtensions;
- num_extensions = sizeof(kInstanceExtensions) / sizeof(kInstanceExtensions[0]);
-
+ VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
+ alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
+ available[num_extensions++] = VkExtensionProperties{
+ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION};
+ available[num_extensions++] =
+ VkExtensionProperties{VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+ VK_KHR_ANDROID_SURFACE_SPEC_VERSION};
+ if (g_driver_instance_extensions[kEXT_debug_report]) {
+ available[num_extensions++] =
+ VkExtensionProperties{VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+ VK_EXT_DEBUG_REPORT_SPEC_VERSION};
+ }
// TODO(jessehall): We need to also enumerate extensions supported by
// implicitly-enabled layers. Currently we don't have that list of
// layers until instance creation.
-
- // TODO(jessehall): We need to also enumerate extensions supported by
- // any driver.
+ extensions = available;
}
if (!properties || *properties_count > num_extensions)
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index 6e32785..b7edb73 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -17,10 +17,19 @@
#ifndef LIBVULKAN_LOADER_H
#define LIBVULKAN_LOADER_H 1
+#include <bitset>
#include "dispatch_gen.h"
namespace vulkan {
+enum InstanceExtension {
+ kKHR_surface,
+ kKHR_android_surface,
+ kEXT_debug_report,
+ kInstanceExtensionCount
+};
+typedef std::bitset<kInstanceExtensionCount> InstanceExtensionSet;
+
inline const InstanceDispatchTable& GetDispatchTable(VkInstance instance) {
return **reinterpret_cast<InstanceDispatchTable**>(instance);
}
@@ -62,6 +71,7 @@
DeviceDispatchTable& dispatch);
bool LoadDriverDispatchTable(VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc_addr,
+ const InstanceExtensionSet& extensions,
DriverDispatchTable& dispatch);
// -----------------------------------------------------------------------------
@@ -146,6 +156,8 @@
uint32_t* count);
LayerRef GetLayerRef(const char* name);
+InstanceExtension InstanceExtensionFromName(const char* name);
+
} // namespace vulkan
#endif // LIBVULKAN_LOADER_H