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