Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c0c07c4 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

libvulkan: enable promoted instance extensions for 1.0 icd instance

QueryPresentationProperties requires GetPhysicalDeviceProperties2KHR,
however, for 1.0 icd instance, GPDP2 extension needs to be enabled by
the loader since the loader advertises 1.1 instance support.

Bug: 160276146
Test: dEQP-VK.wsi.android.shared_presentable_image*
Change-Id: Id0195d4a115e78e1d82b719059de271cd29446e0
parent d4fd1225
Loading
Loading
Loading
Loading
+44 −13
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ class CreateInfoWrapper {
    };

    VkApplicationInfo application_info_;
    uint32_t sanitized_api_version_;

    ExtensionFilter extension_filter_;

@@ -329,6 +330,7 @@ CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
      loader_api_version_(VK_API_VERSION_1_1),
      physical_dev_(VK_NULL_HANDLE),
      instance_info_(create_info),
      sanitized_api_version_(loader_api_version_),
      extension_filter_() {}

CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -385,10 +387,6 @@ VkResult CreateInfoWrapper::SanitizeApiVersion() {
            hal_extensions_.set(i);
        }

        // If pApplicationInfo is NULL, apiVersion is assumed to be 1.0
        if (!instance_info_.pApplicationInfo)
            return VK_SUCCESS;

        uint32_t icd_api_version = VK_API_VERSION_1_0;
        PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version =
            reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
@@ -409,8 +407,13 @@ VkResult CreateInfoWrapper::SanitizeApiVersion() {
            return VK_SUCCESS;

        if (icd_api_version < loader_api_version_) {
            sanitized_api_version_ = icd_api_version;

            if (!instance_info_.pApplicationInfo)
                return VK_SUCCESS;

            application_info_ = *instance_info_.pApplicationInfo;
            application_info_.apiVersion = icd_api_version;
            application_info_.apiVersion = sanitized_api_version_;
            instance_info_.pApplicationInfo = &application_info_;
        }
    } else {
@@ -498,15 +501,33 @@ VkResult CreateInfoWrapper::SanitizeExtensions() {
                                     : dev_info_.ppEnabledExtensionNames;
    auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
                                     : dev_info_.enabledExtensionCount;
    if (!ext_count)
        return VK_SUCCESS;

    VkResult result = InitExtensionFilter();
    if (result != VK_SUCCESS)
        return result;

    if (is_instance_ && sanitized_api_version_ < loader_api_version_) {
        for (uint32_t i = 0; i < ext_count; i++) {
            // Upon api downgrade, skip the promoted instance extensions in the
            // first pass to avoid duplicate extensions.
            const std::optional<uint32_t> version =
                GetInstanceExtensionPromotedVersion(ext_names[i]);
            if (version && *version > sanitized_api_version_ &&
                *version <= loader_api_version_)
                continue;

            FilterExtension(ext_names[i]);
        }

        // Enable the required extensions to support core functionalities.
        const auto promoted_extensions = GetPromotedInstanceExtensions(
            sanitized_api_version_, loader_api_version_);
        for (const auto& promoted_extension : promoted_extensions)
            FilterExtension(promoted_extension);
    } else {
        for (uint32_t i = 0; i < ext_count; i++)
            FilterExtension(ext_names[i]);
    }

    // Enable device extensions that contain physical-device commands, so that
    // vkGetInstanceProcAddr will return those physical-device commands.
@@ -571,10 +592,20 @@ VkResult CreateInfoWrapper::InitExtensionFilter() {
    filter.ext_count = count;

    // allocate name array
    uint32_t enabled_ext_count = (is_instance_)
                                     ? instance_info_.enabledExtensionCount
                                     : dev_info_.enabledExtensionCount;
    if (is_instance_) {
        uint32_t enabled_ext_count = instance_info_.enabledExtensionCount;

        // It requires enabling additional promoted extensions to downgrade api,
        // so we reserve enough space here.
        if (sanitized_api_version_ < loader_api_version_) {
            enabled_ext_count += CountPromotedInstanceExtensions(
                sanitized_api_version_, loader_api_version_);
        }

        count = std::min(filter.ext_count, enabled_ext_count);
    } else {
        count = std::min(filter.ext_count, dev_info_.enabledExtensionCount);
    }
    filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
        allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
        VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+48 −0
Original line number Diff line number Diff line
@@ -577,5 +577,53 @@ bool InitDriverTable(VkDevice dev,
    return success;
}

const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = {
    // clang-format off
    std::make_pair("VK_KHR_device_group_creation", VK_API_VERSION_1_1),
    std::make_pair("VK_KHR_external_fence_capabilities", VK_API_VERSION_1_1),
    std::make_pair("VK_KHR_external_memory_capabilities", VK_API_VERSION_1_1),
    std::make_pair("VK_KHR_external_semaphore_capabilities", VK_API_VERSION_1_1),
    std::make_pair("VK_KHR_get_physical_device_properties2", VK_API_VERSION_1_1),
    // clang-format on
};

std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    auto iter =
        std::lower_bound(begin, end, name,
                         [](const std::pair<const char*, uint32_t>& e,
                            const char* n) { return strcmp(e.first, n) < 0; });
    return (iter < end && strcmp(iter->first, name) == 0)
               ? std::optional<uint32_t>(iter->second)
               : std::nullopt;
}

uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
                                         uint32_t end_version) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    uint32_t count = 0;

    for (auto iter = begin; iter != end; iter++)
        if (iter->second > begin_version && iter->second <= end_version)
            count++;

    return count;
}

std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
                                                       uint32_t end_version) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    std::vector<const char*> extensions;

    for (auto iter = begin; iter != end; iter++)
        if (iter->second > begin_version && iter->second <= end_version)
            extensions.emplace_back(iter->first);

    return extensions;
}

}  // namespace driver
}  // namespace vulkan
+8 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <vulkan/vulkan.h>

#include <bitset>
#include <optional>
#include <vector>

namespace vulkan {
namespace driver {
@@ -109,6 +111,12 @@ bool InitDriverTable(VkDevice dev,
                     PFN_vkGetDeviceProcAddr get_proc,
                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);

std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name);
uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
                                         uint32_t end_version);
std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
                                                       uint32_t end_version);

}  // namespace driver
}  // namespace vulkan

+56 −0
Original line number Diff line number Diff line
@@ -162,6 +162,8 @@ def gen_h():
#include <vulkan/vulkan.h>

#include <bitset>
#include <optional>
#include <vector>

namespace vulkan {
namespace driver {
@@ -229,6 +231,12 @@ bool InitDriverTable(VkDevice dev,
                     PFN_vkGetDeviceProcAddr get_proc,
                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);

std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name);
uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
                                         uint32_t end_version);
std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
                                                       uint32_t end_version);

}  // namespace driver
}  // namespace vulkan

@@ -539,6 +547,54 @@ bool InitDriverTable(VkDevice dev,
    return success;
}

const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = {
    // clang-format off\n""")

    for key, value in sorted(gencom.promoted_inst_ext_dict.items()):
      f.write(gencom.indent(1) + 'std::make_pair("' + key + '", ' + value + '),\n')

    f.write("""\
    // clang-format on
};

std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    auto iter =
        std::lower_bound(begin, end, name,
                         [](const std::pair<const char*, uint32_t>& e,
                            const char* n) { return strcmp(e.first, n) < 0; });
    return (iter < end && strcmp(iter->first, name) == 0)
               ? std::optional<uint32_t>(iter->second)
               : std::nullopt;
}

uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
                                         uint32_t end_version) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    uint32_t count = 0;

    for (auto iter = begin; iter != end; iter++)
        if (iter->second > begin_version && iter->second <= end_version)
            count++;

    return count;
}

std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
                                                       uint32_t end_version) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    std::vector<const char*> extensions;

    for (auto iter = begin; iter != end; iter++)
        if (iter->second > begin_version && iter->second <= end_version)
            extensions.emplace_back(iter->first);

    return extensions;
}

}  // namespace driver
}  // namespace vulkan\n""")

+17 −0
Original line number Diff line number Diff line
@@ -97,6 +97,9 @@ version_code_list = []
# Dict for mapping a function to the core Vulkan API version.
version_dict = {}

# Dict for mapping a promoted instance extension to the core Vulkan API version.
promoted_inst_ext_dict = {}


def indent(num):
  """Returns the requested indents.
@@ -183,6 +186,15 @@ def version_code(version):
  return version[11:]


def version_2_api_version(version):
  """Returns the api version from a version string.

  Args:
    version: Vulkan version string.
  """
  return 'VK_API' + version[2:]


def is_function_supported(cmd):
  """Returns true if a function is core or from a supportable extension.

@@ -327,6 +339,7 @@ def parse_vulkan_registry():
  return_type_dict
  version_code_list
  version_dict
  promoted_inst_ext_dict
  """
  registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
                          'external', 'vulkan-headers', 'registry', 'vk.xml')
@@ -379,6 +392,10 @@ def parse_vulkan_registry():
      apiversion = ''
      if extension.tag == 'extension':
        extname = extension.get('name')
        if (extension.get('type') == 'instance' and
            extension.get('promotedto') is not None):
          promoted_inst_ext_dict[extname] = \
              version_2_api_version(extension.get('promotedto'))
        for req in extension:
          if req.get('feature') is not None:
            apiversion = req.get('feature')