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