• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 #include "HostConnection.h"
22 #include "ResourceTracker.h"
23 #include "VkEncoder.h"
24 
25 #include "func_table.h"
26 
27 #include <array>
28 #include <bitset>
29 #include <mutex>
30 
31 // Used when there is no Vulkan support on the host.
32 // Copied from frameworks/native/vulkan/libvulkan/stubhal.cpp
33 namespace vkstubhal {
34 
35 const size_t kMaxInstances = 32;
36 static std::mutex g_instance_mutex;
37 static std::bitset<kMaxInstances> g_instance_used(false);
38 static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
39 
NoOp()40 [[noreturn]] VKAPI_ATTR void NoOp() {
41     LOG_ALWAYS_FATAL("invalid stub function called");
42 }
43 
44 VkResult
EnumerateInstanceExtensionProperties(const char *,uint32_t * count,VkExtensionProperties *)45 EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
46                                      uint32_t* count,
47                                      VkExtensionProperties* /*properties*/) {
48     AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceExtensionProperties");
49     *count = 0;
50     return VK_SUCCESS;
51 }
52 
53 VkResult
EnumerateInstanceLayerProperties(uint32_t * count,VkLayerProperties *)54 EnumerateInstanceLayerProperties(uint32_t* count,
55                                  VkLayerProperties* /*properties*/) {
56     AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceLayerProperties");
57     *count = 0;
58     return VK_SUCCESS;
59 }
60 
CreateInstance(const VkInstanceCreateInfo *,const VkAllocationCallbacks *,VkInstance * instance)61 VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
62                         const VkAllocationCallbacks* /*allocator*/,
63                         VkInstance* instance) {
64     AEMU_SCOPED_TRACE("vkstubhal::CreateInstance");
65     std::lock_guard<std::mutex> lock(g_instance_mutex);
66     for (size_t i = 0; i < kMaxInstances; i++) {
67         if (!g_instance_used[i]) {
68             g_instance_used[i] = true;
69             g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
70             *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
71             return VK_SUCCESS;
72         }
73     }
74     ALOGE("no more instances available (max=%zu)", kMaxInstances);
75     return VK_ERROR_INITIALIZATION_FAILED;
76 }
77 
DestroyInstance(VkInstance instance,const VkAllocationCallbacks *)78 void DestroyInstance(VkInstance instance,
79                      const VkAllocationCallbacks* /*allocator*/) {
80     AEMU_SCOPED_TRACE("vkstubhal::DestroyInstance");
81     std::lock_guard<std::mutex> lock(g_instance_mutex);
82     ssize_t idx =
83         reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
84     ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
85                 "DestroyInstance: invalid instance handle");
86     g_instance_used[static_cast<size_t>(idx)] = false;
87 }
88 
EnumeratePhysicalDevices(VkInstance,uint32_t * count,VkPhysicalDevice *)89 VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
90                                   uint32_t* count,
91                                   VkPhysicalDevice* /*gpus*/) {
92     AEMU_SCOPED_TRACE("vkstubhal::EnumeratePhysicalDevices");
93     *count = 0;
94     return VK_SUCCESS;
95 }
96 
97 VkResult
EnumeratePhysicalDeviceGroups(VkInstance,uint32_t * count,VkPhysicalDeviceGroupProperties *)98 EnumeratePhysicalDeviceGroups(VkInstance /*instance*/,
99                               uint32_t* count,
100                               VkPhysicalDeviceGroupProperties* /*properties*/) {
101     AEMU_SCOPED_TRACE("vkstubhal::EnumeratePhysicalDeviceGroups");
102     *count = 0;
103     return VK_SUCCESS;
104 }
105 
106 #ifdef VK_USE_PLATFORM_FUCHSIA
107 VkResult
GetMemoryZirconHandleFUCHSIA(VkDevice,const VkMemoryGetZirconHandleInfoFUCHSIA *,uint32_t * pHandle)108 GetMemoryZirconHandleFUCHSIA(VkDevice /*device*/,
109                              const VkMemoryGetZirconHandleInfoFUCHSIA* /*pInfo*/,
110                              uint32_t* pHandle) {
111     AEMU_SCOPED_TRACE("vkstubhal::GetMemoryZirconHandleFUCHSIA");
112     *pHandle = 0;
113     return VK_SUCCESS;
114 }
115 
116 VkResult
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice,VkExternalMemoryHandleTypeFlagBits,uint32_t,VkMemoryZirconHandlePropertiesFUCHSIA *)117 GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice /*device*/,
118                                        VkExternalMemoryHandleTypeFlagBits /*handleType*/,
119                                        uint32_t /*handle*/,
120                                        VkMemoryZirconHandlePropertiesFUCHSIA* /*pProperties*/) {
121     AEMU_SCOPED_TRACE("vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA");
122     return VK_SUCCESS;
123 }
124 
125 VkResult
GetSemaphoreZirconHandleFUCHSIA(VkDevice,const VkSemaphoreGetZirconHandleInfoFUCHSIA *,uint32_t * pHandle)126 GetSemaphoreZirconHandleFUCHSIA(VkDevice /*device*/,
127                                 const VkSemaphoreGetZirconHandleInfoFUCHSIA* /*pInfo*/,
128                                 uint32_t* pHandle) {
129     AEMU_SCOPED_TRACE("vkstubhal::GetSemaphoreZirconHandleFUCHSIA");
130     *pHandle = 0;
131     return VK_SUCCESS;
132 }
133 
134 VkResult
ImportSemaphoreZirconHandleFUCHSIA(VkDevice,const VkImportSemaphoreZirconHandleInfoFUCHSIA *)135 ImportSemaphoreZirconHandleFUCHSIA(VkDevice /*device*/,
136                                    const VkImportSemaphoreZirconHandleInfoFUCHSIA* /*pInfo*/) {
137     AEMU_SCOPED_TRACE("vkstubhal::ImportSemaphoreZirconHandleFUCHSIA");
138     return VK_SUCCESS;
139 }
140 
141 VkResult
CreateBufferCollectionFUCHSIA(VkDevice,const VkBufferCollectionCreateInfoFUCHSIA *,const VkAllocationCallbacks *,VkBufferCollectionFUCHSIA *)142 CreateBufferCollectionFUCHSIA(VkDevice /*device*/,
143                               const VkBufferCollectionCreateInfoFUCHSIA* /*pInfo*/,
144                               const VkAllocationCallbacks* /*pAllocator*/,
145                               VkBufferCollectionFUCHSIA* /*pCollection*/) {
146     AEMU_SCOPED_TRACE("vkstubhal::CreateBufferCollectionFUCHSIA");
147     return VK_SUCCESS;
148 }
149 
150 void
DestroyBufferCollectionFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkAllocationCallbacks *)151 DestroyBufferCollectionFUCHSIA(VkDevice /*device*/,
152                                VkBufferCollectionFUCHSIA /*collection*/,
153                                const VkAllocationCallbacks* /*pAllocator*/) {
154     AEMU_SCOPED_TRACE("vkstubhal::DestroyBufferCollectionFUCHSIA");
155 }
156 
157 VkResult
SetBufferCollectionConstraintsFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkImageCreateInfo *)158 SetBufferCollectionConstraintsFUCHSIA(VkDevice /*device*/,
159                                       VkBufferCollectionFUCHSIA /*collection*/,
160                                       const VkImageCreateInfo* /*pImageInfo*/) {
161     AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionConstraintsFUCHSIA");
162     return VK_SUCCESS;
163 }
164 
165 VkResult
GetBufferCollectionPropertiesFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,VkBufferCollectionPropertiesFUCHSIA *)166 GetBufferCollectionPropertiesFUCHSIA(VkDevice /*device*/,
167                                      VkBufferCollectionFUCHSIA /*collection*/,
168                                      VkBufferCollectionPropertiesFUCHSIA* /*pProperties*/) {
169     AEMU_SCOPED_TRACE("vkstubhal::GetBufferCollectionPropertiesFUCHSIA");
170     return VK_SUCCESS;
171 }
172 #endif
173 
GetInstanceProcAddr(VkInstance instance,const char * name)174 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
175                                        const char* name) {
176     AEMU_SCOPED_TRACE("vkstubhal::GetInstanceProcAddr");
177     if (strcmp(name, "vkCreateInstance") == 0)
178         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
179     if (strcmp(name, "vkDestroyInstance") == 0)
180         return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
181     if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
182         return reinterpret_cast<PFN_vkVoidFunction>(
183             EnumerateInstanceExtensionProperties);
184     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
185         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
186     if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
187         return reinterpret_cast<PFN_vkVoidFunction>(
188             EnumeratePhysicalDeviceGroups);
189     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
190         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
191 #ifdef VK_USE_PLATFORM_FUCHSIA
192     if (strcmp(name, "vkGetMemoryZirconHandleFUCHSIA") == 0)
193         return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandleFUCHSIA);
194     if (strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA") == 0)
195         return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandlePropertiesFUCHSIA);
196     if (strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA") == 0)
197         return reinterpret_cast<PFN_vkVoidFunction>(GetSemaphoreZirconHandleFUCHSIA);
198     if (strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA") == 0)
199         return reinterpret_cast<PFN_vkVoidFunction>(ImportSemaphoreZirconHandleFUCHSIA);
200     if (strcmp(name, "vkCreateBufferCollectionFUCHSIA") == 0)
201         return reinterpret_cast<PFN_vkVoidFunction>(CreateBufferCollectionFUCHSIA);
202     if (strcmp(name, "vkDestroyBufferCollectionFUCHSIA") == 0)
203         return reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferCollectionFUCHSIA);
204     if (strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA") == 0)
205         return reinterpret_cast<PFN_vkVoidFunction>(SetBufferCollectionConstraintsFUCHSIA);
206     if (strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA") == 0)
207         return reinterpret_cast<PFN_vkVoidFunction>(GetBufferCollectionPropertiesFUCHSIA);
208 #endif
209     // Per the spec, return NULL if instance is NULL.
210     if (!instance)
211         return nullptr;
212     // None of the other Vulkan functions should ever be called, as they all
213     // take a VkPhysicalDevice or other object obtained from a physical device.
214     return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
215 }
216 
217 } // namespace vkstubhal
218 
219 namespace {
220 
221 #ifdef VK_USE_PLATFORM_ANDROID_KHR
222 
223 int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
224 
225 hw_module_methods_t goldfish_vulkan_module_methods = {
226     .open = OpenDevice
227 };
228 
229 extern "C" __attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
230     .common = {
231         .tag = HARDWARE_MODULE_TAG,
232         .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
233         .hal_api_version = HARDWARE_HAL_API_VERSION,
234         .id = HWVULKAN_HARDWARE_MODULE_ID,
235         .name = "Goldfish Vulkan Driver",
236         .author = "The Android Open Source Project",
237         .methods = &goldfish_vulkan_module_methods,
238     },
239 };
240 
CloseDevice(struct hw_device_t *)241 int CloseDevice(struct hw_device_t* /*device*/) {
242     AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
243     // nothing to do - opening a device doesn't allocate any resources
244     return 0;
245 }
246 
247 #endif
248 
249 #define VK_HOST_CONNECTION(ret) \
250     HostConnection *hostCon = HostConnection::get(); \
251     if (!hostCon) { \
252         ALOGE("vulkan: Failed to get host connection\n"); \
253         return ret; \
254     } \
255     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
256     if (!rcEnc) { \
257         ALOGE("vulkan: Failed to get renderControl encoder context\n"); \
258         return ret; \
259     } \
260     goldfish_vk::VkEncoder *vkEnc = hostCon->vkEncoder(); \
261     if (!vkEnc) { \
262         ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
263         return ret; \
264     } \
265     goldfish_vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const()); \
266     auto hostSupportsVulkan = goldfish_vk::ResourceTracker::get()->hostSupportsVulkan(); \
267 
268 VKAPI_ATTR
EnumerateInstanceExtensionProperties(const char * layer_name,uint32_t * count,VkExtensionProperties * properties)269 VkResult EnumerateInstanceExtensionProperties(
270     const char* layer_name,
271     uint32_t* count,
272     VkExtensionProperties* properties) {
273     AEMU_SCOPED_TRACE("goldfish_vulkan::EnumerateInstanceExtensionProperties");
274 
275     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
276 
277     if (!hostSupportsVulkan) {
278         return vkstubhal::EnumerateInstanceExtensionProperties(layer_name, count, properties);
279     }
280 
281     if (layer_name) {
282         ALOGW(
283             "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
284             "with a layer name ('%s')",
285             layer_name);
286     }
287 
288     VkResult res = goldfish_vk::ResourceTracker::get()->on_vkEnumerateInstanceExtensionProperties(
289         vkEnc, VK_SUCCESS, layer_name, count, properties);
290 
291     return res;
292 }
293 
294 VKAPI_ATTR
CreateInstance(const VkInstanceCreateInfo * create_info,const VkAllocationCallbacks * allocator,VkInstance * out_instance)295 VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
296                         const VkAllocationCallbacks* allocator,
297                         VkInstance* out_instance) {
298     AEMU_SCOPED_TRACE("goldfish_vulkan::CreateInstance");
299 
300     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
301 
302     if (!hostSupportsVulkan) {
303         return vkstubhal::CreateInstance(create_info, allocator, out_instance);
304     }
305 
306     VkResult res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance);
307 
308     return res;
309 }
310 
311 #ifdef VK_USE_PLATFORM_FUCHSIA
312 VKAPI_ATTR
GetMemoryZirconHandleFUCHSIA(VkDevice device,const VkMemoryGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)313 VkResult GetMemoryZirconHandleFUCHSIA(
314     VkDevice device,
315     const VkMemoryGetZirconHandleInfoFUCHSIA* pInfo,
316     uint32_t* pHandle) {
317     AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandleFUCHSIA");
318 
319     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
320 
321     if (!hostSupportsVulkan) {
322         return vkstubhal::GetMemoryZirconHandleFUCHSIA(device, pInfo, pHandle);
323     }
324 
325     VkResult res = goldfish_vk::ResourceTracker::get()->
326         on_vkGetMemoryZirconHandleFUCHSIA(
327             vkEnc, VK_SUCCESS,
328             device, pInfo, pHandle);
329 
330     return res;
331 }
332 
333 VKAPI_ATTR
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice device,VkExternalMemoryHandleTypeFlagBits handleType,uint32_t handle,VkMemoryZirconHandlePropertiesFUCHSIA * pProperties)334 VkResult GetMemoryZirconHandlePropertiesFUCHSIA(
335     VkDevice device,
336     VkExternalMemoryHandleTypeFlagBits handleType,
337     uint32_t handle,
338     VkMemoryZirconHandlePropertiesFUCHSIA* pProperties) {
339     AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandlePropertiesFUCHSIA");
340 
341     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
342 
343     if (!hostSupportsVulkan) {
344         return vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA(
345             device, handleType, handle, pProperties);
346     }
347 
348     VkResult res = goldfish_vk::ResourceTracker::get()->
349         on_vkGetMemoryZirconHandlePropertiesFUCHSIA(
350             vkEnc, VK_SUCCESS, device, handleType, handle, pProperties);
351 
352     return res;
353 }
354 
355 VKAPI_ATTR
GetSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkSemaphoreGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)356 VkResult GetSemaphoreZirconHandleFUCHSIA(
357     VkDevice device,
358     const VkSemaphoreGetZirconHandleInfoFUCHSIA* pInfo,
359     uint32_t* pHandle) {
360     AEMU_SCOPED_TRACE("goldfish_vulkan::GetSemaphoreZirconHandleFUCHSIA");
361 
362     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
363 
364     if (!hostSupportsVulkan) {
365         return vkstubhal::GetSemaphoreZirconHandleFUCHSIA(device, pInfo, pHandle);
366     }
367 
368     VkResult res = goldfish_vk::ResourceTracker::get()->
369         on_vkGetSemaphoreZirconHandleFUCHSIA(
370             vkEnc, VK_SUCCESS, device, pInfo, pHandle);
371 
372     return res;
373 }
374 
375 VKAPI_ATTR
ImportSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkImportSemaphoreZirconHandleInfoFUCHSIA * pInfo)376 VkResult ImportSemaphoreZirconHandleFUCHSIA(
377     VkDevice device,
378     const VkImportSemaphoreZirconHandleInfoFUCHSIA* pInfo) {
379     AEMU_SCOPED_TRACE("goldfish_vulkan::ImportSemaphoreZirconHandleFUCHSIA");
380 
381     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
382 
383     if (!hostSupportsVulkan) {
384         return vkstubhal::ImportSemaphoreZirconHandleFUCHSIA(device, pInfo);
385     }
386 
387     VkResult res = goldfish_vk::ResourceTracker::get()->
388         on_vkImportSemaphoreZirconHandleFUCHSIA(
389             vkEnc, VK_SUCCESS, device, pInfo);
390 
391     return res;
392 }
393 
394 VKAPI_ATTR
CreateBufferCollectionFUCHSIA(VkDevice device,const VkBufferCollectionCreateInfoFUCHSIA * pInfo,const VkAllocationCallbacks * pAllocator,VkBufferCollectionFUCHSIA * pCollection)395 VkResult CreateBufferCollectionFUCHSIA(
396     VkDevice device,
397     const VkBufferCollectionCreateInfoFUCHSIA* pInfo,
398     const VkAllocationCallbacks* pAllocator,
399     VkBufferCollectionFUCHSIA* pCollection) {
400     AEMU_SCOPED_TRACE("goldfish_vulkan::CreateBufferCollectionFUCHSIA");
401 
402     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
403 
404     if (!hostSupportsVulkan) {
405         return vkstubhal::CreateBufferCollectionFUCHSIA(device, pInfo, pAllocator, pCollection);
406     }
407 
408     VkResult res = goldfish_vk::ResourceTracker::get()->
409         on_vkCreateBufferCollectionFUCHSIA(
410             vkEnc, VK_SUCCESS, device, pInfo, pAllocator, pCollection);
411 
412     return res;
413 }
414 
415 VKAPI_ATTR
DestroyBufferCollectionFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkAllocationCallbacks * pAllocator)416 void DestroyBufferCollectionFUCHSIA(
417     VkDevice device,
418     VkBufferCollectionFUCHSIA collection,
419     const VkAllocationCallbacks* pAllocator) {
420     AEMU_SCOPED_TRACE("goldfish_vulkan::DestroyBufferCollectionFUCHSIA");
421 
422     VK_HOST_CONNECTION()
423 
424     if (!hostSupportsVulkan) {
425         vkstubhal::DestroyBufferCollectionFUCHSIA(device, collection, pAllocator);
426         return;
427     }
428 
429     goldfish_vk::ResourceTracker::get()->
430         on_vkDestroyBufferCollectionFUCHSIA(
431             vkEnc, VK_SUCCESS, device, collection, pAllocator);
432 }
433 
434 VKAPI_ATTR
SetBufferCollectionConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkImageCreateInfo * pImageInfo)435 VkResult SetBufferCollectionConstraintsFUCHSIA(
436     VkDevice device,
437     VkBufferCollectionFUCHSIA collection,
438     const VkImageCreateInfo* pImageInfo) {
439     AEMU_SCOPED_TRACE("goldfish_vulkan::SetBufferCollectionConstraintsFUCHSIA");
440 
441     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
442 
443     if (!hostSupportsVulkan) {
444         return vkstubhal::SetBufferCollectionConstraintsFUCHSIA(device, collection, pImageInfo);
445     }
446 
447     VkResult res = goldfish_vk::ResourceTracker::get()->
448         on_vkSetBufferCollectionConstraintsFUCHSIA(
449             vkEnc, VK_SUCCESS, device, collection, pImageInfo);
450 
451     return res;
452 }
453 
454 VKAPI_ATTR
GetBufferCollectionPropertiesFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,VkBufferCollectionPropertiesFUCHSIA * pProperties)455 VkResult GetBufferCollectionPropertiesFUCHSIA(
456     VkDevice device,
457     VkBufferCollectionFUCHSIA collection,
458     VkBufferCollectionPropertiesFUCHSIA* pProperties) {
459     AEMU_SCOPED_TRACE("goldfish_vulkan::GetBufferCollectionPropertiesFUCHSIA");
460 
461     VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
462 
463     if (!hostSupportsVulkan) {
464         return vkstubhal::GetBufferCollectionPropertiesFUCHSIA(device, collection, pProperties);
465     }
466 
467     VkResult res = goldfish_vk::ResourceTracker::get()->
468         on_vkGetBufferCollectionPropertiesFUCHSIA(
469             vkEnc, VK_SUCCESS, device, collection, pProperties);
470 
471     return res;
472 }
473 #endif
474 
GetDeviceProcAddr(VkDevice device,const char * name)475 static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
476     AEMU_SCOPED_TRACE("goldfish_vulkan::GetDeviceProcAddr");
477 
478     VK_HOST_CONNECTION(nullptr)
479 
480     if (!hostSupportsVulkan) {
481         return nullptr;
482     }
483 
484 #ifdef VK_USE_PLATFORM_FUCHSIA
485     if (!strcmp(name, "vkGetMemoryZirconHandleFUCHSIA")) {
486         return (PFN_vkVoidFunction)GetMemoryZirconHandleFUCHSIA;
487     }
488     if (!strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) {
489         return (PFN_vkVoidFunction)GetMemoryZirconHandlePropertiesFUCHSIA;
490     }
491     if (!strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA")) {
492         return (PFN_vkVoidFunction)GetSemaphoreZirconHandleFUCHSIA;
493     }
494     if (!strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA")) {
495         return (PFN_vkVoidFunction)ImportSemaphoreZirconHandleFUCHSIA;
496     }
497     if (!strcmp(name, "vkCreateBufferCollectionFUCHSIA")) {
498         return (PFN_vkVoidFunction)CreateBufferCollectionFUCHSIA;
499     }
500     if (!strcmp(name, "vkDestroyBufferCollectionFUCHSIA")) {
501         return (PFN_vkVoidFunction)DestroyBufferCollectionFUCHSIA;
502     }
503     if (!strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA")) {
504         return (PFN_vkVoidFunction)SetBufferCollectionConstraintsFUCHSIA;
505     }
506     if (!strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA")) {
507         return (PFN_vkVoidFunction)GetBufferCollectionPropertiesFUCHSIA;
508     }
509 #endif
510     if (!strcmp(name, "vkGetDeviceProcAddr")) {
511         return (PFN_vkVoidFunction)(GetDeviceProcAddr);
512     }
513     return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_device_proc_address(device, name));
514 }
515 
516 VKAPI_ATTR
GetInstanceProcAddr(VkInstance instance,const char * name)517 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
518     AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
519 
520     VK_HOST_CONNECTION(nullptr)
521 
522     if (!hostSupportsVulkan) {
523         return vkstubhal::GetInstanceProcAddr(instance, name);
524     }
525 
526     if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
527         return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
528     }
529     if (!strcmp(name, "vkCreateInstance")) {
530         return (PFN_vkVoidFunction)CreateInstance;
531     }
532     if (!strcmp(name, "vkGetDeviceProcAddr")) {
533         return (PFN_vkVoidFunction)(GetDeviceProcAddr);
534     }
535     return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_instance_proc_address(instance, name));
536 }
537 
538 #ifdef VK_USE_PLATFORM_ANDROID_KHR
539 
540 hwvulkan_device_t goldfish_vulkan_device = {
541     .common = {
542         .tag = HARDWARE_DEVICE_TAG,
543         .version = HWVULKAN_DEVICE_API_VERSION_0_1,
544         .module = &HAL_MODULE_INFO_SYM.common,
545         .close = CloseDevice,
546     },
547     .EnumerateInstanceExtensionProperties = EnumerateInstanceExtensionProperties,
548     .CreateInstance = CreateInstance,
549     .GetInstanceProcAddr = GetInstanceProcAddr,
550 };
551 
OpenDevice(const hw_module_t *,const char * id,hw_device_t ** device)552 int OpenDevice(const hw_module_t* /*module*/,
553                const char* id,
554                hw_device_t** device) {
555     AEMU_SCOPED_TRACE("goldfish_vulkan::OpenDevice");
556 
557     if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
558         *device = &goldfish_vulkan_device.common;
559         goldfish_vk::ResourceTracker::get();
560         return 0;
561     }
562     return -ENOENT;
563 }
564 
565 #endif
566 
567 #ifdef VK_USE_PLATFORM_FUCHSIA
568 
569 class VulkanDevice {
570 public:
VulkanDevice()571     VulkanDevice() {
572         goldfish_vk::ResourceTracker::get();
573     }
574 
GetInstance()575     static VulkanDevice& GetInstance() {
576         static VulkanDevice g_instance;
577         return g_instance;
578     }
579 
GetInstanceProcAddr(VkInstance instance,const char * name)580     PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
581         return ::GetInstanceProcAddr(instance, name);
582     }
583 };
584 
585 extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction
vk_icdGetInstanceProcAddr(VkInstance instance,const char * name)586 vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) {
587     return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name);
588 }
589 
590 extern "C" __attribute__((visibility("default"))) VkResult
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)591 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
592     *pSupportedVersion = std::min(*pSupportedVersion, 3u);
593     return VK_SUCCESS;
594 }
595 
596 #endif
597 
598 } // namespace
599