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 
SetBufferCollectionBufferConstraintsFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkBufferConstraintsInfoFUCHSIA *)224 VkResult SetBufferCollectionBufferConstraintsFUCHSIA(
225     VkDevice /*device*/,
226     VkBufferCollectionFUCHSIA /*collection*/,
227     const VkBufferConstraintsInfoFUCHSIA* /*pBufferConstraintsInfo*/) {
228     AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionBufferConstraintsFUCHSIA");
229     return VK_SUCCESS;
230 }
231 
232 VkResult
GetBufferCollectionPropertiesFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,VkBufferCollectionPropertiesFUCHSIA *)233 GetBufferCollectionPropertiesFUCHSIA(VkDevice /*device*/,
234                                      VkBufferCollectionFUCHSIA /*collection*/,
235                                      VkBufferCollectionPropertiesFUCHSIA* /*pProperties*/) {
236     AEMU_SCOPED_TRACE("vkstubhal::GetBufferCollectionPropertiesFUCHSIA");
237     return VK_SUCCESS;
238 }
239 #endif
240 
GetInstanceProcAddr(VkInstance instance,const char * name)241 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
242                                        const char* name) {
243     AEMU_SCOPED_TRACE("vkstubhal::GetInstanceProcAddr");
244     if (strcmp(name, "vkCreateInstance") == 0)
245         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
246     if (strcmp(name, "vkDestroyInstance") == 0)
247         return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
248     if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
249         return reinterpret_cast<PFN_vkVoidFunction>(
250             EnumerateInstanceExtensionProperties);
251     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
252         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
253     if (strcmp(name, "vkEnumerateInstanceVersion") == 0)
254         return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
255     if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
256         return reinterpret_cast<PFN_vkVoidFunction>(
257             EnumeratePhysicalDeviceGroups);
258     if (strcmp(name, "vkEnumeratePhysicalDeviceGroupsKHR") == 0)
259         return reinterpret_cast<PFN_vkVoidFunction>(
260             EnumeratePhysicalDeviceGroups);
261     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
262         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
263     if (strcmp(name, "vkCreateDebugReportCallbackEXT") == 0)
264         return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT);
265     if (strcmp(name, "vkDestroyDebugReportCallbackEXT") == 0)
266         return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT);
267     if (strcmp(name, "vkDebugReportMessageEXT") == 0)
268         return reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT);
269     if (strcmp(name, "vkCreateDebugUtilsMessengerEXT") == 0)
270         return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugUtilsMessengerEXT);
271     if (strcmp(name, "vkDestroyDebugUtilsMessengerEXT") == 0)
272         return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugUtilsMessengerEXT);
273     if (strcmp(name, "vkSubmitDebugUtilsMessageEXT") == 0)
274         return reinterpret_cast<PFN_vkVoidFunction>(SubmitDebugUtilsMessageEXT);
275 #ifdef VK_USE_PLATFORM_FUCHSIA
276     if (strcmp(name, "vkGetMemoryZirconHandleFUCHSIA") == 0)
277         return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandleFUCHSIA);
278     if (strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA") == 0)
279         return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandlePropertiesFUCHSIA);
280     if (strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA") == 0)
281         return reinterpret_cast<PFN_vkVoidFunction>(GetSemaphoreZirconHandleFUCHSIA);
282     if (strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA") == 0)
283         return reinterpret_cast<PFN_vkVoidFunction>(ImportSemaphoreZirconHandleFUCHSIA);
284     if (strcmp(name, "vkCreateBufferCollectionFUCHSIA") == 0)
285         return reinterpret_cast<PFN_vkVoidFunction>(CreateBufferCollectionFUCHSIA);
286     if (strcmp(name, "vkDestroyBufferCollectionFUCHSIA") == 0)
287         return reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferCollectionFUCHSIA);
288     if (strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA") == 0)
289         return reinterpret_cast<PFN_vkVoidFunction>(SetBufferCollectionConstraintsFUCHSIA);
290     if (strcmp(name, "vkSetBufferCollectionBufferConstraintsFUCHSIA") == 0)
291         return reinterpret_cast<PFN_vkVoidFunction>(SetBufferCollectionBufferConstraintsFUCHSIA);
292     if (strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA") == 0)
293         return reinterpret_cast<PFN_vkVoidFunction>(GetBufferCollectionPropertiesFUCHSIA);
294 #endif
295     // Return NoOp for entrypoints that should never be called.
296     if (strcmp(name, "vkGetPhysicalDeviceFeatures") == 0 ||
297         strcmp(name, "vkGetPhysicalDeviceProperties") == 0 ||
298         strcmp(name, "vkGetPhysicalDeviceFormatProperties") == 0 ||
299         strcmp(name, "vkGetPhysicalDeviceImageFormatProperties") == 0 ||
300         strcmp(name, "vkGetPhysicalDeviceMemoryProperties") == 0 ||
301         strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties") == 0 ||
302         strcmp(name, "vkGetDeviceProcAddr") == 0 ||
303         strcmp(name, "vkCreateDevice") == 0 ||
304         strcmp(name, "vkEnumerateDeviceExtensionProperties") == 0 ||
305         strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties") == 0 ||
306         strcmp(name, "vkGetPhysicalDeviceFeatures2") == 0 ||
307         strcmp(name, "vkGetPhysicalDeviceProperties2") == 0 ||
308         strcmp(name, "vkGetPhysicalDeviceFormatProperties2") == 0 ||
309         strcmp(name, "vkGetPhysicalDeviceImageFormatProperties2") == 0 ||
310         strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties2") == 0 ||
311         strcmp(name, "vkGetPhysicalDeviceMemoryProperties2") == 0 ||
312         strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties2") == 0 ||
313         strcmp(name, "vkGetPhysicalDeviceExternalBufferProperties") == 0 ||
314         strcmp(name, "vkGetPhysicalDeviceExternalFenceProperties") == 0 ||
315         strcmp(name, "vkGetPhysicalDeviceExternalSemaphoreProperties") == 0)
316         return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
317 
318     // Per the spec, return NULL for nonexistent entrypoints.
319     return nullptr;
320 }
321 
322 } // namespace vkstubhal
323 
324 namespace {
325 
326 #ifdef VK_USE_PLATFORM_ANDROID_KHR
327 
328 int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
329 
330 hw_module_methods_t goldfish_vulkan_module_methods = {
331     .open = OpenDevice
332 };
333 
334 extern "C" __attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
335     .common = {
336         .tag = HARDWARE_MODULE_TAG,
337         .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
338         .hal_api_version = HARDWARE_HAL_API_VERSION,
339         .id = HWVULKAN_HARDWARE_MODULE_ID,
340         .name = "Goldfish Vulkan Driver",
341         .author = "The Android Open Source Project",
342         .methods = &goldfish_vulkan_module_methods,
343     },
344 };
345 
CloseDevice(struct hw_device_t *)346 int CloseDevice(struct hw_device_t* /*device*/) {
347     AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
348     // nothing to do - opening a device doesn't allocate any resources
349     return 0;
350 }
351 
352 #endif
353 
354 #define VK_HOST_CONNECTION(ret) \
355     HostConnection *hostCon = HostConnection::get(); \
356     if (!hostCon) { \
357         ALOGE("vulkan: Failed to get host connection\n"); \
358         return ret; \
359     } \
360     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
361     if (!rcEnc) { \
362         ALOGE("vulkan: Failed to get renderControl encoder context\n"); \
363         return ret; \
364     } \
365     goldfish_vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const()); \
366     goldfish_vk::ResourceTracker::ThreadingCallbacks threadingCallbacks = { \
367         [] { \
368           auto hostCon = HostConnection::get(); \
369           hostCon->rcEncoder(); \
370           return hostCon; \
371         }, \
372         [](HostConnection* hostCon) { return hostCon->vkEncoder(); }, \
373     }; \
374     goldfish_vk::ResourceTracker::get()->setThreadingCallbacks(threadingCallbacks); \
375     auto hostSupportsVulkan = goldfish_vk::ResourceTracker::get()->hostSupportsVulkan(); \
376     goldfish_vk::VkEncoder *vkEnc = hostCon->vkEncoder(); \
377     if (!vkEnc) { \
378         ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
379         return ret; \
380     } \
381 
382 VKAPI_ATTR
EnumerateInstanceExtensionProperties(const char * layer_name,uint32_t * count,VkExtensionProperties * properties)383 VkResult EnumerateInstanceExtensionProperties(
384     const char* layer_name,
385     uint32_t* count,
386     VkExtensionProperties* properties) {
387     AEMU_SCOPED_TRACE("goldfish_vulkan::EnumerateInstanceExtensionProperties");
388 
389     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
390 
391     if (!hostSupportsVulkan) {
392         return vkstubhal::EnumerateInstanceExtensionProperties(layer_name, count, properties);
393     }
394 
395     if (layer_name) {
396         ALOGW(
397             "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
398             "with a layer name ('%s')",
399             layer_name);
400     }
401 
402     VkResult res = goldfish_vk::ResourceTracker::get()->on_vkEnumerateInstanceExtensionProperties(
403         vkEnc, VK_SUCCESS, layer_name, count, properties);
404 
405     return res;
406 }
407 
408 VKAPI_ATTR
CreateInstance(const VkInstanceCreateInfo * create_info,const VkAllocationCallbacks * allocator,VkInstance * out_instance)409 VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
410                         const VkAllocationCallbacks* allocator,
411                         VkInstance* out_instance) {
412     AEMU_SCOPED_TRACE("goldfish_vulkan::CreateInstance");
413 
414     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
415 
416     if (!hostSupportsVulkan) {
417         return vkstubhal::CreateInstance(create_info, allocator, out_instance);
418     }
419 
420     VkResult res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance);
421 
422     return res;
423 }
424 
425 #ifdef VK_USE_PLATFORM_FUCHSIA
426 VKAPI_ATTR
GetMemoryZirconHandleFUCHSIA(VkDevice device,const VkMemoryGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)427 VkResult GetMemoryZirconHandleFUCHSIA(
428     VkDevice device,
429     const VkMemoryGetZirconHandleInfoFUCHSIA* pInfo,
430     uint32_t* pHandle) {
431     AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandleFUCHSIA");
432 
433     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
434 
435     if (!hostSupportsVulkan) {
436         return vkstubhal::GetMemoryZirconHandleFUCHSIA(device, pInfo, pHandle);
437     }
438 
439     VkResult res = goldfish_vk::ResourceTracker::get()->
440         on_vkGetMemoryZirconHandleFUCHSIA(
441             vkEnc, VK_SUCCESS,
442             device, pInfo, pHandle);
443 
444     return res;
445 }
446 
447 VKAPI_ATTR
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice device,VkExternalMemoryHandleTypeFlagBits handleType,uint32_t handle,VkMemoryZirconHandlePropertiesFUCHSIA * pProperties)448 VkResult GetMemoryZirconHandlePropertiesFUCHSIA(
449     VkDevice device,
450     VkExternalMemoryHandleTypeFlagBits handleType,
451     uint32_t handle,
452     VkMemoryZirconHandlePropertiesFUCHSIA* pProperties) {
453     AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandlePropertiesFUCHSIA");
454 
455     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
456 
457     if (!hostSupportsVulkan) {
458         return vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA(
459             device, handleType, handle, pProperties);
460     }
461 
462     VkResult res = goldfish_vk::ResourceTracker::get()->
463         on_vkGetMemoryZirconHandlePropertiesFUCHSIA(
464             vkEnc, VK_SUCCESS, device, handleType, handle, pProperties);
465 
466     return res;
467 }
468 
469 VKAPI_ATTR
GetSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkSemaphoreGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)470 VkResult GetSemaphoreZirconHandleFUCHSIA(
471     VkDevice device,
472     const VkSemaphoreGetZirconHandleInfoFUCHSIA* pInfo,
473     uint32_t* pHandle) {
474     AEMU_SCOPED_TRACE("goldfish_vulkan::GetSemaphoreZirconHandleFUCHSIA");
475 
476     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
477 
478     if (!hostSupportsVulkan) {
479         return vkstubhal::GetSemaphoreZirconHandleFUCHSIA(device, pInfo, pHandle);
480     }
481 
482     VkResult res = goldfish_vk::ResourceTracker::get()->
483         on_vkGetSemaphoreZirconHandleFUCHSIA(
484             vkEnc, VK_SUCCESS, device, pInfo, pHandle);
485 
486     return res;
487 }
488 
489 VKAPI_ATTR
ImportSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkImportSemaphoreZirconHandleInfoFUCHSIA * pInfo)490 VkResult ImportSemaphoreZirconHandleFUCHSIA(
491     VkDevice device,
492     const VkImportSemaphoreZirconHandleInfoFUCHSIA* pInfo) {
493     AEMU_SCOPED_TRACE("goldfish_vulkan::ImportSemaphoreZirconHandleFUCHSIA");
494 
495     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
496 
497     if (!hostSupportsVulkan) {
498         return vkstubhal::ImportSemaphoreZirconHandleFUCHSIA(device, pInfo);
499     }
500 
501     VkResult res = goldfish_vk::ResourceTracker::get()->
502         on_vkImportSemaphoreZirconHandleFUCHSIA(
503             vkEnc, VK_SUCCESS, device, pInfo);
504 
505     return res;
506 }
507 
508 VKAPI_ATTR
CreateBufferCollectionFUCHSIA(VkDevice device,const VkBufferCollectionCreateInfoFUCHSIA * pInfo,const VkAllocationCallbacks * pAllocator,VkBufferCollectionFUCHSIA * pCollection)509 VkResult CreateBufferCollectionFUCHSIA(
510     VkDevice device,
511     const VkBufferCollectionCreateInfoFUCHSIA* pInfo,
512     const VkAllocationCallbacks* pAllocator,
513     VkBufferCollectionFUCHSIA* pCollection) {
514     AEMU_SCOPED_TRACE("goldfish_vulkan::CreateBufferCollectionFUCHSIA");
515 
516     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
517 
518     if (!hostSupportsVulkan) {
519         return vkstubhal::CreateBufferCollectionFUCHSIA(device, pInfo, pAllocator, pCollection);
520     }
521 
522     VkResult res = goldfish_vk::ResourceTracker::get()->
523         on_vkCreateBufferCollectionFUCHSIA(
524             vkEnc, VK_SUCCESS, device, pInfo, pAllocator, pCollection);
525 
526     return res;
527 }
528 
529 VKAPI_ATTR
DestroyBufferCollectionFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkAllocationCallbacks * pAllocator)530 void DestroyBufferCollectionFUCHSIA(
531     VkDevice device,
532     VkBufferCollectionFUCHSIA collection,
533     const VkAllocationCallbacks* pAllocator) {
534     AEMU_SCOPED_TRACE("goldfish_vulkan::DestroyBufferCollectionFUCHSIA");
535 
536     VK_HOST_CONNECTION()
537 
538     if (!hostSupportsVulkan) {
539         vkstubhal::DestroyBufferCollectionFUCHSIA(device, collection, pAllocator);
540         return;
541     }
542 
543     goldfish_vk::ResourceTracker::get()->
544         on_vkDestroyBufferCollectionFUCHSIA(
545             vkEnc, VK_SUCCESS, device, collection, pAllocator);
546 }
547 
548 VKAPI_ATTR
SetBufferCollectionConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkImageCreateInfo * pImageInfo)549 VkResult SetBufferCollectionConstraintsFUCHSIA(
550     VkDevice device,
551     VkBufferCollectionFUCHSIA collection,
552     const VkImageCreateInfo* pImageInfo) {
553     AEMU_SCOPED_TRACE("goldfish_vulkan::SetBufferCollectionConstraintsFUCHSIA");
554 
555     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
556 
557     if (!hostSupportsVulkan) {
558         return vkstubhal::SetBufferCollectionConstraintsFUCHSIA(device, collection, pImageInfo);
559     }
560 
561     VkResult res = goldfish_vk::ResourceTracker::get()->
562         on_vkSetBufferCollectionConstraintsFUCHSIA(
563             vkEnc, VK_SUCCESS, device, collection, pImageInfo);
564 
565     return res;
566 }
567 
568 VKAPI_ATTR
SetBufferCollectionBufferConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkBufferConstraintsInfoFUCHSIA * pBufferConstraintsInfo)569 VkResult SetBufferCollectionBufferConstraintsFUCHSIA(
570     VkDevice device,
571     VkBufferCollectionFUCHSIA collection,
572     const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo) {
573     AEMU_SCOPED_TRACE("goldfish_vulkan::SetBufferCollectionBufferConstraintsFUCHSIA");
574 
575     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
576 
577     if (!hostSupportsVulkan) {
578         return vkstubhal::SetBufferCollectionBufferConstraintsFUCHSIA(device, collection,
579                                                                       pBufferConstraintsInfo);
580     }
581 
582     VkResult res =
583         goldfish_vk::ResourceTracker::get()->on_vkSetBufferCollectionBufferConstraintsFUCHSIA(
584             vkEnc, VK_SUCCESS, device, collection, pBufferConstraintsInfo);
585 
586     return res;
587 }
588 
589 VKAPI_ATTR
GetBufferCollectionPropertiesFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,VkBufferCollectionPropertiesFUCHSIA * pProperties)590 VkResult GetBufferCollectionPropertiesFUCHSIA(
591     VkDevice device,
592     VkBufferCollectionFUCHSIA collection,
593     VkBufferCollectionPropertiesFUCHSIA* pProperties) {
594     AEMU_SCOPED_TRACE("goldfish_vulkan::GetBufferCollectionPropertiesFUCHSIA");
595 
596     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
597 
598     if (!hostSupportsVulkan) {
599         return vkstubhal::GetBufferCollectionPropertiesFUCHSIA(device, collection, pProperties);
600     }
601 
602     VkResult res = goldfish_vk::ResourceTracker::get()->
603         on_vkGetBufferCollectionPropertiesFUCHSIA(
604             vkEnc, VK_SUCCESS, device, collection, pProperties);
605 
606     return res;
607 }
608 #endif
609 
GetDeviceProcAddr(VkDevice device,const char * name)610 static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
611     AEMU_SCOPED_TRACE("goldfish_vulkan::GetDeviceProcAddr");
612 
613     VK_HOST_CONNECTION(nullptr)
614 
615     if (!hostSupportsVulkan) {
616         return nullptr;
617     }
618 
619 #ifdef VK_USE_PLATFORM_FUCHSIA
620     if (!strcmp(name, "vkGetMemoryZirconHandleFUCHSIA")) {
621         return (PFN_vkVoidFunction)GetMemoryZirconHandleFUCHSIA;
622     }
623     if (!strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) {
624         return (PFN_vkVoidFunction)GetMemoryZirconHandlePropertiesFUCHSIA;
625     }
626     if (!strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA")) {
627         return (PFN_vkVoidFunction)GetSemaphoreZirconHandleFUCHSIA;
628     }
629     if (!strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA")) {
630         return (PFN_vkVoidFunction)ImportSemaphoreZirconHandleFUCHSIA;
631     }
632     if (!strcmp(name, "vkCreateBufferCollectionFUCHSIA")) {
633         return (PFN_vkVoidFunction)CreateBufferCollectionFUCHSIA;
634     }
635     if (!strcmp(name, "vkDestroyBufferCollectionFUCHSIA")) {
636         return (PFN_vkVoidFunction)DestroyBufferCollectionFUCHSIA;
637     }
638     if (!strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA")) {
639         return (PFN_vkVoidFunction)SetBufferCollectionConstraintsFUCHSIA;
640     }
641     if (!strcmp(name, "vkSetBufferCollectionBufferConstraintsFUCHSIA")) {
642         return (PFN_vkVoidFunction)SetBufferCollectionBufferConstraintsFUCHSIA;
643     }
644     if (!strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA")) {
645         return (PFN_vkVoidFunction)GetBufferCollectionPropertiesFUCHSIA;
646     }
647 #endif
648     if (!strcmp(name, "vkGetDeviceProcAddr")) {
649         return (PFN_vkVoidFunction)(GetDeviceProcAddr);
650     }
651     return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_device_proc_address(device, name));
652 }
653 
654 VKAPI_ATTR
GetInstanceProcAddr(VkInstance instance,const char * name)655 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
656     AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
657 
658     VK_HOST_CONNECTION(nullptr)
659 
660     if (!hostSupportsVulkan) {
661         return vkstubhal::GetInstanceProcAddr(instance, name);
662     }
663 
664     if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
665         return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
666     }
667     if (!strcmp(name, "vkCreateInstance")) {
668         return (PFN_vkVoidFunction)CreateInstance;
669     }
670     if (!strcmp(name, "vkGetDeviceProcAddr")) {
671         return (PFN_vkVoidFunction)(GetDeviceProcAddr);
672     }
673     return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_instance_proc_address(instance, name));
674 }
675 
676 #ifdef VK_USE_PLATFORM_ANDROID_KHR
677 
678 hwvulkan_device_t goldfish_vulkan_device = {
679     .common = {
680         .tag = HARDWARE_DEVICE_TAG,
681         .version = HWVULKAN_DEVICE_API_VERSION_0_1,
682         .module = &HAL_MODULE_INFO_SYM.common,
683         .close = CloseDevice,
684     },
685     .EnumerateInstanceExtensionProperties = EnumerateInstanceExtensionProperties,
686     .CreateInstance = CreateInstance,
687     .GetInstanceProcAddr = GetInstanceProcAddr,
688 };
689 
OpenDevice(const hw_module_t *,const char * id,hw_device_t ** device)690 int OpenDevice(const hw_module_t* /*module*/,
691                const char* id,
692                hw_device_t** device) {
693     AEMU_SCOPED_TRACE("goldfish_vulkan::OpenDevice");
694 
695     if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
696         *device = &goldfish_vulkan_device.common;
697         goldfish_vk::ResourceTracker::get();
698         return 0;
699     }
700     return -ENOENT;
701 }
702 
703 #endif
704 
705 #ifdef VK_USE_PLATFORM_FUCHSIA
706 
707 class VulkanDevice {
708 public:
VulkanDevice()709     VulkanDevice() : mHostSupportsGoldfish(IsAccessible(QEMU_PIPE_PATH)) {
710         InitLogger();
711         goldfish_vk::ResourceTracker::get();
712     }
713 
714     static void InitLogger();
715 
IsAccessible(const char * name)716     static bool IsAccessible(const char* name) {
717         zx_handle_t handle = GetConnectToServiceFunction()(name);
718         if (handle == ZX_HANDLE_INVALID)
719             return false;
720 
721         zxio_storage_t io_storage;
722         zx_status_t status = zxio_remote_init(&io_storage, handle, ZX_HANDLE_INVALID);
723         if (status != ZX_OK)
724             return false;
725 
726         zxio_node_attributes_t attr;
727         status = zxio_attr_get(&io_storage.io, &attr);
728         zxio_close(&io_storage.io);
729         if (status != ZX_OK)
730             return false;
731 
732         return true;
733     }
734 
GetInstance()735     static VulkanDevice& GetInstance() {
736         static VulkanDevice g_instance;
737         return g_instance;
738     }
739 
GetInstanceProcAddr(VkInstance instance,const char * name)740     PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
741         if (!mHostSupportsGoldfish) {
742             return vkstubhal::GetInstanceProcAddr(instance, name);
743         }
744         return ::GetInstanceProcAddr(instance, name);
745     }
746 
747 private:
748     const bool mHostSupportsGoldfish;
749 };
750 
InitLogger()751 void VulkanDevice::InitLogger() {
752    zx_handle_t channel = GetConnectToServiceFunction()("/svc/fuchsia.logger.LogSink");
753    if (channel == ZX_HANDLE_INVALID)
754       return;
755 
756   zx::socket local_socket, remote_socket;
757   zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local_socket, &remote_socket);
758   if (status != ZX_OK)
759     return;
760 
761   auto result = llcpp::fuchsia::logger::LogSink::Call::Connect(
762       zx::unowned_channel(channel), std::move(remote_socket));
763   zx_handle_close(channel);
764 
765   if (result.status() != ZX_OK)
766     return;
767 
768   fx_logger_config_t config = {.min_severity = FX_LOG_INFO,
769                                .console_fd = -1,
770                                .log_service_channel = local_socket.release(),
771                                .tags = nullptr,
772                                .num_tags = 0};
773 
774   fx_log_reconfigure(&config);
775 }
776 
777 extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction
vk_icdGetInstanceProcAddr(VkInstance instance,const char * name)778 vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) {
779     return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name);
780 }
781 
782 extern "C" __attribute__((visibility("default"))) VkResult
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)783 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
784     *pSupportedVersion = std::min(*pSupportedVersion, 3u);
785     return VK_SUCCESS;
786 }
787 
788 typedef VkResult(VKAPI_PTR *PFN_vkConnectToServiceAddr)(const char *pName, uint32_t handle);
789 
790 namespace {
791 
792 PFN_vkConnectToServiceAddr g_vulkan_connector;
793 
LocalConnectToServiceFunction(const char * pName)794 zx_handle_t LocalConnectToServiceFunction(const char* pName) {
795     zx::channel remote_endpoint, local_endpoint;
796     zx_status_t status;
797     if ((status = zx::channel::create(0, &remote_endpoint, &local_endpoint)) != ZX_OK) {
798         ALOGE("zx::channel::create failed: %d", status);
799         return ZX_HANDLE_INVALID;
800     }
801     if ((status = g_vulkan_connector(pName, remote_endpoint.release())) != ZX_OK) {
802         ALOGE("vulkan_connector failed: %d", status);
803         return ZX_HANDLE_INVALID;
804     }
805     return local_endpoint.release();
806 }
807 
808 }
809 
810 extern "C" __attribute__((visibility("default"))) void
vk_icdInitializeConnectToServiceCallback(PFN_vkConnectToServiceAddr callback)811 vk_icdInitializeConnectToServiceCallback(PFN_vkConnectToServiceAddr callback) {
812     g_vulkan_connector = callback;
813     SetConnectToServiceFunction(&LocalConnectToServiceFunction);
814 }
815 
816 #endif
817 
818 } // namespace
819