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 <optional> 22 #include <unordered_set> 23 #include <vector> 24 25 #include "VkCommonOperations.h" 26 #include "VkQsriTimeline.h" 27 #include "aemu/base/BumpPool.h" 28 #include "aemu/base/synchronization/ConditionVariable.h" 29 #include "aemu/base/synchronization/Lock.h" 30 #include "gfxstream/host/BackendCallbacks.h" 31 #include "goldfish_vk_private_defs.h" 32 33 namespace gfxstream { 34 namespace vk { 35 36 struct AndroidNativeBufferInfo; 37 struct VulkanDispatch; 38 39 // This class provides methods to create and query information about Android 40 // native buffers in the context of creating Android swapchain images that have 41 // Android native buffer backing. 42 43 // This is to be refactored to move to external memory only once we get that 44 // working. 45 46 void teardownAndroidNativeBufferImage(VulkanDispatch* vk, AndroidNativeBufferInfo* anbInfo); 47 48 struct AndroidNativeBufferInfo { ~AndroidNativeBufferInfoAndroidNativeBufferInfo49 ~AndroidNativeBufferInfo() { 50 if (vk) { 51 teardownAndroidNativeBufferImage(vk, this); 52 } 53 } 54 55 VulkanDispatch* vk = nullptr; 56 VkDevice device = VK_NULL_HANDLE; 57 VkFormat vkFormat; 58 VkExtent3D extent; 59 VkImageUsageFlags usage; 60 std::vector<uint32_t> queueFamilyIndices; 61 62 int format; 63 int stride; 64 uint32_t colorBufferHandle; 65 bool externallyBacked = false; 66 bool useVulkanNativeImage = false; 67 68 // We will be using separate allocations for image versus staging memory, 69 // because not all host Vulkan drivers will support directly rendering to 70 // host visible memory in a layout that glTexSubImage2D can consume. 71 72 // If we are using external memory, these memories are imported 73 // to the current instance. 74 VkDeviceMemory imageMemory = VK_NULL_HANDLE; 75 VkDeviceMemory stagingMemory = VK_NULL_HANDLE; 76 77 VkBuffer stagingBuffer = VK_NULL_HANDLE; 78 79 uint32_t imageMemoryTypeIndex; 80 uint32_t stagingMemoryTypeIndex; 81 82 uint8_t* mappedStagingPtr = nullptr; 83 84 // To be populated later as we go. 85 VkImage image = VK_NULL_HANDLE; 86 VkMemoryRequirements memReqs; 87 88 // The queue over which we send the buffer/image copy commands depends on 89 // the queue over which vkQueueSignalReleaseImageANDROID happens. 90 // It is assumed that the VkImage object has been created by Android swapchain layer 91 // with all the relevant queue family indices for sharing set properly. 92 struct QueueState { 93 VkQueue queue = VK_NULL_HANDLE; 94 VkCommandPool pool = VK_NULL_HANDLE; 95 VkCommandBuffer cb = VK_NULL_HANDLE; 96 VkCommandBuffer cb2 = VK_NULL_HANDLE; 97 VkFence fence = VK_NULL_HANDLE; 98 android::base::Lock* lock = nullptr; 99 uint32_t queueFamilyIndex = 0; 100 std::optional<CancelableFuture> latestUse; 101 void setup(VulkanDispatch* vk, VkDevice device, VkQueue queue, uint32_t queueFamilyIndex, 102 android::base::Lock* queueLock); 103 void teardown(VulkanDispatch* vk, VkDevice device); 104 }; 105 // We keep one QueueState for each queue family index used by the guest 106 // in vkQueuePresentKHR. 107 std::vector<QueueState> queueStates; 108 109 // Did we ever sync the Vulkan image with a ColorBuffer? 110 // If so, set everSynced along with the queue family index 111 // used to do that. 112 // If the swapchain image was created with exclusive sharing 113 // mode (reflected in this struct's |sharingMode| field), 114 // this part doesn't really matter. 115 bool everSynced = false; 116 uint32_t lastUsedQueueFamilyIndex; 117 118 // On first acquire, we might use a different queue family 119 // to initially set the semaphore/fence to be signaled. 120 // Track that here. 121 bool everAcquired = false; 122 QueueState acquireQueueState; 123 124 // State that is of interest when interacting with sync fds and SyncThread. 125 // Protected by this lock and condition variable. 126 class QsriWaitFencePool { 127 public: 128 QsriWaitFencePool(VulkanDispatch*, VkDevice); 129 ~QsriWaitFencePool(); 130 VkFence getFenceFromPool(); 131 void returnFence(VkFence fence); 132 133 private: 134 android::base::Lock mLock; 135 136 VulkanDispatch* mVk; 137 VkDevice mDevice; 138 139 // A pool of vkFences for waiting (optimization so we don't keep recreating them every 140 // time). 141 std::vector<VkFence> mAvailableFences; 142 std::unordered_set<VkFence> mUsedFences; 143 }; 144 145 std::unique_ptr<QsriWaitFencePool> qsriWaitFencePool = nullptr; 146 std::unique_ptr<VkQsriTimeline> qsriTimeline = nullptr; 147 }; 148 149 VkResult prepareAndroidNativeBufferImage(VulkanDispatch* vk, VkDevice device, 150 android::base::BumpPool& allocator, 151 const VkImageCreateInfo* pCreateInfo, 152 const VkNativeBufferANDROID* nativeBufferANDROID, 153 const VkAllocationCallbacks* pAllocator, 154 const VkPhysicalDeviceMemoryProperties* memProps, 155 AndroidNativeBufferInfo* out); 156 157 void getGralloc0Usage(VkFormat format, VkImageUsageFlags imageUsage, int* usage_out); 158 void getGralloc1Usage(VkFormat format, VkImageUsageFlags imageUsage, 159 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, 160 uint64_t* consumerUsage_out, uint64_t* producerUsage_out); 161 162 VkResult setAndroidNativeImageSemaphoreSignaled(VulkanDispatch* vk, VkDevice device, 163 VkQueue defaultQueue, 164 uint32_t defaultQueueFamilyIndex, 165 android::base::Lock* defaultQueueLock, 166 VkSemaphore semaphore, VkFence fence, 167 AndroidNativeBufferInfo* anbInfo); 168 169 VkResult syncImageToColorBuffer(gfxstream::host::BackendCallbacks& callbacks, VulkanDispatch* vk, 170 uint32_t queueFamilyIndex, VkQueue queue, 171 android::base::Lock* queueLock, uint32_t waitSemaphoreCount, 172 const VkSemaphore* pWaitSemaphores, int* pNativeFenceFd, 173 AndroidNativeBufferInfo* anbInfo); 174 175 } // namespace vk 176 } // namespace gfxstream 177