1 // Copyright (C) 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 express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <hardware/hwvulkan.h>
15 
16 #include <log/log.h>
17 
18 #include <errno.h>
19 #include <string.h>
20 #ifdef VK_USE_PLATFORM_FUCHSIA
21 #include <fuchsia/logger/llcpp/fidl.h>
22 #include <lib/syslog/global.h>
23 #include <lib/zx/channel.h>
24 #include <lib/zx/socket.h>
25 #include <lib/zxio/zxio.h>
26 #include <lib/zxio/inception.h>
27 #include <unistd.h>
28 
29 #include "services/service_connector.h"
30 #endif
31 
32 #include "HostConnection.h"
33 #include "ResourceTracker.h"
34 #include "VkEncoder.h"
35 
36 #include "func_table.h"
37 
38 // Used when there is no Vulkan support on the host.
39 // Copied from frameworks/native/vulkan/libvulkan/stubhal.cpp
40 namespace vkstubhal {
41 
NoOp()42 [[noreturn]] VKAPI_ATTR void NoOp() {
43     LOG_ALWAYS_FATAL("invalid stub function called");
44 }
45 
46 VkResult
EnumerateInstanceExtensionProperties(const char *,uint32_t * count,VkExtensionProperties *)47 EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
48                                      uint32_t* count,
49                                      VkExtensionProperties* /*properties*/) {
50     AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceExtensionProperties");
51     *count = 0;
52     return VK_SUCCESS;
53 }
54 
55 VkResult
EnumerateInstanceLayerProperties(uint32_t * count,VkLayerProperties *)56 EnumerateInstanceLayerProperties(uint32_t* count,
57                                  VkLayerProperties* /*properties*/) {
58     AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceLayerProperties");
59     *count = 0;
60     return VK_SUCCESS;
61 }
62 
CreateInstance(const VkInstanceCreateInfo *,const VkAllocationCallbacks *,VkInstance * instance)63 VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
64                         const VkAllocationCallbacks* /*allocator*/,
65                         VkInstance* instance) {
66     AEMU_SCOPED_TRACE("vkstubhal::CreateInstance");
67     auto dispatch = new hwvulkan_dispatch_t;
68     dispatch->magic = HWVULKAN_DISPATCH_MAGIC;
69     *instance = reinterpret_cast<VkInstance>(dispatch);
70     return VK_SUCCESS;
71 }
72 
DestroyInstance(VkInstance instance,const VkAllocationCallbacks *)73 void DestroyInstance(VkInstance instance,
74                      const VkAllocationCallbacks* /*allocator*/) {
75     AEMU_SCOPED_TRACE("vkstubhal::DestroyInstance");
76     auto dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(instance);
77     ALOG_ASSERT(dispatch->magic == HWVULKAN_DISPATCH_MAGIC,
78                 "DestroyInstance: invalid instance handle");
79     delete dispatch;
80 }
81 
EnumeratePhysicalDevices(VkInstance,uint32_t * count,VkPhysicalDevice *)82 VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
83                                   uint32_t* count,
84                                   VkPhysicalDevice* /*gpus*/) {
85     AEMU_SCOPED_TRACE("vkstubhal::EnumeratePhysicalDevices");
86     *count = 0;
87     return VK_SUCCESS;
88 }
89 
EnumerateInstanceVersion(uint32_t * pApiVersion)90 VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
91     AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceVersion");
92     *pApiVersion = VK_API_VERSION_1_0;
93     return VK_SUCCESS;
94 }
95 
96 VkResult
EnumeratePhysicalDeviceGroups(VkInstance,uint32_t * count,VkPhysicalDeviceGroupProperties *)97 EnumeratePhysicalDeviceGroups(VkInstance /*instance*/,
98                               uint32_t* count,
99                               VkPhysicalDeviceGroupProperties* /*properties*/) {
100     AEMU_SCOPED_TRACE("vkstubhal::EnumeratePhysicalDeviceGroups");
101     *count = 0;
102     return VK_SUCCESS;
103 }
104 
105 VkResult
CreateDebugReportCallbackEXT(VkInstance,const VkDebugReportCallbackCreateInfoEXT *,const VkAllocationCallbacks *,VkDebugReportCallbackEXT * pCallback)106 CreateDebugReportCallbackEXT(VkInstance /*instance*/,
107                              const VkDebugReportCallbackCreateInfoEXT* /*pCreateInfo*/,
108                              const VkAllocationCallbacks* /*pAllocator*/,
109                              VkDebugReportCallbackEXT* pCallback)
110 {
111     AEMU_SCOPED_TRACE("vkstubhal::CreateDebugReportCallbackEXT");
112     *pCallback = VK_NULL_HANDLE;
113     return VK_SUCCESS;
114 }
115 
116 void
DestroyDebugReportCallbackEXT(VkInstance,VkDebugReportCallbackEXT,const VkAllocationCallbacks *)117 DestroyDebugReportCallbackEXT(VkInstance /*instance*/,
118                               VkDebugReportCallbackEXT /*callback*/,
119                               const VkAllocationCallbacks* /*pAllocator*/)
120 {
121     AEMU_SCOPED_TRACE("vkstubhal::DestroyDebugReportCallbackEXT");
122 }
123 
124 void
DebugReportMessageEXT(VkInstance,VkDebugReportFlagsEXT,VkDebugReportObjectTypeEXT,uint64_t,size_t,int32_t,const char *,const char *)125 DebugReportMessageEXT(VkInstance /*instance*/,
126                       VkDebugReportFlagsEXT /*flags*/,
127                       VkDebugReportObjectTypeEXT /*objectType*/,
128                       uint64_t /*object*/,
129                       size_t /*location*/,
130                       int32_t /*messageCode*/,
131                       const char* /*pLayerPrefix*/,
132                       const char* /*pMessage*/)
133 {
134     AEMU_SCOPED_TRACE("vkstubhal::DebugReportMessageEXT");
135 }
136 
137 VkResult
CreateDebugUtilsMessengerEXT(VkInstance,const VkDebugUtilsMessengerCreateInfoEXT *,const VkAllocationCallbacks *,VkDebugUtilsMessengerEXT * pMessenger)138 CreateDebugUtilsMessengerEXT(VkInstance /*instance*/,
139                              const VkDebugUtilsMessengerCreateInfoEXT* /*pCreateInfo*/,
140                              const VkAllocationCallbacks* /*pAllocator*/,
141                              VkDebugUtilsMessengerEXT* pMessenger)
142 {
143     AEMU_SCOPED_TRACE("vkstubhal::CreateDebugUtilsMessengerEXT");
144     *pMessenger = VK_NULL_HANDLE;
145     return VK_SUCCESS;
146 }
147 
148 void
DestroyDebugUtilsMessengerEXT(VkInstance,VkDebugUtilsMessengerEXT,const VkAllocationCallbacks *)149 DestroyDebugUtilsMessengerEXT(VkInstance /*instance*/,
150                               VkDebugUtilsMessengerEXT /*messenger*/,
151                               const VkAllocationCallbacks* /*pAllocator*/)
152 {
153     AEMU_SCOPED_TRACE("vkstubhal::DestroyDebugUtilsMessengerkEXT");
154 }
155 
156 void
SubmitDebugUtilsMessageEXT(VkInstance,VkDebugUtilsMessageSeverityFlagBitsEXT,VkDebugUtilsMessageTypeFlagsEXT,const VkDebugUtilsMessengerCallbackDataEXT *)157 SubmitDebugUtilsMessageEXT(VkInstance /*instance*/,
158                            VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/,
159                            VkDebugUtilsMessageTypeFlagsEXT /*messageTypes*/,
160                            const VkDebugUtilsMessengerCallbackDataEXT* /*pCallbackData*/)
161 {
162     AEMU_SCOPED_TRACE("vkstubhal::SubmitDebugUtilsMessageEXT");
163 }
164 
165 #ifdef VK_USE_PLATFORM_FUCHSIA
166 VkResult
GetMemoryZirconHandleFUCHSIA(VkDevice,const VkMemoryGetZirconHandleInfoFUCHSIA *,uint32_t * pHandle)167 GetMemoryZirconHandleFUCHSIA(VkDevice /*device*/,
168                              const VkMemoryGetZirconHandleInfoFUCHSIA* /*pInfo*/,
169                              uint32_t* pHandle) {
170     AEMU_SCOPED_TRACE("vkstubhal::GetMemoryZirconHandleFUCHSIA");
171     *pHandle = 0;
172     return VK_SUCCESS;
173 }
174 
175 VkResult
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice,VkExternalMemoryHandleTypeFlagBits,uint32_t,VkMemoryZirconHandlePropertiesFUCHSIA *)176 GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice /*device*/,
177                                        VkExternalMemoryHandleTypeFlagBits /*handleType*/,
178                                        uint32_t /*handle*/,
179                                        VkMemoryZirconHandlePropertiesFUCHSIA* /*pProperties*/) {
180     AEMU_SCOPED_TRACE("vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA");
181     return VK_SUCCESS;
182 }
183 
184 VkResult
GetSemaphoreZirconHandleFUCHSIA(VkDevice,const VkSemaphoreGetZirconHandleInfoFUCHSIA *,uint32_t * pHandle)185 GetSemaphoreZirconHandleFUCHSIA(VkDevice /*device*/,
186                                 const VkSemaphoreGetZirconHandleInfoFUCHSIA* /*pInfo*/,
187                                 uint32_t* pHandle) {
188     AEMU_SCOPED_TRACE("vkstubhal::GetSemaphoreZirconHandleFUCHSIA");
189     *pHandle = 0;
190     return VK_SUCCESS;
191 }
192 
193 VkResult
ImportSemaphoreZirconHandleFUCHSIA(VkDevice,const VkImportSemaphoreZirconHandleInfoFUCHSIA *)194 ImportSemaphoreZirconHandleFUCHSIA(VkDevice /*device*/,
195                                    const VkImportSemaphoreZirconHandleInfoFUCHSIA* /*pInfo*/) {
196     AEMU_SCOPED_TRACE("vkstubhal::ImportSemaphoreZirconHandleFUCHSIA");
197     return VK_SUCCESS;
198 }
199 
200 VkResult
CreateBufferCollectionFUCHSIA(VkDevice,const VkBufferCollectionCreateInfoFUCHSIA *,const VkAllocationCallbacks *,VkBufferCollectionFUCHSIA *)201 CreateBufferCollectionFUCHSIA(VkDevice /*device*/,
202                               const VkBufferCollectionCreateInfoFUCHSIA* /*pInfo*/,
203                               const VkAllocationCallbacks* /*pAllocator*/,
204                               VkBufferCollectionFUCHSIA* /*pCollection*/) {
205     AEMU_SCOPED_TRACE("vkstubhal::CreateBufferCollectionFUCHSIA");
206     return VK_SUCCESS;
207 }
208 
209 void
DestroyBufferCollectionFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkAllocationCallbacks *)210 DestroyBufferCollectionFUCHSIA(VkDevice /*device*/,
211                                VkBufferCollectionFUCHSIA /*collection*/,
212                                const VkAllocationCallbacks* /*pAllocator*/) {
213     AEMU_SCOPED_TRACE("vkstubhal::DestroyBufferCollectionFUCHSIA");
214 }
215 
216 VkResult
SetBufferCollectionConstraintsFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkImageCreateInfo *)217 SetBufferCollectionConstraintsFUCHSIA(VkDevice /*device*/,
218                                       VkBufferCollectionFUCHSIA /*collection*/,
219                                       const VkImageCreateInfo* /*pImageInfo*/) {
220     AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionConstraintsFUCHSIA");
221     return VK_SUCCESS;
222 }
223 
224 VkResult
GetBufferCollectionPropertiesFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,VkBufferCollectionPropertiesFUCHSIA *)225 GetBufferCollectionPropertiesFUCHSIA(VkDevice /*device*/,
226                                      VkBufferCollectionFUCHSIA /*collection*/,
227                                      VkBufferCollectionPropertiesFUCHSIA* /*pProperties*/) {
228     AEMU_SCOPED_TRACE("vkstubhal::GetBufferCollectionPropertiesFUCHSIA");
229     return VK_SUCCESS;
230 }
231 #endif
232 
GetInstanceProcAddr(VkInstance instance,const char * name)233 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
234                                        const char* name) {
235     AEMU_SCOPED_TRACE("vkstubhal::GetInstanceProcAddr");
236     if (strcmp(name, "vkCreateInstance") == 0)
237         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
238     if (strcmp(name, "vkDestroyInstance") == 0)
239         return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
240     if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
241         return reinterpret_cast<PFN_vkVoidFunction>(
242             EnumerateInstanceExtensionProperties);
243     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
244         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
245     if (strcmp(name, "vkEnumerateInstanceVersion") == 0)
246         return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
247     if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
248         return reinterpret_cast<PFN_vkVoidFunction>(
249             EnumeratePhysicalDeviceGroups);
250     if (strcmp(name, "vkEnumeratePhysicalDeviceGroupsKHR") == 0)
251         return reinterpret_cast<PFN_vkVoidFunction>(
252             EnumeratePhysicalDeviceGroups);
253     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
254         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
255     if (strcmp(name, "vkCreateDebugReportCallbackEXT") == 0)
256         return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT);
257     if (strcmp(name, "vkDestroyDebugReportCallbackEXT") == 0)
258         return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT);
259     if (strcmp(name, "vkDebugReportMessageEXT") == 0)
260         return reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT);
261     if (strcmp(name, "vkCreateDebugUtilsMessengerEXT") == 0)
262         return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugUtilsMessengerEXT);
263     if (strcmp(name, "vkDestroyDebugUtilsMessengerEXT") == 0)
264         return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugUtilsMessengerEXT);
265     if (strcmp(name, "vkSubmitDebugUtilsMessageEXT") == 0)
266         return reinterpret_cast<PFN_vkVoidFunction>(SubmitDebugUtilsMessageEXT);
267 #ifdef VK_USE_PLATFORM_FUCHSIA
268     if (strcmp(name, "vkGetMemoryZirconHandleFUCHSIA") == 0)
269         return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandleFUCHSIA);
270     if (strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA") == 0)
271         return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandlePropertiesFUCHSIA);
272     if (strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA") == 0)
273         return reinterpret_cast<PFN_vkVoidFunction>(GetSemaphoreZirconHandleFUCHSIA);
274     if (strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA") == 0)
275         return reinterpret_cast<PFN_vkVoidFunction>(ImportSemaphoreZirconHandleFUCHSIA);
276     if (strcmp(name, "vkCreateBufferCollectionFUCHSIA") == 0)
277         return reinterpret_cast<PFN_vkVoidFunction>(CreateBufferCollectionFUCHSIA);
278     if (strcmp(name, "vkDestroyBufferCollectionFUCHSIA") == 0)
279         return reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferCollectionFUCHSIA);
280     if (strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA") == 0)
281         return reinterpret_cast<PFN_vkVoidFunction>(SetBufferCollectionConstraintsFUCHSIA);
282     if (strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA") == 0)
283         return reinterpret_cast<PFN_vkVoidFunction>(GetBufferCollectionPropertiesFUCHSIA);
284 #endif
285     // Return NoOp for entrypoints that should never be called.
286     if (strcmp(name, "vkGetPhysicalDeviceFeatures") == 0 ||
287         strcmp(name, "vkGetPhysicalDeviceProperties") == 0 ||
288         strcmp(name, "vkGetPhysicalDeviceFormatProperties") == 0 ||
289         strcmp(name, "vkGetPhysicalDeviceImageFormatProperties") == 0 ||
290         strcmp(name, "vkGetPhysicalDeviceMemoryProperties") == 0 ||
291         strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties") == 0 ||
292         strcmp(name, "vkGetDeviceProcAddr") == 0 ||
293         strcmp(name, "vkCreateDevice") == 0 ||
294         strcmp(name, "vkEnumerateDeviceExtensionProperties") == 0 ||
295         strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties") == 0 ||
296         strcmp(name, "vkGetPhysicalDeviceFeatures2") == 0 ||
297         strcmp(name, "vkGetPhysicalDeviceProperties2") == 0 ||
298         strcmp(name, "vkGetPhysicalDeviceFormatProperties2") == 0 ||
299         strcmp(name, "vkGetPhysicalDeviceImageFormatProperties2") == 0 ||
300         strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties2") == 0 ||
301         strcmp(name, "vkGetPhysicalDeviceMemoryProperties2") == 0 ||
302         strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties2") == 0 ||
303         strcmp(name, "vkGetPhysicalDeviceExternalBufferProperties") == 0 ||
304         strcmp(name, "vkGetPhysicalDeviceExternalFenceProperties") == 0 ||
305         strcmp(name, "vkGetPhysicalDeviceExternalSemaphoreProperties") == 0)
306         return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
307 
308     // Per the spec, return NULL for nonexistent entrypoints.
309     return nullptr;
310 }
311 
312 } // namespace vkstubhal
313 
314 namespace {
315 
316 #ifdef VK_USE_PLATFORM_ANDROID_KHR
317 
318 int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
319 
320 hw_module_methods_t goldfish_vulkan_module_methods = {
321     .open = OpenDevice
322 };
323 
324 extern "C" __attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
325     .common = {
326         .tag = HARDWARE_MODULE_TAG,
327         .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
328         .hal_api_version = HARDWARE_HAL_API_VERSION,
329         .id = HWVULKAN_HARDWARE_MODULE_ID,
330         .name = "Goldfish Vulkan Driver",
331         .author = "The Android Open Source Project",
332         .methods = &goldfish_vulkan_module_methods,
333     },
334 };
335 
CloseDevice(struct hw_device_t *)336 int CloseDevice(struct hw_device_t* /*device*/) {
337     AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
338     // nothing to do - opening a device doesn't allocate any resources
339     return 0;
340 }
341 
342 #endif
343 
344 #define VK_HOST_CONNECTION(ret) \
345     HostConnection *hostCon = HostConnection::get(); \
346     if (!hostCon) { \
347         ALOGE("vulkan: Failed to get host connection\n"); \
348         return ret; \
349     } \
350     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
351     if (!rcEnc) { \
352         ALOGE("vulkan: Failed to get renderControl encoder context\n"); \
353         return ret; \
354     } \
355     goldfish_vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const()); \
356     goldfish_vk::ResourceTracker::ThreadingCallbacks threadingCallbacks = { \
357         [] { auto hostCon = HostConnection::get(); \
358             ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
359             return hostCon; }, \
360         [](HostConnection* hostCon) { return hostCon->vkEncoder(); }, \
361     }; \
362     goldfish_vk::ResourceTracker::get()->setThreadingCallbacks(threadingCallbacks); \
363     auto hostSupportsVulkan = goldfish_vk::ResourceTracker::get()->hostSupportsVulkan(); \
364     goldfish_vk::VkEncoder *vkEnc = hostCon->vkEncoder(); \
365     if (!vkEnc) { \
366         ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
367         return ret; \
368     } \
369 
370 VKAPI_ATTR
EnumerateInstanceExtensionProperties(const char * layer_name,uint32_t * count,VkExtensionProperties * properties)371 VkResult EnumerateInstanceExtensionProperties(
372     const char* layer_name,
373     uint32_t* count,
374     VkExtensionProperties* properties) {
375     AEMU_SCOPED_TRACE("goldfish_vulkan::EnumerateInstanceExtensionProperties");
376 
377     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
378 
379     if (!hostSupportsVulkan) {
380         return vkstubhal::EnumerateInstanceExtensionProperties(layer_name, count, properties);
381     }
382 
383     if (layer_name) {
384         ALOGW(
385             "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
386             "with a layer name ('%s')",
387             layer_name);
388     }
389 
390     VkResult res = goldfish_vk::ResourceTracker::get()->on_vkEnumerateInstanceExtensionProperties(
391         vkEnc, VK_SUCCESS, layer_name, count, properties);
392 
393     return res;
394 }
395 
396 VKAPI_ATTR
CreateInstance(const VkInstanceCreateInfo * create_info,const VkAllocationCallbacks * allocator,VkInstance * out_instance)397 VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
398                         const VkAllocationCallbacks* allocator,
399                         VkInstance* out_instance) {
400     AEMU_SCOPED_TRACE("goldfish_vulkan::CreateInstance");
401 
402     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
403 
404     if (!hostSupportsVulkan) {
405         return vkstubhal::CreateInstance(create_info, allocator, out_instance);
406     }
407 
408     VkResult res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance);
409 
410     return res;
411 }
412 
413 #ifdef VK_USE_PLATFORM_FUCHSIA
414 VKAPI_ATTR
GetMemoryZirconHandleFUCHSIA(VkDevice device,const VkMemoryGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)415 VkResult GetMemoryZirconHandleFUCHSIA(
416     VkDevice device,
417     const VkMemoryGetZirconHandleInfoFUCHSIA* pInfo,
418     uint32_t* pHandle) {
419     AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandleFUCHSIA");
420 
421     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
422 
423     if (!hostSupportsVulkan) {
424         return vkstubhal::GetMemoryZirconHandleFUCHSIA(device, pInfo, pHandle);
425     }
426 
427     VkResult res = goldfish_vk::ResourceTracker::get()->
428         on_vkGetMemoryZirconHandleFUCHSIA(
429             vkEnc, VK_SUCCESS,
430             device, pInfo, pHandle);
431 
432     return res;
433 }
434 
435 VKAPI_ATTR
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice device,VkExternalMemoryHandleTypeFlagBits handleType,uint32_t handle,VkMemoryZirconHandlePropertiesFUCHSIA * pProperties)436 VkResult GetMemoryZirconHandlePropertiesFUCHSIA(
437     VkDevice device,
438     VkExternalMemoryHandleTypeFlagBits handleType,
439     uint32_t handle,
440     VkMemoryZirconHandlePropertiesFUCHSIA* pProperties) {
441     AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandlePropertiesFUCHSIA");
442 
443     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
444 
445     if (!hostSupportsVulkan) {
446         return vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA(
447             device, handleType, handle, pProperties);
448     }
449 
450     VkResult res = goldfish_vk::ResourceTracker::get()->
451         on_vkGetMemoryZirconHandlePropertiesFUCHSIA(
452             vkEnc, VK_SUCCESS, device, handleType, handle, pProperties);
453 
454     return res;
455 }
456 
457 VKAPI_ATTR
GetSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkSemaphoreGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)458 VkResult GetSemaphoreZirconHandleFUCHSIA(
459     VkDevice device,
460     const VkSemaphoreGetZirconHandleInfoFUCHSIA* pInfo,
461     uint32_t* pHandle) {
462     AEMU_SCOPED_TRACE("goldfish_vulkan::GetSemaphoreZirconHandleFUCHSIA");
463 
464     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
465 
466     if (!hostSupportsVulkan) {
467         return vkstubhal::GetSemaphoreZirconHandleFUCHSIA(device, pInfo, pHandle);
468     }
469 
470     VkResult res = goldfish_vk::ResourceTracker::get()->
471         on_vkGetSemaphoreZirconHandleFUCHSIA(
472             vkEnc, VK_SUCCESS, device, pInfo, pHandle);
473 
474     return res;
475 }
476 
477 VKAPI_ATTR
ImportSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkImportSemaphoreZirconHandleInfoFUCHSIA * pInfo)478 VkResult ImportSemaphoreZirconHandleFUCHSIA(
479     VkDevice device,
480     const VkImportSemaphoreZirconHandleInfoFUCHSIA* pInfo) {
481     AEMU_SCOPED_TRACE("goldfish_vulkan::ImportSemaphoreZirconHandleFUCHSIA");
482 
483     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
484 
485     if (!hostSupportsVulkan) {
486         return vkstubhal::ImportSemaphoreZirconHandleFUCHSIA(device, pInfo);
487     }
488 
489     VkResult res = goldfish_vk::ResourceTracker::get()->
490         on_vkImportSemaphoreZirconHandleFUCHSIA(
491             vkEnc, VK_SUCCESS, device, pInfo);
492 
493     return res;
494 }
495 
496 VKAPI_ATTR
CreateBufferCollectionFUCHSIA(VkDevice device,const VkBufferCollectionCreateInfoFUCHSIA * pInfo,const VkAllocationCallbacks * pAllocator,VkBufferCollectionFUCHSIA * pCollection)497 VkResult CreateBufferCollectionFUCHSIA(
498     VkDevice device,
499     const VkBufferCollectionCreateInfoFUCHSIA* pInfo,
500     const VkAllocationCallbacks* pAllocator,
501     VkBufferCollectionFUCHSIA* pCollection) {
502     AEMU_SCOPED_TRACE("goldfish_vulkan::CreateBufferCollectionFUCHSIA");
503 
504     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
505 
506     if (!hostSupportsVulkan) {
507         return vkstubhal::CreateBufferCollectionFUCHSIA(device, pInfo, pAllocator, pCollection);
508     }
509 
510     VkResult res = goldfish_vk::ResourceTracker::get()->
511         on_vkCreateBufferCollectionFUCHSIA(
512             vkEnc, VK_SUCCESS, device, pInfo, pAllocator, pCollection);
513 
514     return res;
515 }
516 
517 VKAPI_ATTR
DestroyBufferCollectionFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkAllocationCallbacks * pAllocator)518 void DestroyBufferCollectionFUCHSIA(
519     VkDevice device,
520     VkBufferCollectionFUCHSIA collection,
521     const VkAllocationCallbacks* pAllocator) {
522     AEMU_SCOPED_TRACE("goldfish_vulkan::DestroyBufferCollectionFUCHSIA");
523 
524     VK_HOST_CONNECTION()
525 
526     if (!hostSupportsVulkan) {
527         vkstubhal::DestroyBufferCollectionFUCHSIA(device, collection, pAllocator);
528         return;
529     }
530 
531     goldfish_vk::ResourceTracker::get()->
532         on_vkDestroyBufferCollectionFUCHSIA(
533             vkEnc, VK_SUCCESS, device, collection, pAllocator);
534 }
535 
536 VKAPI_ATTR
SetBufferCollectionConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkImageCreateInfo * pImageInfo)537 VkResult SetBufferCollectionConstraintsFUCHSIA(
538     VkDevice device,
539     VkBufferCollectionFUCHSIA collection,
540     const VkImageCreateInfo* pImageInfo) {
541     AEMU_SCOPED_TRACE("goldfish_vulkan::SetBufferCollectionConstraintsFUCHSIA");
542 
543     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
544 
545     if (!hostSupportsVulkan) {
546         return vkstubhal::SetBufferCollectionConstraintsFUCHSIA(device, collection, pImageInfo);
547     }
548 
549     VkResult res = goldfish_vk::ResourceTracker::get()->
550         on_vkSetBufferCollectionConstraintsFUCHSIA(
551             vkEnc, VK_SUCCESS, device, collection, pImageInfo);
552 
553     return res;
554 }
555 
556 VKAPI_ATTR
GetBufferCollectionPropertiesFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,VkBufferCollectionPropertiesFUCHSIA * pProperties)557 VkResult GetBufferCollectionPropertiesFUCHSIA(
558     VkDevice device,
559     VkBufferCollectionFUCHSIA collection,
560     VkBufferCollectionPropertiesFUCHSIA* pProperties) {
561     AEMU_SCOPED_TRACE("goldfish_vulkan::GetBufferCollectionPropertiesFUCHSIA");
562 
563     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
564 
565     if (!hostSupportsVulkan) {
566         return vkstubhal::GetBufferCollectionPropertiesFUCHSIA(device, collection, pProperties);
567     }
568 
569     VkResult res = goldfish_vk::ResourceTracker::get()->
570         on_vkGetBufferCollectionPropertiesFUCHSIA(
571             vkEnc, VK_SUCCESS, device, collection, pProperties);
572 
573     return res;
574 }
575 #endif
576 
GetDeviceProcAddr(VkDevice device,const char * name)577 static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
578     AEMU_SCOPED_TRACE("goldfish_vulkan::GetDeviceProcAddr");
579 
580     VK_HOST_CONNECTION(nullptr)
581 
582     if (!hostSupportsVulkan) {
583         return nullptr;
584     }
585 
586 #ifdef VK_USE_PLATFORM_FUCHSIA
587     if (!strcmp(name, "vkGetMemoryZirconHandleFUCHSIA")) {
588         return (PFN_vkVoidFunction)GetMemoryZirconHandleFUCHSIA;
589     }
590     if (!strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) {
591         return (PFN_vkVoidFunction)GetMemoryZirconHandlePropertiesFUCHSIA;
592     }
593     if (!strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA")) {
594         return (PFN_vkVoidFunction)GetSemaphoreZirconHandleFUCHSIA;
595     }
596     if (!strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA")) {
597         return (PFN_vkVoidFunction)ImportSemaphoreZirconHandleFUCHSIA;
598     }
599     if (!strcmp(name, "vkCreateBufferCollectionFUCHSIA")) {
600         return (PFN_vkVoidFunction)CreateBufferCollectionFUCHSIA;
601     }
602     if (!strcmp(name, "vkDestroyBufferCollectionFUCHSIA")) {
603         return (PFN_vkVoidFunction)DestroyBufferCollectionFUCHSIA;
604     }
605     if (!strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA")) {
606         return (PFN_vkVoidFunction)SetBufferCollectionConstraintsFUCHSIA;
607     }
608     if (!strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA")) {
609         return (PFN_vkVoidFunction)GetBufferCollectionPropertiesFUCHSIA;
610     }
611 #endif
612     if (!strcmp(name, "vkGetDeviceProcAddr")) {
613         return (PFN_vkVoidFunction)(GetDeviceProcAddr);
614     }
615     return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_device_proc_address(device, name));
616 }
617 
618 VKAPI_ATTR
GetInstanceProcAddr(VkInstance instance,const char * name)619 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
620     AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
621 
622     VK_HOST_CONNECTION(nullptr)
623 
624     if (!hostSupportsVulkan) {
625         return vkstubhal::GetInstanceProcAddr(instance, name);
626     }
627 
628     if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
629         return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
630     }
631     if (!strcmp(name, "vkCreateInstance")) {
632         return (PFN_vkVoidFunction)CreateInstance;
633     }
634     if (!strcmp(name, "vkGetDeviceProcAddr")) {
635         return (PFN_vkVoidFunction)(GetDeviceProcAddr);
636     }
637     return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_instance_proc_address(instance, name));
638 }
639 
640 #ifdef VK_USE_PLATFORM_ANDROID_KHR
641 
642 hwvulkan_device_t goldfish_vulkan_device = {
643     .common = {
644         .tag = HARDWARE_DEVICE_TAG,
645         .version = HWVULKAN_DEVICE_API_VERSION_0_1,
646         .module = &HAL_MODULE_INFO_SYM.common,
647         .close = CloseDevice,
648     },
649     .EnumerateInstanceExtensionProperties = EnumerateInstanceExtensionProperties,
650     .CreateInstance = CreateInstance,
651     .GetInstanceProcAddr = GetInstanceProcAddr,
652 };
653 
OpenDevice(const hw_module_t *,const char * id,hw_device_t ** device)654 int OpenDevice(const hw_module_t* /*module*/,
655                const char* id,
656                hw_device_t** device) {
657     AEMU_SCOPED_TRACE("goldfish_vulkan::OpenDevice");
658 
659     if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
660         *device = &goldfish_vulkan_device.common;
661         goldfish_vk::ResourceTracker::get();
662         return 0;
663     }
664     return -ENOENT;
665 }
666 
667 #endif
668 
669 #ifdef VK_USE_PLATFORM_FUCHSIA
670 
671 class VulkanDevice {
672 public:
VulkanDevice()673     VulkanDevice() : mHostSupportsGoldfish(IsAccessible(QEMU_PIPE_PATH)) {
674         InitLogger();
675         goldfish_vk::ResourceTracker::get();
676     }
677 
678     static void InitLogger();
679 
IsAccessible(const char * name)680     static bool IsAccessible(const char* name) {
681         zx_handle_t handle = GetConnectToServiceFunction()(name);
682         if (handle == ZX_HANDLE_INVALID)
683             return false;
684 
685         zxio_storage_t io_storage;
686         zx_status_t status = zxio_remote_init(&io_storage, handle, ZX_HANDLE_INVALID);
687         if (status != ZX_OK)
688             return false;
689 
690         zxio_node_attr_t attr;
691         status = zxio_attr_get(&io_storage.io, &attr);
692         zxio_close(&io_storage.io);
693         if (status != ZX_OK)
694             return false;
695 
696         return true;
697     }
698 
GetInstance()699     static VulkanDevice& GetInstance() {
700         static VulkanDevice g_instance;
701         return g_instance;
702     }
703 
GetInstanceProcAddr(VkInstance instance,const char * name)704     PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
705         if (!mHostSupportsGoldfish) {
706             return vkstubhal::GetInstanceProcAddr(instance, name);
707         }
708         return ::GetInstanceProcAddr(instance, name);
709     }
710 
711 private:
712     const bool mHostSupportsGoldfish;
713 };
714 
InitLogger()715 void VulkanDevice::InitLogger() {
716    zx_handle_t channel = GetConnectToServiceFunction()("/svc/fuchsia.logger.LogSink");
717    if (channel == ZX_HANDLE_INVALID)
718       return;
719 
720   zx::socket local_socket, remote_socket;
721   zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local_socket, &remote_socket);
722   if (status != ZX_OK)
723     return;
724 
725   auto result = llcpp::fuchsia::logger::LogSink::Call::Connect(
726       zx::unowned_channel(channel), std::move(remote_socket));
727   zx_handle_close(channel);
728 
729   if (result.status() != ZX_OK)
730     return;
731 
732   fx_logger_config_t config = {.min_severity = FX_LOG_INFO,
733                                .console_fd = -1,
734                                .log_service_channel = local_socket.release(),
735                                .tags = nullptr,
736                                .num_tags = 0};
737 
738   fx_log_init_with_config(&config);
739 }
740 
741 extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction
vk_icdGetInstanceProcAddr(VkInstance instance,const char * name)742 vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) {
743     return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name);
744 }
745 
746 extern "C" __attribute__((visibility("default"))) VkResult
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)747 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
748     *pSupportedVersion = std::min(*pSupportedVersion, 3u);
749     return VK_SUCCESS;
750 }
751 
752 typedef VkResult(VKAPI_PTR *PFN_vkConnectToServiceAddr)(const char *pName, uint32_t handle);
753 
754 namespace {
755 
756 PFN_vkConnectToServiceAddr g_vulkan_connector;
757 
LocalConnectToServiceFunction(const char * pName)758 zx_handle_t LocalConnectToServiceFunction(const char* pName) {
759     zx::channel remote_endpoint, local_endpoint;
760     zx_status_t status;
761     if ((status = zx::channel::create(0, &remote_endpoint, &local_endpoint)) != ZX_OK) {
762         ALOGE("zx::channel::create failed: %d", status);
763         return ZX_HANDLE_INVALID;
764     }
765     if ((status = g_vulkan_connector(pName, remote_endpoint.release())) != ZX_OK) {
766         ALOGE("vulkan_connector failed: %d", status);
767         return ZX_HANDLE_INVALID;
768     }
769     return local_endpoint.release();
770 }
771 
772 }
773 
774 extern "C" __attribute__((visibility("default"))) void
vk_icdInitializeConnectToServiceCallback(PFN_vkConnectToServiceAddr callback)775 vk_icdInitializeConnectToServiceCallback(PFN_vkConnectToServiceAddr callback) {
776     g_vulkan_connector = callback;
777     SetConnectToServiceFunction(&LocalConnectToServiceFunction);
778 }
779 
780 #endif
781 
782 } // namespace
783