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 void finishFrame(SkSurface* surface); 88 void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect); 89 90 // Inserts a wait on fence command into the Vulkan command buffer. 91 status_t fenceWait(int fence, GrDirectContext* grContext); 92 93 // Creates a fence that is signaled when all the pending Vulkan commands are finished on the 94 // GPU. 95 status_t createReleaseFence(int* nativeFence, GrDirectContext* grContext); 96 97 // Returned pointers are owned by VulkanManager. 98 // An instance of VkFunctorInitParams returned from getVkFunctorInitParams refers to 99 // the internal state of VulkanManager: VulkanManager must be alive to use the returned value. 100 VkFunctorInitParams getVkFunctorInitParams() const; 101 102 103 enum class ContextType { 104 kRenderThread, 105 kUploadThread 106 }; 107 108 // returns a Skia graphic context used to draw content on the specified thread 109 sk_sp<GrDirectContext> createContext(const GrContextOptions& options, 110 ContextType contextType = ContextType::kRenderThread); 111 getDriverVersion()112 uint32_t getDriverVersion() const { return mDriverVersion; } 113 114 private: 115 friend class VulkanSurface; 116 VulkanManager()117 explicit VulkanManager() {} 118 ~VulkanManager(); 119 120 // Sets up the VkInstance and VkDevice objects. Also fills out the passed in 121 // VkPhysicalDeviceFeatures struct. 122 void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&); 123 124 // simple wrapper class that exists only to initialize a pointer to NULL 125 template <typename FNPTR_TYPE> 126 class VkPtr { 127 public: VkPtr()128 VkPtr() : fPtr(NULL) {} 129 VkPtr operator=(FNPTR_TYPE ptr) { 130 fPtr = ptr; 131 return *this; 132 } 133 // NOLINTNEXTLINE(google-explicit-constructor) FNPTR_TYPE()134 operator FNPTR_TYPE() const { return fPtr; } 135 136 private: 137 FNPTR_TYPE fPtr; 138 }; 139 140 // Instance Functions 141 VkPtr<PFN_vkEnumerateInstanceVersion> mEnumerateInstanceVersion; 142 VkPtr<PFN_vkEnumerateInstanceExtensionProperties> mEnumerateInstanceExtensionProperties; 143 VkPtr<PFN_vkCreateInstance> mCreateInstance; 144 145 VkPtr<PFN_vkDestroyInstance> mDestroyInstance; 146 VkPtr<PFN_vkEnumeratePhysicalDevices> mEnumeratePhysicalDevices; 147 VkPtr<PFN_vkGetPhysicalDeviceProperties> mGetPhysicalDeviceProperties; 148 VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> mGetPhysicalDeviceQueueFamilyProperties; 149 VkPtr<PFN_vkGetPhysicalDeviceFeatures2> mGetPhysicalDeviceFeatures2; 150 VkPtr<PFN_vkGetPhysicalDeviceImageFormatProperties2> mGetPhysicalDeviceImageFormatProperties2; 151 VkPtr<PFN_vkCreateDevice> mCreateDevice; 152 VkPtr<PFN_vkEnumerateDeviceExtensionProperties> mEnumerateDeviceExtensionProperties; 153 154 // Device Functions 155 VkPtr<PFN_vkGetDeviceQueue> mGetDeviceQueue; 156 VkPtr<PFN_vkDeviceWaitIdle> mDeviceWaitIdle; 157 VkPtr<PFN_vkDestroyDevice> mDestroyDevice; 158 VkPtr<PFN_vkCreateCommandPool> mCreateCommandPool; 159 VkPtr<PFN_vkDestroyCommandPool> mDestroyCommandPool; 160 VkPtr<PFN_vkAllocateCommandBuffers> mAllocateCommandBuffers; 161 VkPtr<PFN_vkFreeCommandBuffers> mFreeCommandBuffers; 162 VkPtr<PFN_vkResetCommandBuffer> mResetCommandBuffer; 163 VkPtr<PFN_vkBeginCommandBuffer> mBeginCommandBuffer; 164 VkPtr<PFN_vkEndCommandBuffer> mEndCommandBuffer; 165 VkPtr<PFN_vkCmdPipelineBarrier> mCmdPipelineBarrier; 166 167 VkPtr<PFN_vkQueueSubmit> mQueueSubmit; 168 VkPtr<PFN_vkQueueWaitIdle> mQueueWaitIdle; 169 170 VkPtr<PFN_vkCreateSemaphore> mCreateSemaphore; 171 VkPtr<PFN_vkDestroySemaphore> mDestroySemaphore; 172 VkPtr<PFN_vkImportSemaphoreFdKHR> mImportSemaphoreFdKHR; 173 VkPtr<PFN_vkGetSemaphoreFdKHR> mGetSemaphoreFdKHR; 174 VkPtr<PFN_vkCreateFence> mCreateFence; 175 VkPtr<PFN_vkDestroyFence> mDestroyFence; 176 VkPtr<PFN_vkWaitForFences> mWaitForFences; 177 VkPtr<PFN_vkResetFences> mResetFences; 178 VkPtr<PFN_vkFrameBoundaryANDROID> mFrameBoundaryANDROID; 179 180 VkInstance mInstance = VK_NULL_HANDLE; 181 VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE; 182 VkDevice mDevice = VK_NULL_HANDLE; 183 184 uint32_t mGraphicsQueueIndex; 185 186 std::mutex mGraphicsQueueMutex; 187 VkQueue mGraphicsQueue = VK_NULL_HANDLE; 188 interceptedVkQueueSubmit(VkQueue queue,uint32_t submitCount,const VkSubmitInfo * pSubmits,VkFence fence)189 static VKAPI_ATTR VkResult interceptedVkQueueSubmit(VkQueue queue, uint32_t submitCount, 190 const VkSubmitInfo* pSubmits, 191 VkFence fence) { 192 sp<VulkanManager> manager = VulkanManager::getInstance(); 193 std::lock_guard<std::mutex> lock(manager->mGraphicsQueueMutex); 194 return manager->mQueueSubmit(queue, submitCount, pSubmits, fence); 195 } 196 interceptedVkQueueWaitIdle(VkQueue queue)197 static VKAPI_ATTR VkResult interceptedVkQueueWaitIdle(VkQueue queue) { 198 sp<VulkanManager> manager = VulkanManager::getInstance(); 199 std::lock_guard<std::mutex> lock(manager->mGraphicsQueueMutex); 200 return manager->mQueueWaitIdle(queue); 201 } 202 203 static GrVkGetProc sSkiaGetProp; 204 205 // Variables saved to populate VkFunctorInitParams. 206 static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0); 207 std::vector<VkExtensionProperties> mInstanceExtensionsOwner; 208 std::vector<const char*> mInstanceExtensions; 209 std::vector<VkExtensionProperties> mDeviceExtensionsOwner; 210 std::vector<const char*> mDeviceExtensions; 211 VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{}; 212 213 enum class SwapBehavior { 214 Discard, 215 BufferAge, 216 }; 217 SwapBehavior mSwapBehavior = SwapBehavior::Discard; 218 GrVkExtensions mExtensions; 219 uint32_t mDriverVersion = 0; 220 221 VkSemaphore mSwapSemaphore = VK_NULL_HANDLE; 222 void* mDestroySemaphoreContext = nullptr; 223 224 std::mutex mInitializeLock; 225 }; 226 227 } /* namespace renderthread */ 228 } /* namespace uirenderer */ 229 } /* namespace android */ 230 231 #endif /* VULKANMANAGER_H */ 232