vulkan: Implement layer and extension enumeration
Change-Id: I485ebbe3e57da396d361f772793e1e89850c334c
(cherry picked from commit 4bee2c3f2fdff04f1eb437f24a7bcf841364d5b3)
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index 035a96a..4241757 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -19,11 +19,12 @@
LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
LOCAL_CFLAGS += -DLOG_TAG=\"vulkan\"
LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef
-LOCAL_CPPFLAGS := -std=c++1y \
+LOCAL_CPPFLAGS := -std=c++14 \
-Wno-c++98-compat-pedantic \
-Wno-exit-time-destructors \
-Wno-c99-extensions \
- -Wno-zero-length-array
+ -Wno-zero-length-array \
+ -Wno-global-constructors
LOCAL_C_INCLUDES := \
frameworks/native/vulkan/include \
@@ -31,6 +32,7 @@
LOCAL_SRC_FILES := \
dispatch_gen.cpp \
+ layers_extensions.cpp \
loader.cpp \
swapchain.cpp \
vulkan_loader_data.cpp
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
new file mode 100644
index 0000000..e56cdea
--- /dev/null
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+
+#include "loader.h"
+#include <alloca.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <mutex>
+#include <sys/prctl.h>
+#include <string>
+#include <string.h>
+#include <vector>
+#include <log/log.h>
+#include <vulkan/vulkan_loader_data.h>
+
+using namespace vulkan;
+
+namespace vulkan {
+struct Layer {
+ VkLayerProperties properties;
+ size_t library_idx;
+ std::vector<VkExtensionProperties> extensions;
+};
+} // namespace vulkan
+
+namespace {
+
+std::mutex g_library_mutex;
+struct LayerLibrary {
+ std::string path;
+ void* dlhandle;
+ size_t refcount;
+};
+std::vector<LayerLibrary> g_layer_libraries;
+std::vector<Layer> g_layers;
+
+void AddLayerLibrary(const std::string& path) {
+ ALOGV("examining layer library '%s'", path.c_str());
+
+ void* dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
+ if (!dlhandle) {
+ ALOGW("failed to load layer library '%s': %s", path.c_str(), dlerror());
+ return;
+ }
+
+ PFN_vkEnumerateInstanceLayerProperties enumerate_layer_properties =
+ reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
+ dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
+ if (!enumerate_layer_properties) {
+ ALOGW(
+ "failed to find vkEnumerateInstanceLayerProperties in library "
+ "'%s': %s",
+ path.c_str(), dlerror());
+ dlclose(dlhandle);
+ return;
+ }
+ PFN_vkEnumerateInstanceExtensionProperties enumerate_extension_properties =
+ reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
+ dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
+ if (!enumerate_extension_properties) {
+ ALOGW(
+ "failed to find vkEnumerateInstanceExtensionProperties in library "
+ "'%s': %s",
+ path.c_str(), dlerror());
+ dlclose(dlhandle);
+ return;
+ }
+
+ uint32_t layer_count;
+ VkResult result = enumerate_layer_properties(&layer_count, nullptr);
+ if (result != VK_SUCCESS) {
+ ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+ path.c_str(), result);
+ dlclose(dlhandle);
+ return;
+ }
+ VkLayerProperties* properties = static_cast<VkLayerProperties*>(
+ alloca(layer_count * sizeof(VkLayerProperties)));
+ result = enumerate_layer_properties(&layer_count, properties);
+ if (result != VK_SUCCESS) {
+ ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+ path.c_str(), result);
+ dlclose(dlhandle);
+ return;
+ }
+
+ size_t library_idx = g_layer_libraries.size();
+ g_layers.reserve(g_layers.size() + layer_count);
+ for (size_t i = 0; i < layer_count; i++) {
+ Layer layer;
+ layer.properties = properties[i];
+ layer.library_idx = library_idx;
+
+ uint32_t count;
+ result = enumerate_extension_properties(properties[i].layerName, &count,
+ nullptr);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+ "'%s': %d",
+ properties[i].layerName, path.c_str(), result);
+ g_layers.resize(g_layers.size() - (i + 1));
+ dlclose(dlhandle);
+ return;
+ }
+ layer.extensions.resize(count);
+ result = enumerate_extension_properties(properties[i].layerName, &count,
+ layer.extensions.data());
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+ "'%s': %d",
+ properties[i].layerName, path.c_str(), result);
+ g_layers.resize(g_layers.size() - (i + 1));
+ dlclose(dlhandle);
+ return;
+ }
+
+ g_layers.push_back(layer);
+ ALOGV("found layer '%s'", properties[i].layerName);
+ }
+
+ dlclose(dlhandle);
+
+ g_layer_libraries.push_back(LayerLibrary{path, nullptr, 0});
+}
+
+void DiscoverLayersInDirectory(const std::string& dir_path) {
+ ALOGV("looking for layers in '%s'", dir_path.c_str());
+
+ DIR* directory = opendir(dir_path.c_str());
+ if (!directory) {
+ int err = errno;
+ ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
+ dir_path.c_str(), strerror(err), err);
+ return;
+ }
+
+ std::string path;
+ path.reserve(dir_path.size() + 20);
+ path.append(dir_path);
+ path.append("/");
+
+ struct dirent* entry;
+ while ((entry = readdir(directory))) {
+ size_t libname_len = strlen(entry->d_name);
+ if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
+ strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
+ continue;
+ path.append(entry->d_name);
+ AddLayerLibrary(path);
+ path.resize(dir_path.size() + 1);
+ }
+
+ closedir(directory);
+}
+
+void* GetLayerGetProcAddr(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) {
+ const LayerLibrary& library = g_layer_libraries[layer.library_idx];
+ void* gpa;
+ size_t layer_name_len = std::max(2u, strlen(layer.properties.layerName));
+ char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
+ strcpy(name, layer.properties.layerName);
+ strcpy(name + layer_name_len, gpa_name);
+ if (!(gpa = dlsym(library.dlhandle, name))) {
+ strcpy(name, "vk");
+ strcpy(name + 2, gpa_name);
+ gpa = dlsym(library.dlhandle, name);
+ }
+ return gpa;
+}
+
+} // anonymous namespace
+
+namespace vulkan {
+
+void DiscoverLayers() {
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
+ DiscoverLayersInDirectory("/data/local/debug/vulkan");
+ if (!LoaderData::GetInstance().layer_path.empty())
+ DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
+}
+
+uint32_t EnumerateLayers(uint32_t count, VkLayerProperties* properties) {
+ uint32_t n = std::min(count, g_layers.size());
+ for (uint32_t i = 0; i < n; i++) {
+ properties[i] = g_layers[i].properties;
+ }
+ return g_layers.size();
+}
+
+void GetLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count) {
+ for (const auto& layer : g_layers) {
+ if (strcmp(name, layer.properties.layerName) != 0)
+ continue;
+ *properties = layer.extensions.data();
+ *count = layer.extensions.size();
+ }
+}
+
+LayerRef GetLayerRef(const char* name) {
+ for (uint32_t id = 0; id < g_layers.size(); id++) {
+ if (strcmp(name, g_layers[id].properties.layerName) != 0) {
+ LayerLibrary& library = g_layer_libraries[g_layers[id].library_idx];
+ std::lock_guard<std::mutex> lock(g_library_mutex);
+ if (library.refcount++ == 0) {
+ library.dlhandle =
+ dlopen(library.path.c_str(), RTLD_NOW | RTLD_LOCAL);
+ if (!library.dlhandle) {
+ ALOGE("failed to load layer library '%s': %s",
+ library.path.c_str(), dlerror());
+ library.refcount = 0;
+ return LayerRef(nullptr);
+ }
+ }
+ return LayerRef(&g_layers[id]);
+ }
+ }
+ return LayerRef(nullptr);
+}
+
+LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
+
+LayerRef::~LayerRef() {
+ if (layer_) {
+ LayerLibrary& library = g_layer_libraries[layer_->library_idx];
+ std::lock_guard<std::mutex> lock(g_library_mutex);
+ if (--library.refcount == 0) {
+ dlclose(library.dlhandle);
+ library.dlhandle = nullptr;
+ }
+ }
+}
+
+LayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {}
+
+PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
+ return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
+ GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
+ : nullptr;
+}
+
+PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
+ return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+ GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
+ : nullptr;
+}
+
+} // namespace vulkan
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);
}
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index e3a7f0f..1511c3a 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -117,6 +117,35 @@
VKAPI_ATTR VkResult QueuePresentKHR_Bottom(VkQueue queue, const VkPresentInfoKHR* present_info);
// clang-format on
+// -----------------------------------------------------------------------------
+// layers_extensions.cpp
+
+struct Layer;
+class LayerRef {
+ public:
+ LayerRef(Layer* layer);
+ LayerRef(LayerRef&& other);
+ ~LayerRef();
+ LayerRef(const LayerRef&) = delete;
+ LayerRef& operator=(const LayerRef&) = delete;
+
+ // provides bool-like behavior
+ operator const Layer*() const { return layer_; }
+
+ PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
+ PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
+
+ private:
+ Layer* layer_;
+};
+
+void DiscoverLayers();
+uint32_t EnumerateLayers(uint32_t count, VkLayerProperties* properties);
+void GetLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+LayerRef GetLayerRef(const char* name);
+
} // namespace vulkan
#endif // LIBVULKAN_LOADER_H