1 // Copyright 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include <vulkan/vulkan.h> 17 18 #include <atomic> 19 #include <deque> 20 #include <memory> 21 #include <mutex> 22 #include <optional> 23 #include <unordered_set> 24 #include <vector> 25 26 #include "VkCommonOperations.h" 27 #include "VkQsriTimeline.h" 28 #include "aemu/base/AsyncResult.h" 29 #include "aemu/base/BumpPool.h" 30 #include "aemu/base/ThreadAnnotations.h" 31 #include "aemu/base/synchronization/ConditionVariable.h" 32 #include "aemu/base/synchronization/Lock.h" 33 #include "gfxstream/host/BackendCallbacks.h" 34 #include "goldfish_vk_private_defs.h" 35 36 namespace gfxstream { 37 namespace vk { 38 39 struct VulkanDispatch; 40 41 // This class provides methods to create and query information about Android 42 // native buffers in the context of creating Android swapchain images that have 43 // Android native buffer backing. 44 45 class AndroidNativeBufferInfo { 46 public: 47 static std::unique_ptr<AndroidNativeBufferInfo> create( 48 VkEmulation* emu, VulkanDispatch* vk, VkDevice device, android::base::BumpPool& allocator, 49 const VkImageCreateInfo* pCreateInfo, const VkNativeBufferANDROID* nativeBufferANDROID, 50 const VkAllocationCallbacks* pAllocator, const VkPhysicalDeviceMemoryProperties* memProps); 51 52 AndroidNativeBufferInfo(const AndroidNativeBufferInfo&) = delete; 53 AndroidNativeBufferInfo& operator=(const AndroidNativeBufferInfo&) = delete; 54 55 AndroidNativeBufferInfo(AndroidNativeBufferInfo&&) = delete; 56 AndroidNativeBufferInfo& operator=(AndroidNativeBufferInfo&&) = delete; 57 58 ~AndroidNativeBufferInfo(); 59 getImage()60 VkImage getImage() const { return mImage; } 61 isExternallyBacked()62 bool isExternallyBacked() const { return mExternallyBacked; } 63 isUsingNativeImage()64 bool isUsingNativeImage() const { return mUseVulkanNativeImage; } 65 getColorBufferHandle()66 uint32_t getColorBufferHandle() const { return mColorBufferHandle; } 67 68 VkResult on_vkAcquireImageANDROID(VkEmulation* emu, VulkanDispatch* vk, VkDevice device, VkQueue defaultQueue, 69 uint32_t defaultQueueFamilyIndex, 70 std::mutex* defaultQueueMutex, VkSemaphore semaphore, 71 VkFence fence); 72 73 VkResult on_vkQueueSignalReleaseImageANDROID(VkEmulation* emu, 74 VulkanDispatch* vk, uint32_t queueFamilyIndex, 75 VkQueue queue, std::mutex* queueMutex, 76 uint32_t waitSemaphoreCount, 77 const VkSemaphore* pWaitSemaphores, 78 int* pNativeFenceFd); 79 80 AsyncResult registerQsriCallback(VkImage image, VkQsriTimeline::Callback callback); 81 82 private: 83 AndroidNativeBufferInfo() = default; 84 85 VulkanDispatch* mDeviceDispatch = nullptr; 86 VkDevice mDevice = VK_NULL_HANDLE; 87 VkFormat mVkFormat; 88 VkExtent3D mExtent; 89 VkImageUsageFlags mUsage; 90 std::vector<uint32_t> mQueueFamilyIndices; 91 92 int mAhbFormat = 0; 93 int mStride = 0; 94 uint32_t mColorBufferHandle = 0; 95 bool mExternallyBacked = false; 96 bool mUseVulkanNativeImage = false; 97 98 // We will be using separate allocations for image versus staging memory, 99 // because not all host Vulkan drivers will support directly rendering to 100 // host visible memory in a layout that glTexSubImage2D can consume. 101 102 // If we are using external memory, these memories are imported 103 // to the current instance. 104 VkDeviceMemory mImageMemory = VK_NULL_HANDLE; 105 uint32_t mImageMemoryTypeIndex = -1; 106 107 VkDeviceMemory mStagingBufferMemory = VK_NULL_HANDLE; 108 VkBuffer mStagingBuffer = VK_NULL_HANDLE; 109 uint8_t* mMappedStagingPtr = nullptr; 110 111 // To be populated later as we go. 112 VkImage mImage = VK_NULL_HANDLE; 113 VkMemoryRequirements mImageMemoryRequirements; 114 115 // The queue over which we send the buffer/image copy commands depends on 116 // the queue over which vkQueueSignalReleaseImageANDROID happens. 117 // It is assumed that the VkImage object has been created by Android swapchain layer 118 // with all the relevant queue family indices for sharing set properly. 119 struct QueueState { 120 VkQueue queue = VK_NULL_HANDLE; 121 VkCommandPool pool = VK_NULL_HANDLE; 122 VkCommandBuffer cb = VK_NULL_HANDLE; 123 VkCommandBuffer cb2 = VK_NULL_HANDLE; 124 VkFence fence = VK_NULL_HANDLE; 125 std::mutex* queueMutex = nullptr; 126 uint32_t queueFamilyIndex = 0; 127 std::optional<CancelableFuture> latestUse; 128 void setup(VulkanDispatch* vk, VkDevice device, VkQueue queue, uint32_t queueFamilyIndex, 129 std::mutex* queueMutex); 130 void teardown(VulkanDispatch* vk, VkDevice device); 131 }; 132 // We keep one QueueState for each queue family index used by the guest 133 // in vkQueuePresentKHR. 134 std::vector<QueueState> mQueueStates; 135 136 // Did we ever sync the Vulkan image with a ColorBuffer? 137 // If so, set everSynced along with the queue family index 138 // used to do that. 139 // If the swapchain image was created with exclusive sharing 140 // mode (reflected in this struct's |sharingMode| field), 141 // this part doesn't really matter. 142 bool mEverSynced = false; 143 static constexpr uint32_t INVALID_QUEUE_FAMILY_INDEX = std::numeric_limits<uint32_t>::max(); 144 uint32_t mLastUsedQueueFamilyIndex = INVALID_QUEUE_FAMILY_INDEX; 145 146 // On first acquire, we might use a different queue family 147 // to initially set the semaphore/fence to be signaled. 148 // Track that here. 149 bool mEverAcquired = false; 150 QueueState mAcquireQueueState; 151 152 // State that is of interest when interacting with sync fds and SyncThread. 153 // Protected by this lock and condition variable. 154 class QsriWaitFencePool { 155 public: 156 QsriWaitFencePool(VulkanDispatch*, VkDevice); 157 ~QsriWaitFencePool(); 158 VkFence getFenceFromPool(); 159 void returnFence(VkFence fence); 160 161 private: 162 std::mutex mMutex; 163 164 VulkanDispatch* mVk; 165 VkDevice mDevice; 166 167 // A pool of vkFences for waiting (optimization so we don't keep recreating them every 168 // time). 169 std::vector<VkFence> mAvailableFences GUARDED_BY(mMutex); 170 std::unordered_set<VkFence> mUsedFences GUARDED_BY(mMutex); 171 }; 172 173 std::unique_ptr<QsriWaitFencePool> mQsriWaitFencePool; 174 std::unique_ptr<VkQsriTimeline> mQsriTimeline; 175 }; 176 177 void getGralloc0Usage(VkFormat format, VkImageUsageFlags imageUsage, int* usage_out); 178 void getGralloc1Usage(VkFormat format, VkImageUsageFlags imageUsage, 179 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, 180 uint64_t* consumerUsage_out, uint64_t* producerUsage_out); 181 182 } // namespace vk 183 } // namespace gfxstream 184