1 // Copyright (C) 2023 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 
15 #include <errno.h>
16 #include <string.h>
17 
18 #include "../vulkan_enc/vk_util.h"
19 #include "HostConnection.h"
20 #include "ProcessPipe.h"
21 #include "ResourceTracker.h"
22 #include "VkEncoder.h"
23 #include "gfxstream_vk_entrypoints.h"
24 #include "gfxstream_vk_private.h"
25 #include "vk_alloc.h"
26 #include "vk_device.h"
27 #include "vk_instance.h"
28 #include "vk_sync_dummy.h"
29 
30 #define VK_HOST_CONNECTION(ret)                                                    \
31     HostConnection* hostCon = HostConnection::getOrCreate(kCapsetGfxStreamVulkan); \
32     gfxstream::vk::VkEncoder* vkEnc = hostCon->vkEncoder();                        \
33     if (!vkEnc) {                                                                  \
34         mesa_loge("vulkan: Failed to get Vulkan encoder\n");                       \
35         return ret;                                                                \
36     }
37 
38 namespace {
39 
40 static bool instance_extension_table_initialized = false;
41 static struct vk_instance_extension_table gfxstream_vk_instance_extensions_supported = {};
42 
43 // Provided by Mesa components only; never encoded/decoded through gfxstream
44 static const char* const kMesaOnlyInstanceExtension[] = {
45     VK_KHR_SURFACE_EXTENSION_NAME,
46 #if defined(LINUX_GUEST_BUILD)
47     VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
48 #endif
49     VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
50 };
51 
52 static const char* const kMesaOnlyDeviceExtensions[] = {
53     VK_KHR_SWAPCHAIN_EXTENSION_NAME,
54 };
55 
getConnection(void)56 static HostConnection* getConnection(void) {
57     auto hostCon = HostConnection::getOrCreate(kCapsetGfxStreamVulkan);
58     return hostCon;
59 }
60 
getVkEncoder(HostConnection * con)61 static gfxstream::vk::VkEncoder* getVkEncoder(HostConnection* con) { return con->vkEncoder(); }
62 
SetupInstanceForProcess(void)63 static VkResult SetupInstanceForProcess(void) {
64     uint32_t noRenderControlEnc = 0;
65     HostConnection* hostCon = getConnection();
66     if (!hostCon) {
67         mesa_loge("vulkan: Failed to get host connection\n");
68         return VK_ERROR_DEVICE_LOST;
69     }
70 
71     gfxstream::vk::ResourceTracker::get()->setupCaps(noRenderControlEnc);
72     // Legacy goldfish path: could be deleted once goldfish not used guest-side.
73     if (!noRenderControlEnc) {
74         // Implicitly sets up sequence number
75         ExtendedRCEncoderContext* rcEnc = hostCon->rcEncoder();
76         if (!rcEnc) {
77             mesa_loge("vulkan: Failed to get renderControl encoder context\n");
78             return VK_ERROR_DEVICE_LOST;
79         }
80 
81         gfxstream::vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const());
82     }
83 
84     gfxstream::vk::ResourceTracker::get()->setThreadingCallbacks({
85         .hostConnectionGetFunc = getConnection,
86         .vkEncoderGetFunc = getVkEncoder,
87     });
88     gfxstream::vk::ResourceTracker::get()->setSeqnoPtr(getSeqnoPtrForProcess());
89     gfxstream::vk::VkEncoder* vkEnc = getVkEncoder(hostCon);
90     if (!vkEnc) {
91         mesa_loge("vulkan: Failed to get Vulkan encoder\n");
92         return VK_ERROR_DEVICE_LOST;
93     }
94 
95     return VK_SUCCESS;
96 }
97 
isMesaOnlyInstanceExtension(const char * name)98 static bool isMesaOnlyInstanceExtension(const char* name) {
99     for (auto mesaExt : kMesaOnlyInstanceExtension) {
100         if (!strncmp(mesaExt, name, VK_MAX_EXTENSION_NAME_SIZE)) return true;
101     }
102     return false;
103 }
104 
isMesaOnlyDeviceExtension(const char * name)105 static bool isMesaOnlyDeviceExtension(const char* name) {
106     for (auto mesaExt : kMesaOnlyDeviceExtensions) {
107         if (!strncmp(mesaExt, name, VK_MAX_EXTENSION_NAME_SIZE)) return true;
108     }
109     return false;
110 }
111 
112 // Filtered extension names for encoding
filteredInstanceExtensionNames(uint32_t count,const char * const * extNames)113 static std::vector<const char*> filteredInstanceExtensionNames(uint32_t count,
114                                                                const char* const* extNames) {
115     std::vector<const char*> retList;
116     for (uint32_t i = 0; i < count; ++i) {
117         auto extName = extNames[i];
118         if (!isMesaOnlyInstanceExtension(extName)) {
119             retList.push_back(extName);
120         }
121     }
122     return retList;
123 }
124 
filteredDeviceExtensionNames(uint32_t count,const char * const * extNames)125 static std::vector<const char*> filteredDeviceExtensionNames(uint32_t count,
126                                                              const char* const* extNames) {
127     std::vector<const char*> retList;
128     for (uint32_t i = 0; i < count; ++i) {
129         auto extName = extNames[i];
130         if (!isMesaOnlyDeviceExtension(extName)) {
131             retList.push_back(extName);
132         }
133     }
134     return retList;
135 }
136 
get_device_extensions(VkPhysicalDevice physDevInternal,struct vk_device_extension_table * deviceExts)137 static void get_device_extensions(VkPhysicalDevice physDevInternal,
138                                   struct vk_device_extension_table* deviceExts) {
139     VkResult result = (VkResult)0;
140     auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
141     auto resources = gfxstream::vk::ResourceTracker::get();
142     uint32_t numDeviceExts = 0;
143     result = resources->on_vkEnumerateDeviceExtensionProperties(vkEnc, VK_SUCCESS, physDevInternal,
144                                                                 NULL, &numDeviceExts, NULL);
145     if (VK_SUCCESS == result) {
146         std::vector<VkExtensionProperties> extProps(numDeviceExts);
147         result = resources->on_vkEnumerateDeviceExtensionProperties(
148             vkEnc, VK_SUCCESS, physDevInternal, NULL, &numDeviceExts, extProps.data());
149         if (VK_SUCCESS == result) {
150             // device extensions from gfxstream
151             for (uint32_t i = 0; i < numDeviceExts; i++) {
152                 for (uint32_t j = 0; j < VK_DEVICE_EXTENSION_COUNT; j++) {
153                     if (0 == strncmp(extProps[i].extensionName,
154                                      vk_device_extensions[j].extensionName,
155                                      VK_MAX_EXTENSION_NAME_SIZE)) {
156                         deviceExts->extensions[j] = true;
157                         break;
158                     }
159                 }
160             }
161             // device extensions from Mesa
162             for (uint32_t j = 0; j < VK_DEVICE_EXTENSION_COUNT; j++) {
163                 if (isMesaOnlyDeviceExtension(vk_device_extensions[j].extensionName)) {
164                     deviceExts->extensions[j] = true;
165                     break;
166                 }
167             }
168         }
169     }
170 }
171 
gfxstream_vk_physical_device_init(struct gfxstream_vk_physical_device * physical_device,struct gfxstream_vk_instance * instance,VkPhysicalDevice internal_object)172 static VkResult gfxstream_vk_physical_device_init(
173     struct gfxstream_vk_physical_device* physical_device, struct gfxstream_vk_instance* instance,
174     VkPhysicalDevice internal_object) {
175     struct vk_device_extension_table supported_extensions = {};
176     get_device_extensions(internal_object, &supported_extensions);
177 
178     struct vk_physical_device_dispatch_table dispatch_table;
179     memset(&dispatch_table, 0, sizeof(struct vk_physical_device_dispatch_table));
180     vk_physical_device_dispatch_table_from_entrypoints(
181         &dispatch_table, &gfxstream_vk_physical_device_entrypoints, false);
182 #if !defined(__Fuchsia__)
183     vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
184                                                        &wsi_physical_device_entrypoints, false);
185 #endif
186 
187     // Initialize the mesa object
188     VkResult result = vk_physical_device_init(&physical_device->vk, &instance->vk,
189                                               &supported_extensions, NULL, NULL, &dispatch_table);
190 
191     if (VK_SUCCESS == result) {
192         // Set the gfxstream-internal object
193         physical_device->internal_object = internal_object;
194         physical_device->instance = instance;
195         // Note: Must use dummy_sync for correct sync object path in WSI operations
196         physical_device->sync_types[0] = &vk_sync_dummy_type;
197         physical_device->sync_types[1] = NULL;
198         physical_device->vk.supported_sync_types = physical_device->sync_types;
199 
200         result = gfxstream_vk_wsi_init(physical_device);
201     }
202 
203     return result;
204 }
205 
gfxstream_vk_physical_device_finish(struct gfxstream_vk_physical_device * physical_device)206 static void gfxstream_vk_physical_device_finish(
207     struct gfxstream_vk_physical_device* physical_device) {
208     gfxstream_vk_wsi_finish(physical_device);
209 
210     vk_physical_device_finish(&physical_device->vk);
211 }
212 
gfxstream_vk_destroy_physical_device(struct vk_physical_device * physical_device)213 static void gfxstream_vk_destroy_physical_device(struct vk_physical_device* physical_device) {
214     gfxstream_vk_physical_device_finish((struct gfxstream_vk_physical_device*)physical_device);
215     vk_free(&physical_device->instance->alloc, physical_device);
216 }
217 
gfxstream_vk_enumerate_devices(struct vk_instance * vk_instance)218 static VkResult gfxstream_vk_enumerate_devices(struct vk_instance* vk_instance) {
219     VkResult result = VK_SUCCESS;
220     gfxstream_vk_instance* gfxstream_instance = (gfxstream_vk_instance*)vk_instance;
221     uint32_t deviceCount = 0;
222     auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
223     auto resources = gfxstream::vk::ResourceTracker::get();
224     result = resources->on_vkEnumeratePhysicalDevices(
225         vkEnc, VK_SUCCESS, gfxstream_instance->internal_object, &deviceCount, NULL);
226     if (VK_SUCCESS != result) return result;
227     std::vector<VkPhysicalDevice> internal_list(deviceCount);
228     result = resources->on_vkEnumeratePhysicalDevices(
229         vkEnc, VK_SUCCESS, gfxstream_instance->internal_object, &deviceCount, internal_list.data());
230 
231     if (VK_SUCCESS == result) {
232         for (uint32_t i = 0; i < deviceCount; i++) {
233             struct gfxstream_vk_physical_device* gfxstream_physicalDevice =
234                 (struct gfxstream_vk_physical_device*)vk_zalloc(
235                     &gfxstream_instance->vk.alloc, sizeof(struct gfxstream_vk_physical_device), 8,
236                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
237             if (!gfxstream_physicalDevice) {
238                 result = VK_ERROR_OUT_OF_HOST_MEMORY;
239                 break;
240             }
241             result = gfxstream_vk_physical_device_init(gfxstream_physicalDevice, gfxstream_instance,
242                                                        internal_list[i]);
243             if (VK_SUCCESS == result) {
244                 list_addtail(&gfxstream_physicalDevice->vk.link,
245                              &gfxstream_instance->vk.physical_devices.list);
246             } else {
247                 vk_free(&gfxstream_instance->vk.alloc, gfxstream_physicalDevice);
248                 break;
249             }
250         }
251     }
252 
253     return result;
254 }
255 
get_instance_extensions()256 static struct vk_instance_extension_table* get_instance_extensions() {
257     struct vk_instance_extension_table* const retTablePtr =
258         &gfxstream_vk_instance_extensions_supported;
259     if (!instance_extension_table_initialized) {
260         VkResult result = SetupInstanceForProcess();
261         if (VK_SUCCESS == result) {
262             VK_HOST_CONNECTION(retTablePtr)
263             auto resources = gfxstream::vk::ResourceTracker::get();
264             uint32_t numInstanceExts = 0;
265             result = resources->on_vkEnumerateInstanceExtensionProperties(vkEnc, VK_SUCCESS, NULL,
266                                                                           &numInstanceExts, NULL);
267             if (VK_SUCCESS == result) {
268                 std::vector<VkExtensionProperties> extProps(numInstanceExts);
269                 result = resources->on_vkEnumerateInstanceExtensionProperties(
270                     vkEnc, VK_SUCCESS, NULL, &numInstanceExts, extProps.data());
271                 if (VK_SUCCESS == result) {
272                     // instance extensions from gfxstream
273                     for (uint32_t i = 0; i < numInstanceExts; i++) {
274                         for (uint32_t j = 0; j < VK_INSTANCE_EXTENSION_COUNT; j++) {
275                             if (0 == strncmp(extProps[i].extensionName,
276                                              vk_instance_extensions[j].extensionName,
277                                              VK_MAX_EXTENSION_NAME_SIZE)) {
278                                 gfxstream_vk_instance_extensions_supported.extensions[j] = true;
279                                 break;
280                             }
281                         }
282                     }
283                     // instance extensions from Mesa
284                     for (uint32_t j = 0; j < VK_INSTANCE_EXTENSION_COUNT; j++) {
285                         if (isMesaOnlyInstanceExtension(vk_instance_extensions[j].extensionName)) {
286                             gfxstream_vk_instance_extensions_supported.extensions[j] = true;
287                         }
288                     }
289                     instance_extension_table_initialized = true;
290                 }
291             }
292         }
293     }
294     return retTablePtr;
295 }
296 
297 }  // namespace
298 
gfxstream_vk_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)299 VkResult gfxstream_vk_CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
300                                      const VkAllocationCallbacks* pAllocator,
301                                      VkInstance* pInstance) {
302     AEMU_SCOPED_TRACE("vkCreateInstance");
303 
304     struct gfxstream_vk_instance* instance;
305 
306     pAllocator = pAllocator ?: vk_default_allocator();
307     instance = (struct gfxstream_vk_instance*)vk_zalloc(pAllocator, sizeof(*instance), 8,
308                                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
309     if (NULL == instance) {
310         return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
311     }
312 
313     VkResult result = VK_SUCCESS;
314     /* Encoder call */
315     {
316         ALOGV("calling setup instance internally");
317         result = SetupInstanceForProcess();
318         if (VK_SUCCESS != result) {
319             return vk_error(NULL, result);
320         }
321         uint32_t initialEnabledExtensionCount = pCreateInfo->enabledExtensionCount;
322         const char* const* initialPpEnabledExtensionNames = pCreateInfo->ppEnabledExtensionNames;
323         std::vector<const char*> filteredExts = filteredInstanceExtensionNames(
324             pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
325         // Temporarily modify createInfo for the encoder call
326         VkInstanceCreateInfo* mutableCreateInfo = (VkInstanceCreateInfo*)pCreateInfo;
327         mutableCreateInfo->enabledExtensionCount = static_cast<uint32_t>(filteredExts.size());
328         mutableCreateInfo->ppEnabledExtensionNames = filteredExts.data();
329 
330         VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST);
331         result = vkEnc->vkCreateInstance(pCreateInfo, nullptr, &instance->internal_object,
332                                          true /* do lock */);
333         if (VK_SUCCESS != result) {
334             return vk_error(NULL, result);
335         }
336         // Revert the createInfo the user-set data
337         mutableCreateInfo->enabledExtensionCount = initialEnabledExtensionCount;
338         mutableCreateInfo->ppEnabledExtensionNames = initialPpEnabledExtensionNames;
339     }
340 
341     struct vk_instance_dispatch_table dispatch_table;
342     memset(&dispatch_table, 0, sizeof(struct vk_instance_dispatch_table));
343     vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &gfxstream_vk_instance_entrypoints,
344                                                 false);
345 #if !defined(__Fuchsia__)
346     vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &wsi_instance_entrypoints, false);
347 #endif
348 
349     result = vk_instance_init(&instance->vk, get_instance_extensions(), &dispatch_table,
350                               pCreateInfo, pAllocator);
351 
352     if (result != VK_SUCCESS) {
353         vk_free(pAllocator, instance);
354         return vk_error(NULL, result);
355     }
356 
357     instance->vk.physical_devices.enumerate = gfxstream_vk_enumerate_devices;
358     instance->vk.physical_devices.destroy = gfxstream_vk_destroy_physical_device;
359     // TODO: instance->vk.physical_devices.try_create_for_drm (?)
360 
361     *pInstance = gfxstream_vk_instance_to_handle(instance);
362     return VK_SUCCESS;
363 }
364 
gfxstream_vk_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)365 void gfxstream_vk_DestroyInstance(VkInstance _instance, const VkAllocationCallbacks* pAllocator) {
366     AEMU_SCOPED_TRACE("vkDestroyInstance");
367     if (VK_NULL_HANDLE == _instance) return;
368 
369     VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
370 
371     VK_HOST_CONNECTION()
372     vkEnc->vkDestroyInstance(instance->internal_object, pAllocator, true /* do lock */);
373 
374     vk_instance_finish(&instance->vk);
375     vk_free(&instance->vk.alloc, instance);
376 
377     // To make End2EndTests happy, since now the host connection is statically linked to
378     // libvulkan_ranchu.so [separate HostConnections now].
379 #if defined(END2END_TESTS)
380     hostCon->exit();
381     processPipeRestart();
382 #endif
383 }
384 
gfxstream_vk_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)385 VkResult gfxstream_vk_EnumerateInstanceExtensionProperties(const char* pLayerName,
386                                                            uint32_t* pPropertyCount,
387                                                            VkExtensionProperties* pProperties) {
388     AEMU_SCOPED_TRACE("vkvkEnumerateInstanceExtensionProperties");
389     (void)pLayerName;
390 
391     return vk_enumerate_instance_extension_properties(get_instance_extensions(), pPropertyCount,
392                                                       pProperties);
393 }
394 
gfxstream_vk_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)395 VkResult gfxstream_vk_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
396                                                          const char* pLayerName,
397                                                          uint32_t* pPropertyCount,
398                                                          VkExtensionProperties* pProperties) {
399     AEMU_SCOPED_TRACE("vkEnumerateDeviceExtensionProperties");
400     (void)pLayerName;
401     VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
402 
403     VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount);
404 
405     for (int i = 0; i < VK_DEVICE_EXTENSION_COUNT; i++) {
406         if (!pdevice->supported_extensions.extensions[i]) continue;
407 
408         vk_outarray_append_typed(VkExtensionProperties, &out, prop) {
409             *prop = vk_device_extensions[i];
410         }
411     }
412 
413     return vk_outarray_status(&out);
414 }
415 
gfxstream_vk_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)416 VkResult gfxstream_vk_CreateDevice(VkPhysicalDevice physicalDevice,
417                                    const VkDeviceCreateInfo* pCreateInfo,
418                                    const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
419     AEMU_SCOPED_TRACE("vkCreateDevice");
420     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
421     VkResult result = (VkResult)0;
422 
423     /*
424      * Android's libvulkan implements VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT, but
425      * passes it to the underlying driver anyways.  See:
426      *
427      * https://android-review.googlesource.com/c/platform/hardware/google/gfxstream/+/2839438
428      *
429      * and associated bugs. Mesa VK runtime also checks this, so we have to filter out before
430      * reaches it.
431      */
432     VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT* swapchainMaintenance1Features =
433         (VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT*)vk_find_struct<VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT>(pCreateInfo);
434     if (swapchainMaintenance1Features) {
435         swapchainMaintenance1Features->swapchainMaintenance1 = VK_FALSE;
436     }
437 
438     const VkAllocationCallbacks* pMesaAllocator =
439         pAllocator ?: &gfxstream_physicalDevice->instance->vk.alloc;
440     struct gfxstream_vk_device* gfxstream_device = (struct gfxstream_vk_device*)vk_zalloc(
441         pMesaAllocator, sizeof(struct gfxstream_vk_device), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
442     result = gfxstream_device ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
443     if (VK_SUCCESS == result) {
444         uint32_t initialEnabledExtensionCount = pCreateInfo->enabledExtensionCount;
445         const char* const* initialPpEnabledExtensionNames = pCreateInfo->ppEnabledExtensionNames;
446         std::vector<const char*> filteredExts = filteredDeviceExtensionNames(
447             pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
448         // Temporarily modify createInfo for the encoder call
449         VkDeviceCreateInfo* mutableCreateInfo = (VkDeviceCreateInfo*)pCreateInfo;
450         mutableCreateInfo->enabledExtensionCount = static_cast<uint32_t>(filteredExts.size());
451         mutableCreateInfo->ppEnabledExtensionNames = filteredExts.data();
452 
453         /* pNext = VkPhysicalDeviceGroupProperties */
454         std::vector<VkPhysicalDevice> initialPhysicalDeviceList;
455         VkPhysicalDeviceGroupProperties* mutablePhysicalDeviceGroupProperties =
456             (VkPhysicalDeviceGroupProperties*)vk_find_struct<VkPhysicalDeviceGroupProperties>(
457                 pCreateInfo);
458         if (mutablePhysicalDeviceGroupProperties) {
459             // Temporarily modify the VkPhysicalDeviceGroupProperties structure to use translated
460             // VkPhysicalDevice references for the encoder call
461             for (int physDev = 0;
462                  physDev < mutablePhysicalDeviceGroupProperties->physicalDeviceCount; physDev++) {
463                 initialPhysicalDeviceList.push_back(
464                     mutablePhysicalDeviceGroupProperties->physicalDevices[physDev]);
465                 VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice,
466                                mutablePhysicalDeviceGroupProperties->physicalDevices[physDev]);
467                 mutablePhysicalDeviceGroupProperties->physicalDevices[physDev] =
468                     gfxstream_physicalDevice->internal_object;
469             }
470         }
471 
472         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
473         result = vkEnc->vkCreateDevice(gfxstream_physicalDevice->internal_object, pCreateInfo,
474                                        pAllocator, &gfxstream_device->internal_object,
475                                        true /* do lock */);
476         // Revert the createInfo the user-set data
477         mutableCreateInfo->enabledExtensionCount = initialEnabledExtensionCount;
478         mutableCreateInfo->ppEnabledExtensionNames = initialPpEnabledExtensionNames;
479         if (mutablePhysicalDeviceGroupProperties) {
480             // Revert the physicalDevice list in VkPhysicalDeviceGroupProperties to the user-set
481             // data
482             for (int physDev = 0;
483                  physDev < mutablePhysicalDeviceGroupProperties->physicalDeviceCount; physDev++) {
484                 initialPhysicalDeviceList.push_back(
485                     mutablePhysicalDeviceGroupProperties->physicalDevices[physDev]);
486                 mutablePhysicalDeviceGroupProperties->physicalDevices[physDev] =
487                     initialPhysicalDeviceList[physDev];
488             }
489         }
490     }
491     if (VK_SUCCESS == result) {
492         struct vk_device_dispatch_table dispatch_table;
493         memset(&dispatch_table, 0, sizeof(struct vk_device_dispatch_table));
494         vk_device_dispatch_table_from_entrypoints(&dispatch_table, &gfxstream_vk_device_entrypoints,
495                                                   false);
496 #if !defined(__Fuchsia__)
497         vk_device_dispatch_table_from_entrypoints(&dispatch_table, &wsi_device_entrypoints, false);
498 #endif
499 
500         result = vk_device_init(&gfxstream_device->vk, &gfxstream_physicalDevice->vk,
501                                 &dispatch_table, pCreateInfo, pMesaAllocator);
502     }
503     if (VK_SUCCESS == result) {
504         gfxstream_device->physical_device = gfxstream_physicalDevice;
505         // TODO: Initialize cmd_dispatch for emulated secondary command buffer support?
506         gfxstream_device->vk.command_dispatch_table = &gfxstream_device->cmd_dispatch;
507         *pDevice = gfxstream_vk_device_to_handle(gfxstream_device);
508     } else {
509         vk_free(pMesaAllocator, gfxstream_device);
510     }
511 
512     return result;
513 }
514 
gfxstream_vk_DestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)515 void gfxstream_vk_DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
516     AEMU_SCOPED_TRACE("vkDestroyDevice");
517     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
518     if (VK_NULL_HANDLE == device) return;
519 
520     auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
521     vkEnc->vkDestroyDevice(gfxstream_device->internal_object, pAllocator, true /* do lock */);
522 
523     /* Must destroy device queues manually */
524     vk_foreach_queue_safe(queue, &gfxstream_device->vk) {
525         vk_queue_finish(queue);
526         vk_free(&gfxstream_device->vk.alloc, queue);
527     }
528     vk_device_finish(&gfxstream_device->vk);
529     vk_free(&gfxstream_device->vk.alloc, gfxstream_device);
530 }
531 
gfxstream_vk_GetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)532 void gfxstream_vk_GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex,
533                                  VkQueue* pQueue) {
534     AEMU_SCOPED_TRACE("vkGetDeviceQueue");
535     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
536     struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc(
537         &gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), 8,
538         VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
539     VkResult result = gfxstream_queue ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
540     if (VK_SUCCESS == result) {
541         VkDeviceQueueCreateInfo createInfo = {
542             .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
543             .pNext = NULL,
544             .flags = 0,
545             .queueFamilyIndex = queueFamilyIndex,
546             .queueCount = 1,
547             .pQueuePriorities = NULL,
548         };
549         result =
550             vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &createInfo, queueIndex);
551     }
552     if (VK_SUCCESS == result) {
553         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
554         vkEnc->vkGetDeviceQueue(gfxstream_device->internal_object, queueFamilyIndex, queueIndex,
555                                 &gfxstream_queue->internal_object, true /* do lock */);
556 
557         gfxstream_queue->device = gfxstream_device;
558         *pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue);
559     } else {
560         *pQueue = VK_NULL_HANDLE;
561     }
562 }
563 
gfxstream_vk_GetDeviceQueue2(VkDevice device,const VkDeviceQueueInfo2 * pQueueInfo,VkQueue * pQueue)564 void gfxstream_vk_GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo,
565                                   VkQueue* pQueue) {
566     AEMU_SCOPED_TRACE("vkGetDeviceQueue2");
567     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
568     struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc(
569         &gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), 8,
570         VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
571     VkResult result = gfxstream_queue ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
572     if (VK_SUCCESS == result) {
573         VkDeviceQueueCreateInfo createInfo = {
574             .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
575             .pNext = NULL,
576             .flags = pQueueInfo->flags,
577             .queueFamilyIndex = pQueueInfo->queueFamilyIndex,
578             .queueCount = 1,
579             .pQueuePriorities = NULL,
580         };
581         result = vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &createInfo,
582                                pQueueInfo->queueIndex);
583     }
584     if (VK_SUCCESS == result) {
585         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
586         vkEnc->vkGetDeviceQueue2(gfxstream_device->internal_object, pQueueInfo,
587                                  &gfxstream_queue->internal_object, true /* do lock */);
588 
589         gfxstream_queue->device = gfxstream_device;
590         *pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue);
591     } else {
592         *pQueue = VK_NULL_HANDLE;
593     }
594 }
595 
596 /* The loader wants us to expose a second GetInstanceProcAddr function
597  * to work around certain LD_PRELOAD issues seen in apps.
598  */
599 extern "C" PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
600 vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName);
601 
602 extern "C" PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)603 vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName) {
604     return gfxstream_vk_GetInstanceProcAddr(instance, pName);
605 }
606 
607 /* vk_icd.h does not declare this function, so we declare it here to
608  * suppress Wmissing-prototypes.
609  */
610 extern "C" PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
611 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
612 
613 extern "C" PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)614 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
615     *pSupportedVersion = std::min(*pSupportedVersion, 3u);
616     return VK_SUCCESS;
617 }
618 
619 /* With version 4+ of the loader interface the ICD should expose
620  * vk_icdGetPhysicalDeviceProcAddr()
621  */
622 extern "C" PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
623 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, const char* pName);
624 
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,const char * pName)625 PFN_vkVoidFunction vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, const char* pName) {
626     VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
627 
628     return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
629 }
630 
gfxstream_vk_GetInstanceProcAddr(VkInstance _instance,const char * pName)631 PFN_vkVoidFunction gfxstream_vk_GetInstanceProcAddr(VkInstance _instance, const char* pName) {
632     VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
633     return vk_instance_get_proc_addr(&instance->vk, &gfxstream_vk_instance_entrypoints, pName);
634 }
635 
gfxstream_vk_GetDeviceProcAddr(VkDevice _device,const char * pName)636 PFN_vkVoidFunction gfxstream_vk_GetDeviceProcAddr(VkDevice _device, const char* pName) {
637     AEMU_SCOPED_TRACE("vkGetDeviceProcAddr");
638     VK_FROM_HANDLE(gfxstream_vk_device, device, _device);
639     return vk_device_get_proc_addr(&device->vk, pName);
640 }
641 
gfxstream_vk_AllocateMemory(VkDevice device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMemory)642 VkResult gfxstream_vk_AllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
643                                      const VkAllocationCallbacks* pAllocator,
644                                      VkDeviceMemory* pMemory) {
645     AEMU_SCOPED_TRACE("vkAllocateMemory");
646     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
647     VkResult vkAllocateMemory_VkResult_return = (VkResult)0;
648     /* VkMemoryDedicatedAllocateInfo */
649     VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr =
650         (VkMemoryDedicatedAllocateInfo*)vk_find_struct<VkMemoryDedicatedAllocateInfo>(
651             pAllocateInfo);
652     if (dedicatedAllocInfoPtr) {
653         if (dedicatedAllocInfoPtr->buffer) {
654             VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, dedicatedAllocInfoPtr->buffer);
655             dedicatedAllocInfoPtr->buffer = gfxstream_buffer->internal_object;
656         }
657     }
658     {
659         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
660         auto resources = gfxstream::vk::ResourceTracker::get();
661         vkAllocateMemory_VkResult_return =
662             resources->on_vkAllocateMemory(vkEnc, VK_SUCCESS, gfxstream_device->internal_object,
663                                            pAllocateInfo, pAllocator, pMemory);
664     }
665     return vkAllocateMemory_VkResult_return;
666 }
667 
gfxstream_vk_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)668 VkResult gfxstream_vk_EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
669                                                        VkLayerProperties* pProperties) {
670     AEMU_SCOPED_TRACE("vkEnumerateInstanceLayerProperties");
671     auto result = SetupInstanceForProcess();
672     if (VK_SUCCESS != result) {
673         return vk_error(NULL, result);
674     }
675 
676     VkResult vkEnumerateInstanceLayerProperties_VkResult_return = (VkResult)0;
677     {
678         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
679         vkEnumerateInstanceLayerProperties_VkResult_return =
680             vkEnc->vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties,
681                                                       true /* do lock */);
682     }
683     return vkEnumerateInstanceLayerProperties_VkResult_return;
684 }
685 
gfxstream_vk_EnumerateInstanceVersion(uint32_t * pApiVersion)686 VkResult gfxstream_vk_EnumerateInstanceVersion(uint32_t* pApiVersion) {
687     AEMU_SCOPED_TRACE("vkEnumerateInstanceVersion");
688     auto result = SetupInstanceForProcess();
689     if (VK_SUCCESS != result) {
690         return vk_error(NULL, result);
691     }
692 
693     VkResult vkEnumerateInstanceVersion_VkResult_return = (VkResult)0;
694     {
695         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
696         vkEnumerateInstanceVersion_VkResult_return =
697             vkEnc->vkEnumerateInstanceVersion(pApiVersion, true /* do lock */);
698     }
699     return vkEnumerateInstanceVersion_VkResult_return;
700 }
701 
transformDescriptorSetList(const VkWriteDescriptorSet * pDescriptorSets,uint32_t descriptorSetCount,std::vector<std::vector<VkDescriptorBufferInfo>> & bufferInfos)702 static std::vector<VkWriteDescriptorSet> transformDescriptorSetList(
703     const VkWriteDescriptorSet* pDescriptorSets, uint32_t descriptorSetCount,
704     std::vector<std::vector<VkDescriptorBufferInfo>>& bufferInfos) {
705     std::vector<VkWriteDescriptorSet> outDescriptorSets(descriptorSetCount);
706     for (uint32_t i = 0; i < descriptorSetCount; ++i) {
707         const auto& srcDescriptorSet = pDescriptorSets[i];
708         const uint32_t descriptorCount = srcDescriptorSet.descriptorCount;
709 
710         VkWriteDescriptorSet& outDescriptorSet = outDescriptorSets[i];
711         outDescriptorSet = srcDescriptorSet;
712 
713         bufferInfos.push_back(std::vector<VkDescriptorBufferInfo>());
714         bufferInfos[i].reserve(descriptorCount);
715         memset(&bufferInfos[i][0], 0, sizeof(VkDescriptorBufferInfo) * descriptorCount);
716         for (uint32_t j = 0; j < descriptorCount; ++j) {
717             const auto* srcBufferInfo = srcDescriptorSet.pBufferInfo;
718             if (srcBufferInfo) {
719                 bufferInfos[i][j] = srcBufferInfo[j];
720                 bufferInfos[i][j].buffer = VK_NULL_HANDLE;
721                 if (vk_descriptor_type_has_descriptor_buffer(srcDescriptorSet.descriptorType) &&
722                     srcBufferInfo[j].buffer) {
723                     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstreamBuffer, srcBufferInfo[j].buffer);
724                     bufferInfos[i][j].buffer = gfxstreamBuffer->internal_object;
725                 }
726             }
727         }
728         outDescriptorSet.pBufferInfo = bufferInfos[i].data();
729     }
730     return outDescriptorSets;
731 }
732 
gfxstream_vk_UpdateDescriptorSets(VkDevice device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)733 void gfxstream_vk_UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
734                                        const VkWriteDescriptorSet* pDescriptorWrites,
735                                        uint32_t descriptorCopyCount,
736                                        const VkCopyDescriptorSet* pDescriptorCopies) {
737     AEMU_SCOPED_TRACE("vkUpdateDescriptorSets");
738     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
739     {
740         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
741         std::vector<std::vector<VkDescriptorBufferInfo>> descriptorBufferInfoStorage;
742         std::vector<VkWriteDescriptorSet> internal_pDescriptorWrites = transformDescriptorSetList(
743             pDescriptorWrites, descriptorWriteCount, descriptorBufferInfoStorage);
744         auto resources = gfxstream::vk::ResourceTracker::get();
745         resources->on_vkUpdateDescriptorSets(
746             vkEnc, gfxstream_device->internal_object, descriptorWriteCount,
747             internal_pDescriptorWrites.data(), descriptorCopyCount, pDescriptorCopies);
748     }
749 }
750