libvulkan: Enumerate device layers
Change-Id: I7623eab3d8bb958470437998ba603ac1171d764c
(cherry picked from commit eab7505b0741dc5c062df889a7ca5db1a9e619e8)
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 90a3827..f2fbf31 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -28,6 +28,19 @@
using namespace vulkan;
+// TODO(jessehall): This file currently builds up global data structures as it
+// loads, and never cleans them up. This means we're doing heap allocations
+// without going through an app-provided allocator, but worse, we'll leak those
+// allocations if the loader is unloaded.
+//
+// We should allocate "enough" BSS space, and suballocate from there. Will
+// probably want to intern strings, etc., and will need some custom/manual data
+// structures.
+
+// TODO(jessehall): Currently we have separate lists for instance and device
+// layers. Most layers are both; we should use one entry for each layer name,
+// with a mask saying what kind(s) it is.
+
namespace vulkan {
struct Layer {
VkLayerProperties properties;
@@ -45,7 +58,8 @@
size_t refcount;
};
std::vector<LayerLibrary> g_layer_libraries;
-std::vector<Layer> g_layers;
+std::vector<Layer> g_instance_layers;
+std::vector<Layer> g_device_layers;
void AddLayerLibrary(const std::string& path) {
ALOGV("examining layer library '%s'", path.c_str());
@@ -56,81 +70,163 @@
return;
}
- PFN_vkEnumerateInstanceLayerProperties enumerate_layer_properties =
+ PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
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 =
+ PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
- if (!enumerate_extension_properties) {
- ALOGW(
- "failed to find vkEnumerateInstanceExtensionProperties in library "
- "'%s': %s",
- path.c_str(), dlerror());
+ PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
+ reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
+ dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
+ PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
+ reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
+ dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
+ if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
+ (enumerate_device_layers && enumerate_device_extensions))) {
+ ALOGV(
+ "layer library '%s' has neither instance nor device enumeraion "
+ "functions",
+ path.c_str());
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;
+ VkResult result;
+ uint32_t num_instance_layers = 0;
+ uint32_t num_device_layers = 0;
+ if (enumerate_instance_layers) {
+ result = enumerate_instance_layers(&num_instance_layers, 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;
+ if (enumerate_device_layers) {
+ result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
+ nullptr);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
+ path.c_str(), result);
+ dlclose(dlhandle);
+ return;
+ }
+ }
+ VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
+ (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
+ if (num_instance_layers > 0) {
+ result = enumerate_instance_layers(&num_instance_layers, properties);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceLayerProperties failed for library '%s': "
+ "%d",
+ path.c_str(), result);
+ dlclose(dlhandle);
+ return;
+ }
+ }
+ if (num_device_layers > 0) {
+ result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
+ properties + num_instance_layers);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateDeviceLayerProperties 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++) {
+ size_t prev_num_instance_layers = g_instance_layers.size();
+ size_t prev_num_device_layers = g_device_layers.size();
+ g_instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
+ g_device_layers.reserve(prev_num_device_layers + num_device_layers);
+ for (size_t i = 0; i < num_instance_layers; i++) {
+ const VkLayerProperties& props = properties[i];
+
Layer layer;
- layer.properties = properties[i];
+ layer.properties = props;
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;
+ if (enumerate_instance_extensions) {
+ uint32_t count = 0;
+ result =
+ enumerate_instance_extensions(props.layerName, &count, nullptr);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for "
+ "library "
+ "'%s': %d",
+ props.layerName, path.c_str(), result);
+ g_instance_layers.resize(prev_num_instance_layers);
+ dlclose(dlhandle);
+ return;
+ }
+ layer.extensions.resize(count);
+ result = enumerate_instance_extensions(props.layerName, &count,
+ layer.extensions.data());
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for "
+ "library "
+ "'%s': %d",
+ props.layerName, path.c_str(), result);
+ g_instance_layers.resize(prev_num_instance_layers);
+ dlclose(dlhandle);
+ return;
+ }
}
- g_layers.push_back(layer);
- ALOGV("found layer '%s'", properties[i].layerName);
+ g_instance_layers.push_back(layer);
+ ALOGV("added instance layer '%s'", props.layerName);
+ }
+ for (size_t i = 0; i < num_device_layers; i++) {
+ const VkLayerProperties& props = properties[num_instance_layers + i];
+
+ Layer layer;
+ layer.properties = props;
+ layer.library_idx = library_idx;
+
+ if (enumerate_device_extensions) {
+ uint32_t count;
+ result = enumerate_device_extensions(
+ VK_NULL_HANDLE, props.layerName, &count, nullptr);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateDeviceExtensionProperties(%s) failed for "
+ "library "
+ "'%s': %d",
+ props.layerName, path.c_str(), result);
+ g_instance_layers.resize(prev_num_instance_layers);
+ g_device_layers.resize(prev_num_device_layers);
+ dlclose(dlhandle);
+ return;
+ }
+ layer.extensions.resize(count);
+ result =
+ enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
+ &count, layer.extensions.data());
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateDeviceExtensionProperties(%s) failed for "
+ "library "
+ "'%s': %d",
+ props.layerName, path.c_str(), result);
+ g_instance_layers.resize(prev_num_instance_layers);
+ g_device_layers.resize(prev_num_device_layers);
+ dlclose(dlhandle);
+ return;
+ }
+ }
+
+ g_device_layers.push_back(layer);
+ ALOGV("added device layer '%s'", props.layerName);
}
dlclose(dlhandle);
@@ -185,40 +281,37 @@
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, static_cast<uint32_t>(g_layers.size()));
+uint32_t EnumerateLayers(const std::vector<Layer>& layers,
+ uint32_t count,
+ VkLayerProperties* properties) {
+ uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
for (uint32_t i = 0; i < n; i++) {
- properties[i] = g_layers[i].properties;
+ properties[i] = layers[i].properties;
}
- return static_cast<uint32_t>(g_layers.size());
+ return static_cast<uint32_t>(layers.size());
}
-void GetLayerExtensions(const char* name,
+void GetLayerExtensions(const std::vector<Layer>& layers,
+ 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 = static_cast<uint32_t>(layer.extensions.size());
+ auto layer =
+ std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
+ return strcmp(entry.properties.layerName, name) == 0;
+ });
+ if (layer == layers.cend()) {
+ *properties = nullptr;
+ *count = 0;
+ } else {
+ *properties = layer->extensions.data();
+ *count = static_cast<uint32_t>(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];
+LayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
+ for (uint32_t id = 0; id < layers.size(); id++) {
+ if (strcmp(name, layers[id].properties.layerName) != 0) {
+ LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
std::lock_guard<std::mutex> lock(g_library_mutex);
if (library.refcount++ == 0) {
library.dlhandle =
@@ -230,12 +323,52 @@
return LayerRef(nullptr);
}
}
- return LayerRef(&g_layers[id]);
+ return LayerRef(&layers[id]);
}
}
return LayerRef(nullptr);
}
+} // 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 EnumerateInstanceLayers(uint32_t count,
+ VkLayerProperties* properties) {
+ return EnumerateLayers(g_instance_layers, count, properties);
+}
+
+uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
+ return EnumerateLayers(g_device_layers, count, properties);
+}
+
+void GetInstanceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count) {
+ GetLayerExtensions(g_instance_layers, name, properties, count);
+}
+
+void GetDeviceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count) {
+ GetLayerExtensions(g_device_layers, name, properties, count);
+}
+
+LayerRef GetInstanceLayerRef(const char* name) {
+ return GetLayerRef(g_instance_layers, name);
+}
+
+LayerRef GetDeviceLayerRef(const char* name) {
+ return GetLayerRef(g_device_layers, name);
+}
+
LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
LayerRef::~LayerRef() {
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index 618bd93..00eb9b1 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -344,8 +344,19 @@
}
template <class TObject>
+LayerRef GetLayerRef(const char* name);
+template <>
+LayerRef GetLayerRef<Instance>(const char* name) {
+ return GetInstanceLayerRef(name);
+}
+template <>
+LayerRef GetLayerRef<Device>(const char* name) {
+ return GetDeviceLayerRef(name);
+}
+
+template <class TObject>
bool ActivateLayer(TObject* object, const char* name) {
- LayerRef layer(GetLayerRef(name));
+ LayerRef layer(GetLayerRef<TObject>(name));
if (!layer)
return false;
if (std::find(object->active_layers.begin(), object->active_layers.end(),
@@ -687,10 +698,12 @@
VKAPI_ATTR
VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice /*pdev*/,
uint32_t* properties_count,
- VkLayerProperties* /*properties*/) {
- // TODO(jessehall): Implement me...
- *properties_count = 0;
- return VK_SUCCESS;
+ VkLayerProperties* properties) {
+ uint32_t layer_count =
+ EnumerateDeviceLayers(properties ? *properties_count : 0, properties);
+ if (!properties || *properties_count > layer_count)
+ *properties_count = layer_count;
+ return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
}
VKAPI_ATTR
@@ -874,7 +887,7 @@
const VkExtensionProperties* extensions = nullptr;
uint32_t num_extensions = 0;
if (layer_name) {
- GetLayerExtensions(layer_name, &extensions, &num_extensions);
+ GetInstanceLayerExtensions(layer_name, &extensions, &num_extensions);
} else {
VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
@@ -907,7 +920,7 @@
return VK_ERROR_INITIALIZATION_FAILED;
uint32_t layer_count =
- EnumerateLayers(properties ? *properties_count : 0, properties);
+ EnumerateInstanceLayers(properties ? *properties_count : 0, properties);
if (!properties || *properties_count > layer_count)
*properties_count = layer_count;
return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index df43f74..375396e 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -154,11 +154,16 @@
};
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);
+uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
+uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
+void GetInstanceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+void GetDeviceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+LayerRef GetInstanceLayerRef(const char* name);
+LayerRef GetDeviceLayerRef(const char* name);
InstanceExtension InstanceExtensionFromName(const char* name);
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index b73e987..71f989e 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -255,6 +255,27 @@
printf("%s%s (v%u)\n", prefix, e.extensionName, e.specVersion);
}
+void PrintLayers(
+ const std::vector<VkLayerProperties>& layers,
+ const std::vector<std::vector<VkExtensionProperties>> extensions,
+ const char* prefix) {
+ std::string ext_prefix(prefix);
+ ext_prefix.append(" ");
+ for (size_t i = 0; i < layers.size(); i++) {
+ printf(
+ "%s%s %u.%u.%u/%u\n"
+ "%s %s\n",
+ prefix, layers[i].layerName,
+ ExtractMajorVersion(layers[i].specVersion),
+ ExtractMinorVersion(layers[i].specVersion),
+ ExtractPatchVersion(layers[i].specVersion),
+ layers[i].implementationVersion, prefix, layers[i].description);
+ if (!extensions[i].empty())
+ printf("%s Extensions [%zu]:\n", prefix, extensions[i].size());
+ PrintExtensions(extensions[i], ext_prefix.c_str());
+ }
+}
+
void PrintGpuInfo(const GpuInfo& info) {
VkResult result;
std::ostringstream strbuf;
@@ -321,19 +342,7 @@
}
if (!info.layers.empty()) {
printf(" Layers [%zu]:\n", info.layers.size());
- for (size_t i = 0; i < info.layers.size(); i++) {
- const auto& layer = info.layers[i];
- printf(" - %s %u.%u.%u/%u \"%s\"\n", layer.layerName,
- ExtractMajorVersion(layer.specVersion),
- ExtractMinorVersion(layer.specVersion),
- ExtractPatchVersion(layer.specVersion),
- layer.implementationVersion, layer.description);
- if (!info.layer_extensions[i].empty()) {
- printf(" Extensions [%zu]:\n",
- info.layer_extensions.size());
- PrintExtensions(info.layer_extensions[i], " ");
- }
- }
+ PrintLayers(info.layers, info.layer_extensions, " ");
}
}
}
@@ -345,17 +354,7 @@
PrintExtensions(info.extensions, " ");
if (!info.layers.empty()) {
printf("Instance Layers [%zu]:\n", info.layers.size());
- for (size_t i = 0; i < info.layers.size(); i++) {
- const auto& layer = info.layers[i];
- printf(" %s %u.%u.%u/%u \"%s\"\n", layer.layerName,
- ExtractMajorVersion(layer.specVersion),
- ExtractMinorVersion(layer.specVersion),
- ExtractPatchVersion(layer.specVersion),
- layer.implementationVersion, layer.description);
- if (!info.layer_extensions[i].empty()) {
- PrintExtensions(info.layer_extensions[i], " ");
- }
- }
+ PrintLayers(info.layers, info.layer_extensions, " ");
}
printf("PhysicalDevices [%zu]:\n", info.gpus.size());