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