• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef VULKANMANAGER_H
18 #define VULKANMANAGER_H
19 
20 #include <functional>
21 #include <mutex>
22 
23 #include "vulkan/vulkan_core.h"
24 #if !defined(VK_USE_PLATFORM_ANDROID_KHR)
25 #define VK_USE_PLATFORM_ANDROID_KHR
26 #endif
27 #include <GrContextOptions.h>
28 #include <SkSurface.h>
29 #include <utils/StrongPointer.h>
30 #include <vk/GrVkBackendContext.h>
31 #include <vk/GrVkExtensions.h>
32 #include <vulkan/vulkan.h>
33 
34 // VK_ANDROID_frame_boundary is a bespoke extension defined by AGI
35 // (https://github.com/google/agi) to enable profiling of apps rendering via
36 // HWUI. This extension is not defined in Khronos, hence the need to declare it
37 // manually here. There's a superseding extension (VK_EXT_frame_boundary) being
38 // discussed in Khronos, but in the meantime we use the bespoke
39 // VK_ANDROID_frame_boundary. This is a device extension that is implemented by
40 // AGI's Vulkan capture layer, such that it is only supported by devices when
41 // AGI is doing a capture of the app.
42 //
43 // TODO(b/182165045): use the Khronos blessed VK_EXT_frame_boudary once it has
44 // landed in the spec.
45 typedef void(VKAPI_PTR* PFN_vkFrameBoundaryANDROID)(VkDevice device, VkSemaphore semaphore,
46                                                     VkImage image);
47 #define VK_ANDROID_FRAME_BOUNDARY_EXTENSION_NAME "VK_ANDROID_frame_boundary"
48 
49 #include "Frame.h"
50 #include "IRenderPipeline.h"
51 #include "VulkanSurface.h"
52 #include "private/hwui/DrawVkInfo.h"
53 
54 class GrVkExtensions;
55 
56 namespace android {
57 namespace uirenderer {
58 namespace renderthread {
59 
60 class RenderThread;
61 
62 // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
63 // which are re-used by CanvasContext. This class is created once and should be used by all vulkan
64 // windowing contexts. The VulkanManager must be initialized before use.
65 class VulkanManager final : public RefBase {
66 public:
67     static sp<VulkanManager> getInstance();
68 
69     // Sets up the vulkan context that is shared amonst all clients of the VulkanManager. This must
70     // be call once before use of the VulkanManager. Multiple calls after the first will simiply
71     // return.
72     void initialize();
73 
74     // Quick check to see if the VulkanManager has been initialized.
hasVkContext()75     bool hasVkContext() { return mDevice != VK_NULL_HANDLE; }
76 
77     // Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
78     VulkanSurface* createSurface(ANativeWindow* window,
79                                  ColorMode colorMode,
80                                  sk_sp<SkColorSpace> surfaceColorSpace,
81                                  SkColorType surfaceColorType,
82                                  GrDirectContext* grContext,
83                                  uint32_t extraBuffers);
84     void destroySurface(VulkanSurface* surface);
85 
86     Frame dequeueNextBuffer(VulkanSurface* surface);
87     // Finishes the frame and submits work to the GPU
88     // Returns the estimated start time for intiating GPU work, -1 otherwise.
89     nsecs_t finishFrame(SkSurface* surface);
90     void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect);
91 
92     // Inserts a wait on fence command into the Vulkan command buffer.
93     status_t fenceWait(int fence, GrDirectContext* grContext);
94 
95     // Creates a fence that is signaled when all the pending Vulkan commands are finished on the
96     // GPU.
97     status_t createReleaseFence(int* nativeFence, GrDirectContext* grContext);
98 
99     // Returned pointers are owned by VulkanManager.
100     // An instance of VkFunctorInitParams returned from getVkFunctorInitParams refers to
101     // the internal state of VulkanManager: VulkanManager must be alive to use the returned value.
102     VkFunctorInitParams getVkFunctorInitParams() const;
103 
104 
105     enum class ContextType {
106         kRenderThread,
107         kUploadThread
108     };
109 
110     // returns a Skia graphic context used to draw content on the specified thread
111     sk_sp<GrDirectContext> createContext(const GrContextOptions& options,
112                                          ContextType contextType = ContextType::kRenderThread);
113 
getDriverVersion()114     uint32_t getDriverVersion() const { return mDriverVersion; }
115 
116 private:
117     friend class VulkanSurface;
118 
VulkanManager()119     explicit VulkanManager() {}
120     ~VulkanManager();
121 
122     // Sets up the VkInstance and VkDevice objects. Also fills out the passed in
123     // VkPhysicalDeviceFeatures struct.
124     void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&);
125 
126     // simple wrapper class that exists only to initialize a pointer to NULL
127     template <typename FNPTR_TYPE>
128     class VkPtr {
129     public:
VkPtr()130         VkPtr() : fPtr(NULL) {}
131         VkPtr operator=(FNPTR_TYPE ptr) {
132             fPtr = ptr;
133             return *this;
134         }
135         // NOLINTNEXTLINE(google-explicit-constructor)
FNPTR_TYPE()136         operator FNPTR_TYPE() const { return fPtr; }
137 
138     private:
139         FNPTR_TYPE fPtr;
140     };
141 
142     // Instance Functions
143     VkPtr<PFN_vkEnumerateInstanceVersion> mEnumerateInstanceVersion;
144     VkPtr<PFN_vkEnumerateInstanceExtensionProperties> mEnumerateInstanceExtensionProperties;
145     VkPtr<PFN_vkCreateInstance> mCreateInstance;
146 
147     VkPtr<PFN_vkDestroyInstance> mDestroyInstance;
148     VkPtr<PFN_vkEnumeratePhysicalDevices> mEnumeratePhysicalDevices;
149     VkPtr<PFN_vkGetPhysicalDeviceProperties> mGetPhysicalDeviceProperties;
150     VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> mGetPhysicalDeviceQueueFamilyProperties;
151     VkPtr<PFN_vkGetPhysicalDeviceFeatures2> mGetPhysicalDeviceFeatures2;
152     VkPtr<PFN_vkGetPhysicalDeviceImageFormatProperties2> mGetPhysicalDeviceImageFormatProperties2;
153     VkPtr<PFN_vkCreateDevice> mCreateDevice;
154     VkPtr<PFN_vkEnumerateDeviceExtensionProperties> mEnumerateDeviceExtensionProperties;
155 
156     // Device Functions
157     VkPtr<PFN_vkGetDeviceQueue> mGetDeviceQueue;
158     VkPtr<PFN_vkDeviceWaitIdle> mDeviceWaitIdle;
159     VkPtr<PFN_vkDestroyDevice> mDestroyDevice;
160     VkPtr<PFN_vkCreateCommandPool> mCreateCommandPool;
161     VkPtr<PFN_vkDestroyCommandPool> mDestroyCommandPool;
162     VkPtr<PFN_vkAllocateCommandBuffers> mAllocateCommandBuffers;
163     VkPtr<PFN_vkFreeCommandBuffers> mFreeCommandBuffers;
164     VkPtr<PFN_vkResetCommandBuffer> mResetCommandBuffer;
165     VkPtr<PFN_vkBeginCommandBuffer> mBeginCommandBuffer;
166     VkPtr<PFN_vkEndCommandBuffer> mEndCommandBuffer;
167     VkPtr<PFN_vkCmdPipelineBarrier> mCmdPipelineBarrier;
168 
169     VkPtr<PFN_vkQueueSubmit> mQueueSubmit;
170     VkPtr<PFN_vkQueueWaitIdle> mQueueWaitIdle;
171 
172     VkPtr<PFN_vkCreateSemaphore> mCreateSemaphore;
173     VkPtr<PFN_vkDestroySemaphore> mDestroySemaphore;
174     VkPtr<PFN_vkImportSemaphoreFdKHR> mImportSemaphoreFdKHR;
175     VkPtr<PFN_vkGetSemaphoreFdKHR> mGetSemaphoreFdKHR;
176     VkPtr<PFN_vkCreateFence> mCreateFence;
177     VkPtr<PFN_vkDestroyFence> mDestroyFence;
178     VkPtr<PFN_vkWaitForFences> mWaitForFences;
179     VkPtr<PFN_vkResetFences> mResetFences;
180     VkPtr<PFN_vkFrameBoundaryANDROID> mFrameBoundaryANDROID;
181 
182     VkInstance mInstance = VK_NULL_HANDLE;
183     VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
184     VkDevice mDevice = VK_NULL_HANDLE;
185 
186     uint32_t mGraphicsQueueIndex;
187 
188     std::mutex mGraphicsQueueMutex;
189     VkQueue mGraphicsQueue = VK_NULL_HANDLE;
190 
interceptedVkQueueSubmit(VkQueue queue,uint32_t submitCount,const VkSubmitInfo * pSubmits,VkFence fence)191     static VKAPI_ATTR VkResult interceptedVkQueueSubmit(VkQueue queue, uint32_t submitCount,
192                                                         const VkSubmitInfo* pSubmits,
193                                                         VkFence fence) {
194         sp<VulkanManager> manager = VulkanManager::getInstance();
195         std::lock_guard<std::mutex> lock(manager->mGraphicsQueueMutex);
196         return manager->mQueueSubmit(queue, submitCount, pSubmits, fence);
197     }
198 
interceptedVkQueueWaitIdle(VkQueue queue)199     static VKAPI_ATTR VkResult interceptedVkQueueWaitIdle(VkQueue queue) {
200         sp<VulkanManager> manager = VulkanManager::getInstance();
201         std::lock_guard<std::mutex> lock(manager->mGraphicsQueueMutex);
202         return manager->mQueueWaitIdle(queue);
203     }
204 
205     static GrVkGetProc sSkiaGetProp;
206 
207     // Variables saved to populate VkFunctorInitParams.
208     static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
209     std::vector<VkExtensionProperties> mInstanceExtensionsOwner;
210     std::vector<const char*> mInstanceExtensions;
211     std::vector<VkExtensionProperties> mDeviceExtensionsOwner;
212     std::vector<const char*> mDeviceExtensions;
213     VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
214 
215     enum class SwapBehavior {
216         Discard,
217         BufferAge,
218     };
219     SwapBehavior mSwapBehavior = SwapBehavior::Discard;
220     GrVkExtensions mExtensions;
221     uint32_t mDriverVersion = 0;
222 
223     VkSemaphore mSwapSemaphore = VK_NULL_HANDLE;
224     void* mDestroySemaphoreContext = nullptr;
225 
226     std::mutex mInitializeLock;
227 };
228 
229 } /* namespace renderthread */
230 } /* namespace uirenderer */
231 } /* namespace android */
232 
233 #endif /* VULKANMANAGER_H */
234