Flutter Engine
vulkan_proc_table.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "vulkan_proc_table.h"
6 
7 #include <dlfcn.h>
8 
9 #include "flutter/fml/logging.h"
10 
11 #define ACQUIRE_PROC(name, context) \
12  if (!(name = AcquireProc("vk" #name, context))) { \
13  FML_DLOG(INFO) << "Could not acquire proc: vk" << #name; \
14  return false; \
15  }
16 
17 namespace vulkan {
18 
19 VulkanProcTable::VulkanProcTable()
20  : handle_(nullptr), acquired_mandatory_proc_addresses_(false) {
21  acquired_mandatory_proc_addresses_ =
22  OpenLibraryHandle() && SetupLoaderProcAddresses();
23 }
24 
25 VulkanProcTable::~VulkanProcTable() {
26  CloseLibraryHandle();
27 }
28 
30  return acquired_mandatory_proc_addresses_;
31 }
32 
34  return instance_ && device_;
35 }
36 
38  return instance_;
39 }
40 
42  return device_;
43 }
44 
45 bool VulkanProcTable::SetupLoaderProcAddresses() {
46  if (handle_ == nullptr) {
47  return true;
48  }
49 
50  GetInstanceProcAddr =
51 #if VULKAN_LINK_STATICALLY
52  GetInstanceProcAddr = &vkGetInstanceProcAddr;
53 #else // VULKAN_LINK_STATICALLY
54  reinterpret_cast<PFN_vkGetInstanceProcAddr>(
55  dlsym(handle_, "vkGetInstanceProcAddr"));
56 #endif // VULKAN_LINK_STATICALLY
57 
58  if (!GetInstanceProcAddr) {
59  FML_DLOG(WARNING) << "Could not acquire vkGetInstanceProcAddr.";
60  return false;
61  }
62 
63  VulkanHandle<VkInstance> null_instance(VK_NULL_HANDLE, nullptr);
64 
65  ACQUIRE_PROC(CreateInstance, null_instance);
66  ACQUIRE_PROC(EnumerateInstanceExtensionProperties, null_instance);
67  ACQUIRE_PROC(EnumerateInstanceLayerProperties, null_instance);
68 
69  return true;
70 }
71 
73  const VulkanHandle<VkInstance>& handle) {
74  ACQUIRE_PROC(CreateDevice, handle);
75  ACQUIRE_PROC(DestroyDevice, handle);
76  ACQUIRE_PROC(DestroyInstance, handle);
77  ACQUIRE_PROC(EnumerateDeviceLayerProperties, handle);
78  ACQUIRE_PROC(EnumeratePhysicalDevices, handle);
79  ACQUIRE_PROC(GetDeviceProcAddr, handle);
80  ACQUIRE_PROC(GetPhysicalDeviceFeatures, handle);
81  ACQUIRE_PROC(GetPhysicalDeviceQueueFamilyProperties, handle);
82 #if OS_ANDROID
83  ACQUIRE_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR, handle);
84  ACQUIRE_PROC(GetPhysicalDeviceSurfaceFormatsKHR, handle);
85  ACQUIRE_PROC(GetPhysicalDeviceSurfacePresentModesKHR, handle);
86  ACQUIRE_PROC(GetPhysicalDeviceSurfaceSupportKHR, handle);
87  ACQUIRE_PROC(DestroySurfaceKHR, handle);
88  ACQUIRE_PROC(CreateAndroidSurfaceKHR, handle);
89 #endif // OS_ANDROID
90 
91  // The debug report functions are optional. We don't want proc acquisition to
92  // fail here because the optional methods were not present (since ACQUIRE_PROC
93  // returns false on failure). Wrap the optional proc acquisitions in an
94  // anonymous lambda and invoke it. We don't really care about the result since
95  // users of Debug reporting functions check for their presence explicitly.
96  [this, &handle]() -> bool {
97  ACQUIRE_PROC(CreateDebugReportCallbackEXT, handle);
98  ACQUIRE_PROC(DestroyDebugReportCallbackEXT, handle);
99  return true;
100  }();
101 
102  instance_ = {handle, nullptr};
103  return true;
104 }
105 
107  const VulkanHandle<VkDevice>& handle) {
108  ACQUIRE_PROC(AllocateCommandBuffers, handle);
109  ACQUIRE_PROC(AllocateMemory, handle);
110  ACQUIRE_PROC(BeginCommandBuffer, handle);
111  ACQUIRE_PROC(BindImageMemory, handle);
112  ACQUIRE_PROC(CmdPipelineBarrier, handle);
113  ACQUIRE_PROC(CreateCommandPool, handle);
114  ACQUIRE_PROC(CreateFence, handle);
115  ACQUIRE_PROC(CreateImage, handle);
116  ACQUIRE_PROC(CreateSemaphore, handle);
117  ACQUIRE_PROC(DestroyCommandPool, handle);
118  ACQUIRE_PROC(DestroyFence, handle);
119  ACQUIRE_PROC(DestroyImage, handle);
120  ACQUIRE_PROC(DestroySemaphore, handle);
121  ACQUIRE_PROC(DeviceWaitIdle, handle);
122  ACQUIRE_PROC(EndCommandBuffer, handle);
123  ACQUIRE_PROC(FreeCommandBuffers, handle);
124  ACQUIRE_PROC(FreeMemory, handle);
125  ACQUIRE_PROC(GetDeviceQueue, handle);
126  ACQUIRE_PROC(GetImageMemoryRequirements, handle);
127  ACQUIRE_PROC(QueueSubmit, handle);
128  ACQUIRE_PROC(QueueWaitIdle, handle);
129  ACQUIRE_PROC(ResetCommandBuffer, handle);
130  ACQUIRE_PROC(ResetFences, handle);
131  ACQUIRE_PROC(WaitForFences, handle);
132 #if OS_ANDROID
133  ACQUIRE_PROC(AcquireNextImageKHR, handle);
134  ACQUIRE_PROC(CreateSwapchainKHR, handle);
135  ACQUIRE_PROC(DestroySwapchainKHR, handle);
136  ACQUIRE_PROC(GetSwapchainImagesKHR, handle);
137  ACQUIRE_PROC(QueuePresentKHR, handle);
138 #endif // OS_ANDROID
139 #if OS_FUCHSIA
140  ACQUIRE_PROC(GetMemoryZirconHandleFUCHSIA, handle);
141  ACQUIRE_PROC(ImportSemaphoreZirconHandleFUCHSIA, handle);
142 #endif // OS_FUCHSIA
143  device_ = {handle, nullptr};
144  return true;
145 }
146 
147 bool VulkanProcTable::OpenLibraryHandle() {
148 #if VULKAN_LINK_STATICALLY
149  static char kDummyLibraryHandle = '\0';
150  handle_ = reinterpret_cast<decltype(handle_)>(&kDummyLibraryHandle);
151  return true;
152 #else // VULKAN_LINK_STATICALLY
153  dlerror(); // clear existing errors on thread.
154  handle_ = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
155  if (handle_ == nullptr) {
156  FML_DLOG(WARNING) << "Could not open the vulkan library: " << dlerror();
157  return false;
158  }
159  return true;
160 #endif // VULKAN_LINK_STATICALLY
161 }
162 
163 bool VulkanProcTable::CloseLibraryHandle() {
164 #if VULKAN_LINK_STATICALLY
165  handle_ = nullptr;
166  return true;
167 #else
168  if (handle_ != nullptr) {
169  dlerror(); // clear existing errors on thread.
170  if (dlclose(handle_) != 0) {
171  FML_DLOG(ERROR) << "Could not close the vulkan library handle. This "
172  "indicates a leak.";
173  FML_DLOG(ERROR) << dlerror();
174  }
175  handle_ = nullptr;
176  }
177  return handle_ == nullptr;
178 #endif
179 }
180 
181 PFN_vkVoidFunction VulkanProcTable::AcquireProc(
182  const char* proc_name,
183  const VulkanHandle<VkInstance>& instance) const {
184  if (proc_name == nullptr || !GetInstanceProcAddr) {
185  return nullptr;
186  }
187 
188  // A VK_NULL_HANDLE as the instance is an acceptable parameter.
189  return GetInstanceProcAddr(instance, proc_name);
190 }
191 
192 PFN_vkVoidFunction VulkanProcTable::AcquireProc(
193  const char* proc_name,
194  const VulkanHandle<VkDevice>& device) const {
195  if (proc_name == nullptr || !device || !GetDeviceProcAddr) {
196  return nullptr;
197  }
198 
199  return GetDeviceProcAddr(device, proc_name);
200 }
201 
203  if (!IsValid()) {
204  return nullptr;
205  }
206 
207  return [this](const char* proc_name, VkInstance instance, VkDevice device) {
208  if (device != VK_NULL_HANDLE) {
209  auto result = AcquireProc(proc_name, {device, nullptr});
210  if (result != nullptr) {
211  return result;
212  }
213  }
214 
215  return AcquireProc(proc_name, {instance, nullptr});
216  };
217 }
218 
219 } // namespace vulkan
bool SetupDeviceProcAddresses(const VulkanHandle< VkDevice > &device)
bool AreInstanceProcsSetup() const
GrVkGetProc CreateSkiaGetProc() const
bool SetupInstanceProcAddresses(const VulkanHandle< VkInstance > &instance)
bool HasAcquiredMandatoryProcAddresses() const
#define ACQUIRE_PROC(name, context)
#define FML_DLOG(severity)
Definition: logging.h:85