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