vulkan: Implement layer and extension enumeration
Change-Id: I485ebbe3e57da396d361f772793e1e89850c334c
(cherry picked from commit 4bee2c3f2fdff04f1eb437f24a7bcf841364d5b3)
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index f884e8b..a57e5da 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
// module header
#include "loader.h"
@@ -46,9 +46,6 @@
namespace {
-// Define Handle typedef to be void* as returned from dlopen.
-typedef void* SharedLibraryHandle;
-
// These definitions are taken from the LunarG Vulkan Loader. They are used to
// enforce compatability between the Loader and Layers.
typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
@@ -124,16 +121,6 @@
// ----------------------------------------------------------------------------
-struct LayerData {
- String path;
- SharedLibraryHandle handle;
- uint32_t ref_count;
-};
-
-typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
-
-// ----------------------------------------------------------------------------
-
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
size_t alignment,
@@ -188,33 +175,35 @@
};
// ----------------------------------------------------------------------------
+// Global Data and Initialization
-hwvulkan_device_t* g_hwdevice;
+hwvulkan_device_t* g_hwdevice = nullptr;
+void LoadVulkanHAL() {
+ static const hwvulkan_module_t* module;
+ int result =
+ hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+ if (result != 0) {
+ ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result), result);
+ return;
+ }
+ result = module->common.methods->open(
+ &module->common, HWVULKAN_DEVICE_0,
+ reinterpret_cast<hw_device_t**>(&g_hwdevice));
+ if (result != 0) {
+ ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
+ result);
+ module = nullptr;
+ return;
+ }
+}
+
bool EnsureInitialized() {
static std::once_flag once_flag;
- static const hwvulkan_module_t* module;
-
std::call_once(once_flag, []() {
- int result;
- result = hw_get_module("vulkan",
- reinterpret_cast<const hw_module_t**>(&module));
- if (result != 0) {
- ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
- result);
- return;
- }
- result = module->common.methods->open(
- &module->common, HWVULKAN_DEVICE_0,
- reinterpret_cast<hw_device_t**>(&g_hwdevice));
- if (result != 0) {
- ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
- result);
- module = nullptr;
- return;
- }
+ LoadVulkanHAL();
+ DiscoverLayers();
});
-
- return module != nullptr && g_hwdevice != nullptr;
+ return g_hwdevice != nullptr;
}
// -----------------------------------------------------------------------------
@@ -226,18 +215,16 @@
get_instance_proc_addr(nullptr),
alloc(alloc_callbacks),
num_physical_devices(0),
- layers(CallbackAllocator<std::pair<String, LayerData>>(alloc)),
- active_layers(CallbackAllocator<String>(alloc)),
+ active_layers(CallbackAllocator<LayerRef>(alloc)),
message(VK_NULL_HANDLE) {
memset(&dispatch, 0, sizeof(dispatch));
memset(physical_devices, 0, sizeof(physical_devices));
- pthread_mutex_init(&layer_lock, 0);
drv.instance = VK_NULL_HANDLE;
memset(&drv.dispatch, 0, sizeof(drv.dispatch));
drv.num_physical_devices = 0;
}
- ~Instance() { pthread_mutex_destroy(&layer_lock); }
+ ~Instance() {}
const InstanceDispatchTable* dispatch_ptr;
const VkInstance handle;
@@ -252,11 +239,7 @@
uint32_t num_physical_devices;
VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
- pthread_mutex_t layer_lock;
- // Map of layer names to layer data
- UnorderedMap<String, LayerData> layers;
- // Vector of layers active for this instance
- Vector<LayerMapIterator> active_layers;
+ Vector<LayerRef> active_layers;
VkDbgMsgCallback message;
struct {
@@ -269,14 +252,13 @@
struct Device {
Device(Instance* instance_)
: instance(instance_),
- active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
+ active_layers(CallbackAllocator<LayerRef>(instance->alloc)) {
memset(&dispatch, 0, sizeof(dispatch));
}
DeviceDispatchTable dispatch;
Instance* instance;
PFN_vkGetDeviceProcAddr get_device_proc_addr;
- // Vector of layers active for this device
- Vector<LayerMapIterator> active_layers;
+ Vector<LayerRef> active_layers;
};
template <typename THandle>
@@ -329,106 +311,16 @@
alloc->pfnFree(alloc->pUserData, device);
}
-void FindLayersInDirectory(Instance& instance, const String& dir_name) {
- DIR* directory = opendir(dir_name.c_str());
- if (!directory) {
- int err = errno;
- ALOGW_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
- dir_name.c_str(), strerror(err), err);
- return;
- }
-
- Vector<VkLayerProperties> properties(
- CallbackAllocator<VkLayerProperties>(instance.alloc));
- struct dirent* entry;
- while ((entry = readdir(directory))) {
- size_t length = strlen(entry->d_name);
- if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
- strncmp(entry->d_name + length - 3, ".so", 3) != 0)
- continue;
- // Open so
- SharedLibraryHandle layer_handle =
- dlopen((dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
- if (!layer_handle) {
- ALOGE("%s failed to load with error %s; Skipping", entry->d_name,
- dlerror());
- continue;
- }
-
- // Get Layers in so
- PFN_vkEnumerateInstanceLayerProperties get_layer_properties =
- reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
- dlsym(layer_handle, "vkEnumerateInstanceLayerProperties"));
- if (!get_layer_properties) {
- ALOGE(
- "%s failed to find vkEnumerateInstanceLayerProperties with "
- "error %s; Skipping",
- entry->d_name, dlerror());
- dlclose(layer_handle);
- continue;
- }
- uint32_t count;
- get_layer_properties(&count, nullptr);
-
- properties.resize(count);
- get_layer_properties(&count, &properties[0]);
-
- // Add Layers to potential list
- for (uint32_t i = 0; i < count; ++i) {
- String layer_name(properties[i].layerName,
- CallbackAllocator<char>(instance.alloc));
- LayerData layer_data = {dir_name + entry->d_name, 0, 0};
- instance.layers.insert(std::make_pair(layer_name, layer_data));
- ALOGV("Found layer %s", properties[i].layerName);
- }
- dlclose(layer_handle);
- }
-
- closedir(directory);
-}
-
template <class TObject>
-void ActivateLayer(TObject* object, Instance* instance, const String& name) {
- // If object has layer, do nothing
- auto element = instance->layers.find(name);
- if (element == instance->layers.end()) {
- return;
- }
+bool ActivateLayer(TObject* object, const char* name) {
+ LayerRef layer(GetLayerRef(name));
+ if (!layer)
+ return false;
if (std::find(object->active_layers.begin(), object->active_layers.end(),
- element) != object->active_layers.end()) {
- ALOGW("Layer %s already activated; skipping", name.c_str());
- return;
- }
- // If layer is not open, open it
- LayerData& layer_data = element->second;
- pthread_mutex_lock(&instance->layer_lock);
- if (layer_data.ref_count == 0) {
- SharedLibraryHandle layer_handle =
- dlopen(layer_data.path.c_str(), RTLD_NOW | RTLD_LOCAL);
- if (!layer_handle) {
- pthread_mutex_unlock(&instance->layer_lock);
- ALOGE("%s failed to load with error %s; Skipping",
- layer_data.path.c_str(), dlerror());
- return;
- }
- layer_data.handle = layer_handle;
- }
- layer_data.ref_count++;
- pthread_mutex_unlock(&instance->layer_lock);
- ALOGV("Activating layer %s", name.c_str());
- object->active_layers.push_back(element);
-}
-
-void DeactivateLayer(Instance& instance,
- Vector<LayerMapIterator>::iterator& element) {
- LayerMapIterator& layer_map_data = *element;
- LayerData& layer_data = layer_map_data->second;
- pthread_mutex_lock(&instance.layer_lock);
- layer_data.ref_count--;
- if (!layer_data.ref_count) {
- dlclose(layer_data.handle);
- }
- pthread_mutex_unlock(&instance.layer_lock);
+ layer) == object->active_layers.end())
+ object->active_layers.push_back(std::move(layer));
+ ALOGV("activated layer '%s'", name);
+ return true;
}
struct InstanceNamesPair {
@@ -478,7 +370,7 @@
size_t end, start = 0;
while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
layer_name = layer_prop_str.substr(start, end - start);
- ActivateLayer(object, instance, layer_name);
+ ActivateLayer(object, layer_name.c_str());
start = end + 1;
}
Vector<String> layer_names(CallbackAllocator<String>(instance->alloc));
@@ -487,23 +379,18 @@
property_list(SetLayerNamesFromProperty,
static_cast<void*>(&instance_names_pair));
for (auto layer_name_element : layer_names) {
- ActivateLayer(object, instance, layer_name_element);
+ ActivateLayer(object, layer_name_element.c_str());
}
}
// Load app layers
for (uint32_t i = 0; i < create_info->enabledLayerNameCount; ++i) {
- String layer_name(create_info->ppEnabledLayerNames[i],
- string_allocator);
- auto element = instance->layers.find(layer_name);
- if (element == instance->layers.end()) {
+ if (!ActivateLayer(object, create_info->ppEnabledLayerNames[i])) {
ALOGE("requested %s layer '%s' not present",
create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
? "instance"
: "device",
- layer_name.c_str());
+ create_info->ppEnabledLayerNames[i]);
return VK_ERROR_LAYER_NOT_PRESENT;
- } else {
- ActivateLayer(object, instance, layer_name);
}
}
return VK_SUCCESS;
@@ -736,22 +623,22 @@
VKAPI_ATTR
VkResult EnumerateDeviceExtensionProperties_Bottom(
- VkPhysicalDevice pdev,
- const char* layer_name,
+ VkPhysicalDevice /*pdev*/,
+ const char* /*layer_name*/,
uint32_t* properties_count,
- VkExtensionProperties* properties) {
- // TODO: what are we supposed to do with layer_name here?
- return GetDispatchParent(pdev)
- .drv.dispatch.EnumerateDeviceExtensionProperties(
- pdev, layer_name, properties_count, properties);
+ VkExtensionProperties* /*properties*/) {
+ // TODO(jessehall): Implement me...
+ *properties_count = 0;
+ return VK_SUCCESS;
}
VKAPI_ATTR
-VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice pdev,
+VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice /*pdev*/,
uint32_t* properties_count,
- VkLayerProperties* properties) {
- return GetDispatchParent(pdev).drv.dispatch.EnumerateDeviceLayerProperties(
- pdev, properties_count, properties);
+ VkLayerProperties* /*properties*/) {
+ // TODO(jessehall): Implement me...
+ *properties_count = 0;
+ return VK_SUCCESS;
}
VKAPI_ATTR
@@ -825,20 +712,11 @@
next_element->next_element = next_object;
next_object = static_cast<void*>(next_element);
- auto& name = device->active_layers[idx]->first;
- auto& handle = device->active_layers[idx]->second.handle;
- next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- dlsym(handle, (name + "GetDeviceProcAddr").c_str()));
+ next_get_proc_addr = device->active_layers[idx].GetGetDeviceProcAddr();
if (!next_get_proc_addr) {
+ next_object = next_element->next_element;
next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- dlsym(handle, "vkGetDeviceProcAddr"));
- if (!next_get_proc_addr) {
- ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
- name.c_str(), dlerror());
- next_object = next_element->next_element;
- next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- next_element->get_proc_addr);
- }
+ next_element->get_proc_addr);
}
}
@@ -882,10 +760,7 @@
vkGetInstanceProcAddr(vkinstance, "vkDbgDestroyMsgCallback"));
DebugDestroyMessageCallback(vkinstance, instance.message);
}
- for (auto it = instance.active_layers.begin();
- it != instance.active_layers.end(); ++it) {
- DeactivateLayer(instance, it);
- }
+ instance.active_layers.clear();
const VkAllocationCallbacks* alloc = instance.alloc;
instance.~Instance();
alloc->pfnFree(alloc->pUserData, &instance);
@@ -925,30 +800,44 @@
// through a dispatch table.
VkResult EnumerateInstanceExtensionProperties_Top(
- const char* /*layer_name*/,
- uint32_t* count,
- VkExtensionProperties* /*properties*/) {
+ const char* layer_name,
+ uint32_t* properties_count,
+ VkExtensionProperties* properties) {
if (!EnsureInitialized())
return VK_ERROR_INITIALIZATION_FAILED;
- // TODO: not yet implemented
- ALOGW("vkEnumerateInstanceExtensionProperties not implemented");
+ const VkExtensionProperties* extensions = nullptr;
+ uint32_t num_extensions = 0;
+ if (layer_name) {
+ GetLayerExtensions(layer_name, &extensions, &num_extensions);
+ } else {
+ static const VkExtensionProperties kInstanceExtensions[] =
+ {{VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_REVISION},
+ {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_REVISION}};
+ extensions = kInstanceExtensions;
+ num_extensions = sizeof(kInstanceExtensions) / sizeof(kInstanceExtensions[0]);
+ // 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.
+ }
- *count = 0;
- return VK_SUCCESS;
+ if (!properties || *properties_count > num_extensions)
+ *properties_count = num_extensions;
+ if (properties)
+ std::copy(extensions, extensions + *properties_count, properties);
+ return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
}
-VkResult EnumerateInstanceLayerProperties_Top(
- uint32_t* count,
- VkLayerProperties* /*properties*/) {
+VkResult EnumerateInstanceLayerProperties_Top(uint32_t* properties_count,
+ VkLayerProperties* properties) {
if (!EnsureInitialized())
return VK_ERROR_INITIALIZATION_FAILED;
- // TODO: not yet implemented
- ALOGW("vkEnumerateInstanceLayerProperties not implemented");
-
- *count = 0;
- return VK_SUCCESS;
+ uint32_t layer_count =
+ EnumerateLayers(properties ? *properties_count : 0, properties);
+ if (!properties || *properties_count > layer_count)
+ *properties_count = layer_count;
+ return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
}
VkResult CreateInstance_Top(const VkInstanceCreateInfo* create_info,
@@ -972,16 +861,6 @@
return VK_ERROR_OUT_OF_HOST_MEMORY;
Instance* instance = new (instance_mem) Instance(allocator);
- // Scan layers
- CallbackAllocator<char> string_allocator(instance->alloc);
- String dir_name("/data/local/debug/vulkan/", string_allocator);
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
- FindLayersInDirectory(*instance, dir_name);
- const std::string& path = LoaderData::GetInstance().layer_path;
- dir_name.assign(path.c_str(), path.size());
- dir_name.append("/");
- FindLayersInDirectory(*instance, dir_name);
-
result = ActivateAllLayers(create_info, instance, instance);
if (result != VK_SUCCESS) {
DestroyInstance_Bottom(instance->handle, allocator);
@@ -1005,21 +884,12 @@
next_element->next_element = next_object;
next_object = static_cast<void*>(next_element);
- auto& name = instance->active_layers[idx]->first;
- auto& handle = instance->active_layers[idx]->second.handle;
- next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
- dlsym(handle, (name + "GetInstanceProcAddr").c_str()));
+ next_get_proc_addr =
+ instance->active_layers[idx].GetGetInstanceProcAddr();
if (!next_get_proc_addr) {
+ next_object = next_element->next_element;
next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
- dlsym(handle, "vkGetInstanceProcAddr"));
- if (!next_get_proc_addr) {
- ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
- name.c_str(), dlerror());
- next_object = next_element->next_element;
- next_get_proc_addr =
- reinterpret_cast<PFN_vkGetInstanceProcAddr>(
- next_element->get_proc_addr);
- }
+ next_element->get_proc_addr);
}
}
instance->get_instance_proc_addr = next_get_proc_addr;
@@ -1167,12 +1037,6 @@
if (!vkdevice)
return;
Device& device = GetDispatchParent(vkdevice);
- // TODO(jessehall): This seems very wrong. We might close a layer library
- // right before we call DestroyDevice in it.
- for (auto it = device.active_layers.begin();
- it != device.active_layers.end(); ++it) {
- DeactivateLayer(*device.instance, it);
- }
device.dispatch.DestroyDevice(vkdevice, device.instance->alloc);
DestroyDevice(&device);
}