Merge changes I97efd6c9,I6460f8f0,Ic67e4290,I16214514,Ieaa4e463, ... into nyc-dev
* changes:
vulkan: remove g_device_layers
vulkan: ignore device-only layers
vulkan: ignore layer libraries without instance layers
vulkan: add FindLayer helper
vulkan: constify LayerRef members
vulkan: make g_library_mutex per-LayerLibrary
vulkan: make LayerLibrary a class
vulkan: refactor GetLayerGetProcAddr
vulkan: refactor AddLayerLibrary
vulkan: refactor LayerRef::~LayerRef
vulkan: refactor GetLayerRef
vulkan: add a constructor for LayerLibrary
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 6b53a9a..4cf1c2a 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -43,75 +43,118 @@
// 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 {
namespace api {
struct Layer {
VkLayerProperties properties;
size_t library_idx;
- std::vector<VkExtensionProperties> extensions;
+
+ bool is_global;
+
+ std::vector<VkExtensionProperties> instance_extensions;
+ std::vector<VkExtensionProperties> device_extensions;
};
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_instance_layers;
-std::vector<Layer> g_device_layers;
+class LayerLibrary {
+ public:
+ LayerLibrary(const std::string& path)
+ : path_(path), dlhandle_(nullptr), refcount_(0) {}
-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;
+ LayerLibrary(LayerLibrary&& other)
+ : path_(std::move(other.path_)),
+ dlhandle_(other.dlhandle_),
+ refcount_(other.refcount_) {
+ other.dlhandle_ = nullptr;
+ other.refcount_ = 0;
}
+ LayerLibrary(const LayerLibrary&) = delete;
+ LayerLibrary& operator=(const LayerLibrary&) = delete;
+
+ // these are thread-safe
+ bool Open();
+ void Close();
+
+ bool EnumerateLayers(size_t library_idx,
+ std::vector<Layer>& instance_layers) const;
+
+ void* GetGPA(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) const;
+
+ private:
+ const std::string path_;
+
+ std::mutex mutex_;
+ void* dlhandle_;
+ size_t refcount_;
+};
+
+bool LayerLibrary::Open() {
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ if (refcount_++ == 0) {
+ dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+ ALOGV("Opening library %s", path_.c_str());
+ if (!dlhandle_) {
+ ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+ dlerror());
+ refcount_ = 0;
+ return false;
+ }
+ }
+ ALOGV("Refcount on activate is %zu", refcount_);
+ return true;
+}
+
+void LayerLibrary::Close() {
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ if (--refcount_ == 0) {
+ ALOGV("Closing library %s", path_.c_str());
+ dlclose(dlhandle_);
+ dlhandle_ = nullptr;
+ }
+ ALOGV("Refcount on destruction is %zu", refcount_);
+}
+
+bool LayerLibrary::EnumerateLayers(size_t library_idx,
+ std::vector<Layer>& instance_layers) const {
PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
- dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
+ dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
- dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
- 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;
+ dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
+ if (!enumerate_instance_layers || !enumerate_instance_extensions) {
+ ALOGV("layer library '%s' misses some instance enumeraion functions",
+ path_.c_str());
+ return false;
}
- VkResult result;
+ // device functions are optional
+ PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
+ reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
+ dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
+ PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
+ reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
+ dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
+
+ // get layer counts
uint32_t num_instance_layers = 0;
uint32_t num_device_layers = 0;
- if (enumerate_instance_layers) {
- result = enumerate_instance_layers(&num_instance_layers, nullptr);
+ VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
+ if (result != VK_SUCCESS || !num_instance_layers) {
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateInstanceLayerProperties failed for library '%s': "
"%d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
+ path_.c_str(), result);
}
+ return false;
}
if (enumerate_device_layers) {
result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -119,23 +162,19 @@
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateDeviceLayerProperties failed for library '%s': %d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
+ path_.c_str(), result);
+ return false;
}
}
+
+ // get layer properties
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;
- }
+ result = enumerate_instance_layers(&num_instance_layers, properties);
+ if (result != VK_SUCCESS) {
+ ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+ path_.c_str(), result);
+ return false;
}
if (num_device_layers > 0) {
result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -143,102 +182,121 @@
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateDeviceLayerProperties failed for library '%s': %d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
+ path_.c_str(), result);
+ return false;
}
}
- size_t library_idx = g_layer_libraries.size();
- 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);
+ // append layers to instance_layers
+ size_t prev_num_instance_layers = instance_layers.size();
+ instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
for (size_t i = 0; i < num_instance_layers; i++) {
const VkLayerProperties& props = properties[i];
Layer layer;
layer.properties = props;
layer.library_idx = library_idx;
+ layer.is_global = false;
- 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;
+ 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);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
+ }
+ layer.instance_extensions.resize(count);
+ result = enumerate_instance_extensions(
+ props.layerName, &count, layer.instance_extensions.data());
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+ "'%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
+ }
+
+ for (size_t j = 0; j < num_device_layers; j++) {
+ const auto& dev_props = properties[num_instance_layers + j];
+ if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
+ layer.is_global = true;
+ break;
}
}
- 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;
+ if (layer.is_global && enumerate_device_extensions) {
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;
+ "library '%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
}
- layer.extensions.resize(count);
- result =
- enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
- &count, layer.extensions.data());
+ layer.device_extensions.resize(count);
+ result = enumerate_device_extensions(
+ VK_NULL_HANDLE, props.layerName, &count,
+ layer.device_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;
+ "library '%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
}
}
- g_device_layers.push_back(layer);
- ALOGV(" added device layer '%s'", props.layerName);
+ instance_layers.push_back(layer);
+ ALOGV(" added %s layer '%s'",
+ (layer.is_global) ? "global" : "instance", props.layerName);
}
- dlclose(dlhandle);
+ return true;
+}
- g_layer_libraries.push_back(LayerLibrary{path, nullptr, 0});
+void* LayerLibrary::GetGPA(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) const {
+ void* gpa;
+ size_t layer_name_len =
+ std::max(size_t{2}, 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(dlhandle_, name))) {
+ strcpy(name, "vk");
+ strcpy(name + 2, gpa_name);
+ gpa = dlsym(dlhandle_, name);
+ }
+ return gpa;
+}
+
+std::vector<LayerLibrary> g_layer_libraries;
+std::vector<Layer> g_instance_layers;
+
+void AddLayerLibrary(const std::string& path) {
+ ALOGV("examining layer library '%s'", path.c_str());
+
+ LayerLibrary library(path);
+ if (!library.Open())
+ return;
+
+ if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
+ library.Close();
+ return;
+ }
+
+ library.Close();
+
+ g_layer_libraries.emplace_back(std::move(library));
}
void DiscoverLayersInDirectory(const std::string& dir_path) {
@@ -271,71 +329,25 @@
closedir(directory);
}
+const Layer* FindInstanceLayer(const char* name) {
+ auto layer =
+ std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
+ [=](const Layer& entry) {
+ return strcmp(entry.properties.layerName, name) == 0;
+ });
+ return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
+}
+
+const Layer* FindDeviceLayer(const char* name) {
+ const Layer* layer = FindInstanceLayer(name);
+ return (layer && layer->is_global) ? layer : nullptr;
+}
+
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(size_t{2}, 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;
-}
-
-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] = layers[i].properties;
- }
- return static_cast<uint32_t>(layers.size());
-}
-
-void GetLayerExtensions(const std::vector<Layer>& layers,
- const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count) {
- 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(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 =
- dlopen(library.path.c_str(), RTLD_NOW | RTLD_LOCAL);
- ALOGV("Opening library %s", library.path.c_str());
- if (!library.dlhandle) {
- ALOGE("failed to load layer library '%s': %s",
- library.path.c_str(), dlerror());
- library.refcount = 0;
- return LayerRef(nullptr);
- }
- }
- ALOGV("Refcount on activate is %zu", library.refcount);
- return LayerRef(&layers[id]);
- }
- }
- return LayerRef(nullptr);
+ return library.GetGPA(layer, gpa_name, gpa_name_len);
}
} // anonymous namespace
@@ -349,45 +361,84 @@
uint32_t EnumerateInstanceLayers(uint32_t count,
VkLayerProperties* properties) {
- return EnumerateLayers(g_instance_layers, count, properties);
+ uint32_t n =
+ std::min(count, static_cast<uint32_t>(g_instance_layers.size()));
+ for (uint32_t i = 0; i < n; i++)
+ properties[i] = g_instance_layers[i].properties;
+
+ return static_cast<uint32_t>(g_instance_layers.size());
}
uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
- return EnumerateLayers(g_device_layers, count, properties);
+ uint32_t n = 0;
+ for (const auto& layer : g_instance_layers) {
+ // ignore non-global layers
+ if (!layer.is_global)
+ continue;
+
+ if (n < count)
+ properties[n] = layer.properties;
+ n++;
+ }
+
+ return n;
}
void GetInstanceLayerExtensions(const char* name,
const VkExtensionProperties** properties,
uint32_t* count) {
- GetLayerExtensions(g_instance_layers, name, properties, count);
+ const Layer* layer = FindInstanceLayer(name);
+ if (layer) {
+ *properties = layer->instance_extensions.data();
+ *count = static_cast<uint32_t>(layer->instance_extensions.size());
+ } else {
+ *properties = nullptr;
+ *count = 0;
+ }
}
void GetDeviceLayerExtensions(const char* name,
const VkExtensionProperties** properties,
uint32_t* count) {
- GetLayerExtensions(g_device_layers, name, properties, count);
+ const Layer* layer = FindDeviceLayer(name);
+ if (layer) {
+ *properties = layer->device_extensions.data();
+ *count = static_cast<uint32_t>(layer->device_extensions.size());
+ } else {
+ *properties = nullptr;
+ *count = 0;
+ }
}
LayerRef GetInstanceLayerRef(const char* name) {
- return GetLayerRef(g_instance_layers, name);
+ const Layer* layer = FindInstanceLayer(name);
+ if (layer) {
+ LayerLibrary& library = g_layer_libraries[layer->library_idx];
+ if (!library.Open())
+ layer = nullptr;
+ }
+
+ return LayerRef(layer, true);
}
LayerRef GetDeviceLayerRef(const char* name) {
- return GetLayerRef(g_device_layers, name);
+ const Layer* layer = FindDeviceLayer(name);
+ if (layer) {
+ LayerLibrary& library = g_layer_libraries[layer->library_idx];
+ if (!library.Open())
+ layer = nullptr;
+ }
+
+ return LayerRef(layer, false);
}
-LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
+LayerRef::LayerRef(const Layer* layer, bool is_instance)
+ : layer_(layer), is_instance_(is_instance) {}
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) {
- ALOGV("Closing library %s", library.path.c_str());
- dlclose(library.dlhandle);
- library.dlhandle = nullptr;
- }
- ALOGV("Refcount on destruction is %zu", library.refcount);
+ library.Close();
}
}
@@ -395,11 +446,12 @@
return layer_->properties.layerName;
}
-uint32_t LayerRef::GetSpecVersion() {
+uint32_t LayerRef::GetSpecVersion() const {
return layer_->properties.specVersion;
}
-LayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
+LayerRef::LayerRef(LayerRef&& other)
+ : layer_(other.layer_), is_instance_(other.is_instance_) {
other.layer_ = nullptr;
}
@@ -416,10 +468,12 @@
}
bool LayerRef::SupportsExtension(const char* name) const {
- return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
+ const auto& extensions = (is_instance_) ? layer_->instance_extensions
+ : layer_->device_extensions;
+ return std::find_if(extensions.cbegin(), extensions.cend(),
[=](const VkExtensionProperties& ext) {
return strcmp(ext.extensionName, name) == 0;
- }) != layer_->extensions.cend();
+ }) != extensions.cend();
}
} // namespace api
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 7e7bfd3..e2eb32b 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -25,14 +25,14 @@
struct Layer;
class LayerRef {
public:
- LayerRef(Layer* layer);
+ LayerRef(const Layer* layer, bool is_instance);
LayerRef(LayerRef&& other);
~LayerRef();
LayerRef(const LayerRef&) = delete;
LayerRef& operator=(const LayerRef&) = delete;
const char* GetName() const;
- uint32_t GetSpecVersion();
+ uint32_t GetSpecVersion() const;
// provides bool-like behavior
operator const Layer*() const { return layer_; }
@@ -43,7 +43,8 @@
bool SupportsExtension(const char* name) const;
private:
- Layer* layer_;
+ const Layer* layer_;
+ bool is_instance_;
};
void DiscoverLayers();