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

Commit 701cc4c4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[HWUI] Let Skia automatically enable extensions and features" into main

parents 8adbf55c d390aea6
Loading
Loading
Loading
Loading
+55 −105
Original line number Diff line number Diff line
@@ -43,21 +43,14 @@ namespace android {
namespace uirenderer {
namespace renderthread {

// Not all of these are strictly required, but are all enabled if present.
// Not all of these are strictly required, but are all enabled if present. Only
// extensions that hwui itself wants to use are added. The ones implicitly used by Skia
// are added by Skia itself via VulkanPreferredFeatures.
static std::array<std::string_view, 26> sEnableExtensions{
        VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
        VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
        VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
        VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
        VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
        VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
        VK_KHR_MAINTENANCE1_EXTENSION_NAME,
        VK_KHR_MAINTENANCE2_EXTENSION_NAME,
        VK_KHR_MAINTENANCE3_EXTENSION_NAME,
        VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
        VK_KHR_SURFACE_EXTENSION_NAME,
        VK_KHR_SWAPCHAIN_EXTENSION_NAME,
        VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME,
        VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
        VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
        VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
@@ -70,7 +63,6 @@ static std::array<std::string_view, 26> sEnableExtensions{
        VK_EXT_DEVICE_FAULT_EXTENSION_NAME,
        VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME,
        VK_ANDROID_FRAME_BOUNDARY_EXTENSION_NAME,
        VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME,
};

static bool shouldEnableExtension(const std::string_view& extension) {
@@ -82,23 +74,6 @@ static bool shouldEnableExtension(const std::string_view& extension) {
    return false;
}

static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) {
    // All Vulkan structs that could be part of the features chain will start with the
    // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
    // so we can get access to the pNext for the next struct.
    struct CommonVulkanHeader {
        VkStructureType sType;
        void* pNext;
    };

    void* pNext = features.pNext;
    while (pNext) {
        void* current = pNext;
        pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
        free(current);
    }
}

#define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F)
#define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
@@ -142,12 +117,12 @@ VulkanManager::~VulkanManager() {
    mInstanceExtensions.clear();
    mDeviceExtensionsOwner.clear();
    mDeviceExtensions.clear();
    free_features_extensions_structs(mPhysicalDeviceFeatures2);
    mPhysicalDeviceFeatures2 = {};
    mDeviceFaultFeatures = {};
    mGlobalPriorityQueryFeatures = {};
}

void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
                                VkPhysicalDeviceFeatures2& features) {
void VulkanManager::setupDevice() {
    VkResult err;

    constexpr VkApplicationInfo app_info = {
@@ -189,6 +164,12 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
        LOG_ALWAYS_FATAL_IF(!hasKHRSurfaceExtension || !hasKHRAndroidSurfaceExtension);
    }

    // Let Skia enable instance extensions.
    mVulkanFeatures.init(mAPIVersion);
    mVulkanFeatures.addToInstanceExtensions(mInstanceExtensionsOwner.data(),
                                            mInstanceExtensionsOwner.size(),
                                            mInstanceExtensions);

    const VkInstanceCreateInfo instance_create = {
            VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,  // sType
            nullptr,                                 // pNext
@@ -260,6 +241,10 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
    }
    LOG_ALWAYS_FATAL_IF(mGraphicsQueueIndex == queueCount);

    mPhysicalDeviceFeatures2 = {};
    mPhysicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
    void** tailPNext = &mPhysicalDeviceFeatures2.pNext;

    {
        uint32_t extensionCount = 0;
        err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
@@ -270,6 +255,7 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
                                                  mDeviceExtensionsOwner.data());
        LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
        bool hasKHRSwapchainExtension = false;
        bool hasGlobalPriority = mAPIVersion >= VK_API_VERSION_1_4;
        for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
            if (!shouldEnableExtension(extension.extensionName)) {
                ALOGV("Not enabling device extension %s", extension.extensionName);
@@ -280,9 +266,41 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
            if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
                hasKHRSwapchainExtension = true;
            }
            else if (!strcmp(extension.extensionName, VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) {
                mDeviceFaultFeatures = {};
                mDeviceFaultFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
                *tailPNext = &mDeviceFaultFeatures;
                tailPNext = &mDeviceFaultFeatures.pNext;
            }
            else if (!strcmp(extension.extensionName, VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME) ||
                     !strcmp(extension.extensionName,
                             VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME)) {
                hasGlobalPriority = true;
            }
        }
        LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);

        if (hasGlobalPriority) {
            mGlobalPriorityQueryFeatures = {};
            mGlobalPriorityQueryFeatures.sType =
                    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT;
            *tailPNext = &mGlobalPriorityQueryFeatures;
            tailPNext = &mGlobalPriorityQueryFeatures.pNext;
        }
    }

    // Let Skia add features to be queried.
    mVulkanFeatures.addFeaturesToQuery(mDeviceExtensionsOwner.data(),
                                       mDeviceExtensionsOwner.size(), mPhysicalDeviceFeatures2);

    // Query to get the physical device features
    mGetPhysicalDeviceFeatures2(mPhysicalDevice, &mPhysicalDeviceFeatures2);
    // Robust buffer access can reduce performance on some platforms. It is not needed by
    // HWUI.
    mPhysicalDeviceFeatures2.features.robustBufferAccess = VK_FALSE;

    // Let Skia enable extensions and features.
    mVulkanFeatures.addFeaturesToEnable(mDeviceExtensions, mPhysicalDeviceFeatures2);

    auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
        if (device != VK_NULL_HANDLE) {
@@ -291,81 +309,13 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
        return vkGetInstanceProcAddr(instance, proc_name);
    };

    grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
    mExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
                      mInstanceExtensions.data(), mDeviceExtensions.size(),
                      mDeviceExtensions.data());

    LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));

    memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2));
    features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
    features.pNext = nullptr;

    // Setup all extension feature structs we may want to use.
    void** tailPNext = &features.pNext;

    if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
        VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
        blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)malloc(
                sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
        LOG_ALWAYS_FATAL_IF(!blend);
        blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
        blend->pNext = nullptr;
        *tailPNext = blend;
        tailPNext = &blend->pNext;
    }

    VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
    ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)malloc(
            sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
    LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
    ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
    ycbcrFeature->pNext = nullptr;
    *tailPNext = ycbcrFeature;
    tailPNext = &ycbcrFeature->pNext;

    if (grExtensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) {
        VkPhysicalDeviceFaultFeaturesEXT* deviceFaultFeatures =
                new VkPhysicalDeviceFaultFeaturesEXT;
        deviceFaultFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
        deviceFaultFeatures->pNext = nullptr;
        *tailPNext = deviceFaultFeatures;
        tailPNext = &deviceFaultFeatures->pNext;
    }

    if (grExtensions.hasExtension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME, 1)) {
        VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT* formatFeatures =
                new VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT;
        formatFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT;
        formatFeatures->pNext = nullptr;
        *tailPNext = formatFeatures;
        tailPNext = &formatFeatures->pNext;
    }

    if (grExtensions.hasExtension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME, 1)) {
        VkPhysicalDevicePipelineCreationCacheControlFeatures* cacheControlFeatures =
                new VkPhysicalDevicePipelineCreationCacheControlFeatures;
        cacheControlFeatures->sType =
                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;
        cacheControlFeatures->pNext = nullptr;
        *tailPNext = cacheControlFeatures;
        tailPNext = &cacheControlFeatures->pNext;
    }

    VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT* globalPriorityQueryFeatures =
            new VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT;
    globalPriorityQueryFeatures->sType =
            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT;
    globalPriorityQueryFeatures->pNext = nullptr;
    globalPriorityQueryFeatures->globalPriorityQuery = false;
    *tailPNext = globalPriorityQueryFeatures;
    tailPNext = &globalPriorityQueryFeatures->pNext;
    LOG_ALWAYS_FATAL_IF(!mExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));


    // query to get the physical device features
    mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
    // this looks like it would slow things down,
    // and we can't depend on it on all platforms
    features.features.robustBufferAccess = VK_FALSE;

    float queuePriorities[kRequestedQueueCount] = {0.0};

@@ -374,7 +324,7 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
    VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;

    if (Properties::contextPriority != 0 &&
        grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
        mExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
        VkQueueGlobalPriorityEXT globalPriority;
        switch (Properties::contextPriority) {
            case EGL_CONTEXT_PRIORITY_LOW_IMG:
@@ -392,7 +342,7 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,

        // check if the requested priority is reported by the query
        bool attachGlobalPriority = false;
        if (globalPriorityQueryFeatures->globalPriorityQuery) {
        if (mGlobalPriorityQueryFeatures.globalPriorityQuery) {
            for (uint32_t i = 0; i < queuePriorityProps[mGraphicsQueueIndex].priorityCount; i++) {
                if (queuePriorityProps[mGraphicsQueueIndex].priorities[i] == globalPriority) {
                    attachGlobalPriority = true;
@@ -440,7 +390,7 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,

    const VkDeviceCreateInfo deviceInfo = {
            VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,  // sType
            &features,                             // pNext
            &mPhysicalDeviceFeatures2,             // pNext
            0,                                     // VkDeviceCreateFlags
            1,                                     // queueCreateInfoCount
            &queueInfo,                            // pQueueCreateInfos
@@ -484,7 +434,7 @@ void VulkanManager::initialize() {
        LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
        LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));

        this->setupDevice(mExtensions, mPhysicalDeviceFeatures2);
        this->setupDevice();

        mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
        mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 1, &mAHBUploadQueue);
+8 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <include/gpu/ganesh/GrContextOptions.h>
#include <utils/StrongPointer.h>
#include <vk/VulkanExtensions.h>
#include <vk/VulkanPreferredFeatures.h>
#include <vulkan/vulkan.h>

// VK_ANDROID_frame_boundary is a bespoke extension defined by AGI
@@ -120,9 +121,9 @@ private:
    explicit VulkanManager() {}
    ~VulkanManager();

    // Sets up the VkInstance and VkDevice objects. Also fills out the passed in
    // VkPhysicalDeviceFeatures struct.
    void setupDevice(skgpu::VulkanExtensions&, VkPhysicalDeviceFeatures2&);
    // Sets up the VkInstance and VkDevice objects. Fills out mPhysicalDeviceFeatures2 and
    // other feature structs.
    void setupDevice();

    // simple wrapper class that exists only to initialize a pointer to NULL
    template <typename FNPTR_TYPE>
@@ -189,12 +190,14 @@ private:
    VkQueue mAHBUploadQueue = VK_NULL_HANDLE;

    // Variables saved to populate VkFunctorInitParams.
    static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
    static const uint32_t mAPIVersion = VK_API_VERSION_1_1;
    std::vector<VkExtensionProperties> mInstanceExtensionsOwner;
    std::vector<const char*> mInstanceExtensions;
    std::vector<VkExtensionProperties> mDeviceExtensionsOwner;
    std::vector<const char*> mDeviceExtensions;
    VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
    VkPhysicalDeviceFaultFeaturesEXT mDeviceFaultFeatures{};
    VkPhysicalDeviceGlobalPriorityQueryFeatures mGlobalPriorityQueryFeatures{};

    enum class SwapBehavior {
        Discard,
@@ -202,6 +205,7 @@ private:
    };
    SwapBehavior mSwapBehavior = SwapBehavior::Discard;
    skgpu::VulkanExtensions mExtensions;
    skgpu::VulkanPreferredFeatures mVulkanFeatures;
    uint32_t mDriverVersion = 0;

    std::once_flag mInitFlag;