summaryrefslogtreecommitdiff
path: root/vulkan/libvulkan/api.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vulkan/libvulkan/api.cpp')
-rw-r--r--vulkan/libvulkan/api.cpp146
1 files changed, 137 insertions, 9 deletions
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 6e08d23189..5b9affd03a 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -29,6 +29,8 @@
#include <algorithm>
#include <mutex>
#include <new>
+#include <string>
+#include <unordered_set>
#include <utility>
#include <android-base/strings.h>
@@ -144,7 +146,7 @@ class OverrideLayerNames {
}
void GetLayersFromSettings() {
- // These will only be available if conditions are met in GraphicsEnvironemnt
+ // These will only be available if conditions are met in GraphicsEnvironment
// gpu_debug_layers = layer1:layer2:layerN
const std::string layers = android::GraphicsEnv::getInstance().getDebugLayers();
if (!layers.empty()) {
@@ -669,6 +671,12 @@ VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) {
return VK_ERROR_LAYER_NOT_PRESENT;
}
+ if (!layer.ref.GetGetInstanceProcAddr()) {
+ ALOGW("Failed to locate vkGetInstanceProcAddr in layer %s", name);
+ layer.ref.~LayerRef();
+ return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+
ALOGI("Loaded layer %s", name);
return VK_SUCCESS;
@@ -1171,14 +1179,40 @@ bool EnsureInitialized() {
std::call_once(once_flag, []() {
if (driver::OpenHAL()) {
- DiscoverLayers();
initialized = true;
}
});
+ {
+ static pid_t pid = getpid() + 1;
+ static std::mutex layer_lock;
+ std::lock_guard<std::mutex> lock(layer_lock);
+ if (pid != getpid()) {
+ pid = getpid();
+ DiscoverLayers();
+ }
+ }
+
return initialized;
}
+template <typename Functor>
+void ForEachLayerFromSettings(Functor functor) {
+ const std::string layersSetting =
+ android::GraphicsEnv::getInstance().getDebugLayers();
+ if (!layersSetting.empty()) {
+ std::vector<std::string> layers =
+ android::base::Split(layersSetting, ":");
+ for (uint32_t i = 0; i < layers.size(); i++) {
+ const Layer* layer = FindLayer(layers[i].c_str());
+ if (!layer) {
+ continue;
+ }
+ functor(layer);
+ }
+ }
+}
+
} // anonymous namespace
VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
@@ -1265,9 +1299,56 @@ VkResult EnumerateInstanceExtensionProperties(
return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
}
- // TODO how about extensions from implicitly enabled layers?
- return vulkan::driver::EnumerateInstanceExtensionProperties(
- nullptr, pPropertyCount, pProperties);
+ // If the pLayerName is nullptr, we must advertise all instance extensions
+ // from all implicitly enabled layers and the driver implementation. If
+ // there are duplicates among layers and the driver implementation, always
+ // only preserve the top layer closest to the application regardless of the
+ // spec version.
+ std::vector<VkExtensionProperties> properties;
+ std::unordered_set<std::string> extensionNames;
+
+ // Expose extensions from implicitly enabled layers.
+ ForEachLayerFromSettings([&](const Layer* layer) {
+ uint32_t count = 0;
+ const VkExtensionProperties* props =
+ GetLayerInstanceExtensions(*layer, count);
+ if (count > 0) {
+ for (uint32_t i = 0; i < count; ++i) {
+ if (extensionNames.emplace(props[i].extensionName).second) {
+ properties.push_back(props[i]);
+ }
+ }
+ }
+ });
+
+ // TODO(b/143293104): Parse debug.vulkan.layers properties
+
+ // Expose extensions from driver implementation.
+ {
+ uint32_t count = 0;
+ VkResult result = vulkan::driver::EnumerateInstanceExtensionProperties(
+ nullptr, &count, nullptr);
+ if (result == VK_SUCCESS && count > 0) {
+ std::vector<VkExtensionProperties> props(count);
+ result = vulkan::driver::EnumerateInstanceExtensionProperties(
+ nullptr, &count, props.data());
+ for (auto prop : props) {
+ if (extensionNames.emplace(prop.extensionName).second) {
+ properties.push_back(prop);
+ }
+ }
+ }
+ }
+
+ uint32_t totalCount = properties.size();
+ if (!pProperties || *pPropertyCount > totalCount) {
+ *pPropertyCount = totalCount;
+ }
+ if (pProperties) {
+ std::copy(properties.data(), properties.data() + *pPropertyCount,
+ pProperties);
+ }
+ return *pPropertyCount < totalCount ? VK_INCOMPLETE : VK_SUCCESS;
}
VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
@@ -1319,10 +1400,57 @@ VkResult EnumerateDeviceExtensionProperties(
return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
}
- // TODO how about extensions from implicitly enabled layers?
- const InstanceData& data = GetData(physicalDevice);
- return data.dispatch.EnumerateDeviceExtensionProperties(
- physicalDevice, nullptr, pPropertyCount, pProperties);
+ // If the pLayerName is nullptr, we must advertise all device extensions
+ // from all implicitly enabled layers and the driver implementation. If
+ // there are duplicates among layers and the driver implementation, always
+ // only preserve the top layer closest to the application regardless of the
+ // spec version.
+ std::vector<VkExtensionProperties> properties;
+ std::unordered_set<std::string> extensionNames;
+
+ // Expose extensions from implicitly enabled layers.
+ ForEachLayerFromSettings([&](const Layer* layer) {
+ uint32_t count = 0;
+ const VkExtensionProperties* props =
+ GetLayerDeviceExtensions(*layer, count);
+ if (count > 0) {
+ for (uint32_t i = 0; i < count; ++i) {
+ if (extensionNames.emplace(props[i].extensionName).second) {
+ properties.push_back(props[i]);
+ }
+ }
+ }
+ });
+
+ // TODO(b/143293104): Parse debug.vulkan.layers properties
+
+ // Expose extensions from driver implementation.
+ {
+ const InstanceData& data = GetData(physicalDevice);
+ uint32_t count = 0;
+ VkResult result = data.dispatch.EnumerateDeviceExtensionProperties(
+ physicalDevice, nullptr, &count, nullptr);
+ if (result == VK_SUCCESS && count > 0) {
+ std::vector<VkExtensionProperties> props(count);
+ result = data.dispatch.EnumerateDeviceExtensionProperties(
+ physicalDevice, nullptr, &count, props.data());
+ for (auto prop : props) {
+ if (extensionNames.emplace(prop.extensionName).second) {
+ properties.push_back(prop);
+ }
+ }
+ }
+ }
+
+ uint32_t totalCount = properties.size();
+ if (!pProperties || *pPropertyCount > totalCount) {
+ *pPropertyCount = totalCount;
+ }
+ if (pProperties) {
+ std::copy(properties.data(), properties.data() + *pPropertyCount,
+ pProperties);
+ }
+ return *pPropertyCount < totalCount ? VK_INCOMPLETE : VK_SUCCESS;
}
VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {