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

Commit f52ad201 authored by Nolan Scobie's avatar Nolan Scobie
Browse files

Refactor SkiaVkRenderEngine's VulkanInterface and DestroySemaphoreInfo

... to be shareable (and more defensive).

VulkanInterface is mostly unmodified, other than being converted from a
struct to a class. Part of that entails adding getters for a few fields.

DestroySemaphoreInfo now handles its own destruction, and supports
owning N VkSemaphores (required for Graphite). It also now stores which
VulkanInterface it needs to be destroyed with, so that the callback path
no longer needs to reference a static VulkanInterface (one tiny step
towards b/300533018.)

Also incidentally fixed a bug where realtime priority status may have
been left uninitialized.

Bug: b/293371537
Test: manual testing + existing tests transitively exercise these classes
Change-Id: I3a7782d76c72b9ad61f3a1d6968c352a86a2af9f
parent 7eb8cb82
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,7 @@ filegroup {
        "skia/SkiaRenderEngine.cpp",
        "skia/SkiaRenderEngine.cpp",
        "skia/SkiaGLRenderEngine.cpp",
        "skia/SkiaGLRenderEngine.cpp",
        "skia/SkiaVkRenderEngine.cpp",
        "skia/SkiaVkRenderEngine.cpp",
        "skia/VulkanInterface.cpp",
        "skia/debug/CaptureTimer.cpp",
        "skia/debug/CaptureTimer.cpp",
        "skia/debug/CommonPool.cpp",
        "skia/debug/CommonPool.cpp",
        "skia/debug/SkiaCapture.cpp",
        "skia/debug/SkiaCapture.cpp",
+26 −641

File changed.

Preview size limit exceeded, changes collapsed.

+37 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#include <vk/GrVkBackendContext.h>
#include <vk/GrVkBackendContext.h>


#include "SkiaRenderEngine.h"
#include "SkiaRenderEngine.h"
#include "VulkanInterface.h"


namespace android {
namespace android {
namespace renderengine {
namespace renderengine {
@@ -32,6 +33,42 @@ public:


    int getContextPriority() override;
    int getContextPriority() override;


    class DestroySemaphoreInfo {
    public:
        DestroySemaphoreInfo() = delete;
        DestroySemaphoreInfo(const DestroySemaphoreInfo&) = delete;
        DestroySemaphoreInfo& operator=(const DestroySemaphoreInfo&) = delete;
        DestroySemaphoreInfo& operator=(DestroySemaphoreInfo&&) = delete;

        DestroySemaphoreInfo(VulkanInterface& vulkanInterface, std::vector<VkSemaphore> semaphores)
              : mVulkanInterface(vulkanInterface), mSemaphores(std::move(semaphores)) {}
        DestroySemaphoreInfo(VulkanInterface& vulkanInterface, VkSemaphore semaphore)
              : DestroySemaphoreInfo(vulkanInterface, std::vector<VkSemaphore>(1, semaphore)) {}

        void unref() {
            --mRefs;
            if (!mRefs) {
                for (VkSemaphore semaphore : mSemaphores) {
                    mVulkanInterface.destroySemaphore(semaphore);
                }
                delete this;
            }
        }

    private:
        ~DestroySemaphoreInfo() = default;

        VulkanInterface& mVulkanInterface;
        std::vector<VkSemaphore> mSemaphores;
        // We need to make sure we don't delete the VkSemaphore until it is done being used by both
        // Skia (including by the GPU) and inside SkiaVkRenderEngine. So we always start with two
        // refs, one owned by Skia and one owned by the SkiaVkRenderEngine. The refs are decremented
        // each time unref() is called on this object. Skia will call unref() once it is done with
        // the semaphore and the GPU has finished work on the semaphore. SkiaVkRenderEngine calls
        // unref() after sending the semaphore to Skia and exporting it if need be.
        int mRefs = 2;
    };

protected:
protected:
    // Implementations of abstract SkiaRenderEngine functions specific to
    // Implementations of abstract SkiaRenderEngine functions specific to
    // rendering backend
    // rendering backend
+582 −0

File added.

Preview size limit exceeded, changes collapsed.

+95 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <include/gpu/vk/GrVkBackendContext.h>
#include <include/gpu/vk/GrVkExtensions.h>

#include <vulkan/vulkan.h>

using namespace skgpu;

namespace android {
namespace renderengine {
namespace skia {

class VulkanInterface {
public:
    // Create an uninitialized interface. Initialize with `init`.
    VulkanInterface() = default;
    ~VulkanInterface() = default;
    VulkanInterface(const VulkanInterface&) = delete;
    VulkanInterface& operator=(const VulkanInterface&) = delete;
    VulkanInterface& operator=(VulkanInterface&&) = delete;

    void init(bool protectedContent = false);
    void teardown();

    // TODO: b/293371537 - Graphite variant (external/skia/include/gpu/vk/VulkanBackendContext.h)
    GrVkBackendContext getBackendContext();
    VkSemaphore createExportableSemaphore();
    VkSemaphore importSemaphoreFromSyncFd(int syncFd);
    int exportSemaphoreSyncFd(VkSemaphore semaphore);
    void destroySemaphore(VkSemaphore semaphore);

    bool isInitialized() const { return mInitialized; }
    bool isRealtimePriority() const { return mIsRealtimePriority; }
    const std::vector<std::string>& getInstanceExtensionNames() { return mInstanceExtensionNames; }
    const std::vector<std::string>& getDeviceExtensionNames() { return mDeviceExtensionNames; }

private:
    struct VulkanFuncs {
        PFN_vkCreateSemaphore vkCreateSemaphore = nullptr;
        PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr;
        PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR = nullptr;
        PFN_vkDestroySemaphore vkDestroySemaphore = nullptr;

        PFN_vkDeviceWaitIdle vkDeviceWaitIdle = nullptr;
        PFN_vkDestroyDevice vkDestroyDevice = nullptr;
        PFN_vkDestroyInstance vkDestroyInstance = nullptr;
    };

    static void onVkDeviceFault(void* callbackContext, const std::string& description,
                                const std::vector<VkDeviceFaultAddressInfoEXT>& addressInfos,
                                const std::vector<VkDeviceFaultVendorInfoEXT>& vendorInfos,
                                const std::vector<std::byte>& vendorBinaryData);

    bool mInitialized = false;
    VkInstance mInstance = VK_NULL_HANDLE;
    VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
    VkDevice mDevice = VK_NULL_HANDLE;
    VkQueue mQueue = VK_NULL_HANDLE;
    int mQueueIndex = 0;
    uint32_t mApiVersion = 0;
    GrVkExtensions mGrExtensions;
    VkPhysicalDeviceFeatures2* mPhysicalDeviceFeatures2 = nullptr;
    VkPhysicalDeviceSamplerYcbcrConversionFeatures* mSamplerYcbcrConversionFeatures = nullptr;
    VkPhysicalDeviceProtectedMemoryFeatures* mProtectedMemoryFeatures = nullptr;
    VkPhysicalDeviceFaultFeaturesEXT* mDeviceFaultFeatures = nullptr;
    GrVkGetProc mGrGetProc = nullptr;
    bool mIsProtected = false;
    bool mIsRealtimePriority = false;

    VulkanFuncs mFuncs;

    std::vector<std::string> mInstanceExtensionNames;
    std::vector<std::string> mDeviceExtensionNames;
};

} // namespace skia
} // namespace renderengine
} // namespace android