1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <hardware/hwvulkan.h>
15
16 #include <log/log.h>
17
18 #include <errno.h>
19 #include <string.h>
20 #ifdef VK_USE_PLATFORM_FUCHSIA
21 #include <fidl/fuchsia.logger/cpp/wire.h>
22 #include <lib/syslog/global.h>
23 #include <lib/zx/channel.h>
24 #include <lib/zx/socket.h>
25 #include <lib/zxio/zxio.h>
26 #include <unistd.h>
27
28 #include "TraceProviderFuchsia.h"
29 #include "services/service_connector.h"
30 #endif
31
32 #include "HostConnection.h"
33 #include "ProcessPipe.h"
34 #include "ResourceTracker.h"
35 #include "VkEncoder.h"
36 #include "func_table.h"
37
38 // Used when there is no Vulkan support on the host.
39 // Copied from frameworks/native/vulkan/libvulkan/stubhal.cpp
40 namespace vkstubhal {
41
NoOp()42 [[noreturn]] VKAPI_ATTR void NoOp() {
43 LOG_ALWAYS_FATAL("invalid stub function called");
44 }
45
46 VkResult
EnumerateInstanceExtensionProperties(const char *,uint32_t * count,VkExtensionProperties *)47 EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
48 uint32_t* count,
49 VkExtensionProperties* /*properties*/) {
50 AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceExtensionProperties");
51 *count = 0;
52 return VK_SUCCESS;
53 }
54
55 VkResult
EnumerateInstanceLayerProperties(uint32_t * count,VkLayerProperties *)56 EnumerateInstanceLayerProperties(uint32_t* count,
57 VkLayerProperties* /*properties*/) {
58 AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceLayerProperties");
59 *count = 0;
60 return VK_SUCCESS;
61 }
62
CreateInstance(const VkInstanceCreateInfo *,const VkAllocationCallbacks *,VkInstance * instance)63 VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
64 const VkAllocationCallbacks* /*allocator*/,
65 VkInstance* instance) {
66 AEMU_SCOPED_TRACE("vkstubhal::CreateInstance");
67 auto dispatch = new hwvulkan_dispatch_t;
68 dispatch->magic = HWVULKAN_DISPATCH_MAGIC;
69 *instance = reinterpret_cast<VkInstance>(dispatch);
70 return VK_SUCCESS;
71 }
72
DestroyInstance(VkInstance instance,const VkAllocationCallbacks *)73 void DestroyInstance(VkInstance instance,
74 const VkAllocationCallbacks* /*allocator*/) {
75 AEMU_SCOPED_TRACE("vkstubhal::DestroyInstance");
76 auto dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(instance);
77 ALOG_ASSERT(dispatch->magic == HWVULKAN_DISPATCH_MAGIC,
78 "DestroyInstance: invalid instance handle");
79 delete dispatch;
80 }
81
EnumeratePhysicalDevices(VkInstance,uint32_t * count,VkPhysicalDevice *)82 VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
83 uint32_t* count,
84 VkPhysicalDevice* /*gpus*/) {
85 AEMU_SCOPED_TRACE("vkstubhal::EnumeratePhysicalDevices");
86 *count = 0;
87 return VK_SUCCESS;
88 }
89
EnumerateInstanceVersion(uint32_t * pApiVersion)90 VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
91 AEMU_SCOPED_TRACE("vkstubhal::EnumerateInstanceVersion");
92 *pApiVersion = VK_API_VERSION_1_0;
93 return VK_SUCCESS;
94 }
95
96 VkResult
EnumeratePhysicalDeviceGroups(VkInstance,uint32_t * count,VkPhysicalDeviceGroupProperties *)97 EnumeratePhysicalDeviceGroups(VkInstance /*instance*/,
98 uint32_t* count,
99 VkPhysicalDeviceGroupProperties* /*properties*/) {
100 AEMU_SCOPED_TRACE("vkstubhal::EnumeratePhysicalDeviceGroups");
101 *count = 0;
102 return VK_SUCCESS;
103 }
104
105 VkResult
CreateDebugReportCallbackEXT(VkInstance,const VkDebugReportCallbackCreateInfoEXT *,const VkAllocationCallbacks *,VkDebugReportCallbackEXT * pCallback)106 CreateDebugReportCallbackEXT(VkInstance /*instance*/,
107 const VkDebugReportCallbackCreateInfoEXT* /*pCreateInfo*/,
108 const VkAllocationCallbacks* /*pAllocator*/,
109 VkDebugReportCallbackEXT* pCallback)
110 {
111 AEMU_SCOPED_TRACE("vkstubhal::CreateDebugReportCallbackEXT");
112 *pCallback = VK_NULL_HANDLE;
113 return VK_SUCCESS;
114 }
115
116 void
DestroyDebugReportCallbackEXT(VkInstance,VkDebugReportCallbackEXT,const VkAllocationCallbacks *)117 DestroyDebugReportCallbackEXT(VkInstance /*instance*/,
118 VkDebugReportCallbackEXT /*callback*/,
119 const VkAllocationCallbacks* /*pAllocator*/)
120 {
121 AEMU_SCOPED_TRACE("vkstubhal::DestroyDebugReportCallbackEXT");
122 }
123
124 void
DebugReportMessageEXT(VkInstance,VkDebugReportFlagsEXT,VkDebugReportObjectTypeEXT,uint64_t,size_t,int32_t,const char *,const char *)125 DebugReportMessageEXT(VkInstance /*instance*/,
126 VkDebugReportFlagsEXT /*flags*/,
127 VkDebugReportObjectTypeEXT /*objectType*/,
128 uint64_t /*object*/,
129 size_t /*location*/,
130 int32_t /*messageCode*/,
131 const char* /*pLayerPrefix*/,
132 const char* /*pMessage*/)
133 {
134 AEMU_SCOPED_TRACE("vkstubhal::DebugReportMessageEXT");
135 }
136
137 VkResult
CreateDebugUtilsMessengerEXT(VkInstance,const VkDebugUtilsMessengerCreateInfoEXT *,const VkAllocationCallbacks *,VkDebugUtilsMessengerEXT * pMessenger)138 CreateDebugUtilsMessengerEXT(VkInstance /*instance*/,
139 const VkDebugUtilsMessengerCreateInfoEXT* /*pCreateInfo*/,
140 const VkAllocationCallbacks* /*pAllocator*/,
141 VkDebugUtilsMessengerEXT* pMessenger)
142 {
143 AEMU_SCOPED_TRACE("vkstubhal::CreateDebugUtilsMessengerEXT");
144 *pMessenger = VK_NULL_HANDLE;
145 return VK_SUCCESS;
146 }
147
148 void
DestroyDebugUtilsMessengerEXT(VkInstance,VkDebugUtilsMessengerEXT,const VkAllocationCallbacks *)149 DestroyDebugUtilsMessengerEXT(VkInstance /*instance*/,
150 VkDebugUtilsMessengerEXT /*messenger*/,
151 const VkAllocationCallbacks* /*pAllocator*/)
152 {
153 AEMU_SCOPED_TRACE("vkstubhal::DestroyDebugUtilsMessengerkEXT");
154 }
155
156 void
SubmitDebugUtilsMessageEXT(VkInstance,VkDebugUtilsMessageSeverityFlagBitsEXT,VkDebugUtilsMessageTypeFlagsEXT,const VkDebugUtilsMessengerCallbackDataEXT *)157 SubmitDebugUtilsMessageEXT(VkInstance /*instance*/,
158 VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/,
159 VkDebugUtilsMessageTypeFlagsEXT /*messageTypes*/,
160 const VkDebugUtilsMessengerCallbackDataEXT* /*pCallbackData*/)
161 {
162 AEMU_SCOPED_TRACE("vkstubhal::SubmitDebugUtilsMessageEXT");
163 }
164
165 #ifdef VK_USE_PLATFORM_FUCHSIA
166 VkResult
GetMemoryZirconHandleFUCHSIA(VkDevice,const VkMemoryGetZirconHandleInfoFUCHSIA *,uint32_t * pHandle)167 GetMemoryZirconHandleFUCHSIA(VkDevice /*device*/,
168 const VkMemoryGetZirconHandleInfoFUCHSIA* /*pInfo*/,
169 uint32_t* pHandle) {
170 AEMU_SCOPED_TRACE("vkstubhal::GetMemoryZirconHandleFUCHSIA");
171 *pHandle = 0;
172 return VK_SUCCESS;
173 }
174
175 VkResult
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice,VkExternalMemoryHandleTypeFlagBits,uint32_t,VkMemoryZirconHandlePropertiesFUCHSIA *)176 GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice /*device*/,
177 VkExternalMemoryHandleTypeFlagBits /*handleType*/,
178 uint32_t /*handle*/,
179 VkMemoryZirconHandlePropertiesFUCHSIA* /*pProperties*/) {
180 AEMU_SCOPED_TRACE("vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA");
181 return VK_SUCCESS;
182 }
183
184 VkResult
GetSemaphoreZirconHandleFUCHSIA(VkDevice,const VkSemaphoreGetZirconHandleInfoFUCHSIA *,uint32_t * pHandle)185 GetSemaphoreZirconHandleFUCHSIA(VkDevice /*device*/,
186 const VkSemaphoreGetZirconHandleInfoFUCHSIA* /*pInfo*/,
187 uint32_t* pHandle) {
188 AEMU_SCOPED_TRACE("vkstubhal::GetSemaphoreZirconHandleFUCHSIA");
189 *pHandle = 0;
190 return VK_SUCCESS;
191 }
192
193 VkResult
ImportSemaphoreZirconHandleFUCHSIA(VkDevice,const VkImportSemaphoreZirconHandleInfoFUCHSIA *)194 ImportSemaphoreZirconHandleFUCHSIA(VkDevice /*device*/,
195 const VkImportSemaphoreZirconHandleInfoFUCHSIA* /*pInfo*/) {
196 AEMU_SCOPED_TRACE("vkstubhal::ImportSemaphoreZirconHandleFUCHSIA");
197 return VK_SUCCESS;
198 }
199
CreateBufferCollectionFUCHSIA(VkDevice,const VkBufferCollectionCreateInfoFUCHSIA *,const VkAllocationCallbacks *,VkBufferCollectionFUCHSIA *)200 VkResult CreateBufferCollectionFUCHSIA(
201 VkDevice /*device*/,
202 const VkBufferCollectionCreateInfoFUCHSIA* /*pInfo*/,
203 const VkAllocationCallbacks* /*pAllocator*/,
204 VkBufferCollectionFUCHSIA* /*pCollection*/) {
205 AEMU_SCOPED_TRACE("vkstubhal::CreateBufferCollectionFUCHSIA");
206 return VK_SUCCESS;
207 }
208
DestroyBufferCollectionFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkAllocationCallbacks *)209 void DestroyBufferCollectionFUCHSIA(
210 VkDevice /*device*/,
211 VkBufferCollectionFUCHSIA /*collection*/,
212 const VkAllocationCallbacks* /*pAllocator*/) {
213 AEMU_SCOPED_TRACE("vkstubhal::DestroyBufferCollectionFUCHSIA");
214 }
215
SetBufferCollectionImageConstraintsFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkImageConstraintsInfoFUCHSIA *)216 VkResult SetBufferCollectionImageConstraintsFUCHSIA(
217 VkDevice /*device*/,
218 VkBufferCollectionFUCHSIA /*collection*/,
219 const VkImageConstraintsInfoFUCHSIA* /*pImageConstraintsInfo*/) {
220 AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionImageConstraintsFUCHSIA");
221 return VK_SUCCESS;
222 }
223
SetBufferCollectionBufferConstraintsFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkBufferConstraintsInfoFUCHSIA *)224 VkResult SetBufferCollectionBufferConstraintsFUCHSIA(
225 VkDevice /*device*/,
226 VkBufferCollectionFUCHSIA /*collection*/,
227 const VkBufferConstraintsInfoFUCHSIA* /*pBufferConstraintsInfo*/) {
228 AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionBufferConstraintsFUCHSIA");
229 return VK_SUCCESS;
230 }
231
GetBufferCollectionPropertiesFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,VkBufferCollectionPropertiesFUCHSIA *)232 VkResult GetBufferCollectionPropertiesFUCHSIA(
233 VkDevice /*device*/,
234 VkBufferCollectionFUCHSIA /*collection*/,
235 VkBufferCollectionPropertiesFUCHSIA* /*pProperties*/) {
236 AEMU_SCOPED_TRACE("vkstubhal::GetBufferCollectionPropertiesFUCHSIA");
237 return VK_SUCCESS;
238 }
239 #endif
240
GetInstanceProcAddr(VkInstance instance,const char * name)241 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
242 const char* name) {
243 AEMU_SCOPED_TRACE("vkstubhal::GetInstanceProcAddr");
244 if (strcmp(name, "vkCreateInstance") == 0)
245 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
246 if (strcmp(name, "vkDestroyInstance") == 0)
247 return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
248 if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
249 return reinterpret_cast<PFN_vkVoidFunction>(
250 EnumerateInstanceExtensionProperties);
251 if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
252 return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
253 if (strcmp(name, "vkEnumerateInstanceVersion") == 0)
254 return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
255 if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
256 return reinterpret_cast<PFN_vkVoidFunction>(
257 EnumeratePhysicalDeviceGroups);
258 if (strcmp(name, "vkEnumeratePhysicalDeviceGroupsKHR") == 0)
259 return reinterpret_cast<PFN_vkVoidFunction>(
260 EnumeratePhysicalDeviceGroups);
261 if (strcmp(name, "vkGetInstanceProcAddr") == 0)
262 return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
263 if (strcmp(name, "vkCreateDebugReportCallbackEXT") == 0)
264 return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT);
265 if (strcmp(name, "vkDestroyDebugReportCallbackEXT") == 0)
266 return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT);
267 if (strcmp(name, "vkDebugReportMessageEXT") == 0)
268 return reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT);
269 if (strcmp(name, "vkCreateDebugUtilsMessengerEXT") == 0)
270 return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugUtilsMessengerEXT);
271 if (strcmp(name, "vkDestroyDebugUtilsMessengerEXT") == 0)
272 return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugUtilsMessengerEXT);
273 if (strcmp(name, "vkSubmitDebugUtilsMessageEXT") == 0)
274 return reinterpret_cast<PFN_vkVoidFunction>(SubmitDebugUtilsMessageEXT);
275 #ifdef VK_USE_PLATFORM_FUCHSIA
276 if (strcmp(name, "vkGetMemoryZirconHandleFUCHSIA") == 0)
277 return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandleFUCHSIA);
278 if (strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA") == 0)
279 return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandlePropertiesFUCHSIA);
280 if (strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA") == 0)
281 return reinterpret_cast<PFN_vkVoidFunction>(GetSemaphoreZirconHandleFUCHSIA);
282 if (strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA") == 0)
283 return reinterpret_cast<PFN_vkVoidFunction>(ImportSemaphoreZirconHandleFUCHSIA);
284 if (strcmp(name, "vkCreateBufferCollectionFUCHSIA") == 0)
285 return reinterpret_cast<PFN_vkVoidFunction>(
286 CreateBufferCollectionFUCHSIA);
287 if (strcmp(name, "vkDestroyBufferCollectionFUCHSIA") == 0)
288 return reinterpret_cast<PFN_vkVoidFunction>(
289 DestroyBufferCollectionFUCHSIA);
290 if (strcmp(name, "vkSetBufferCollectionImageConstraintsFUCHSIA") == 0)
291 return reinterpret_cast<PFN_vkVoidFunction>(
292 SetBufferCollectionImageConstraintsFUCHSIA);
293 if (strcmp(name, "vkSetBufferCollectionBufferConstraintsFUCHSIA") == 0)
294 return reinterpret_cast<PFN_vkVoidFunction>(
295 SetBufferCollectionBufferConstraintsFUCHSIA);
296 if (strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA") == 0)
297 return reinterpret_cast<PFN_vkVoidFunction>(
298 GetBufferCollectionPropertiesFUCHSIA);
299 #endif
300 // Return NoOp for entrypoints that should never be called.
301 if (strcmp(name, "vkGetPhysicalDeviceFeatures") == 0 ||
302 strcmp(name, "vkGetPhysicalDeviceProperties") == 0 ||
303 strcmp(name, "vkGetPhysicalDeviceFormatProperties") == 0 ||
304 strcmp(name, "vkGetPhysicalDeviceImageFormatProperties") == 0 ||
305 strcmp(name, "vkGetPhysicalDeviceMemoryProperties") == 0 ||
306 strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties") == 0 ||
307 strcmp(name, "vkGetDeviceProcAddr") == 0 ||
308 strcmp(name, "vkCreateDevice") == 0 ||
309 strcmp(name, "vkEnumerateDeviceExtensionProperties") == 0 ||
310 strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties") == 0 ||
311 strcmp(name, "vkGetPhysicalDeviceFeatures2") == 0 ||
312 strcmp(name, "vkGetPhysicalDeviceProperties2") == 0 ||
313 strcmp(name, "vkGetPhysicalDeviceFormatProperties2") == 0 ||
314 strcmp(name, "vkGetPhysicalDeviceImageFormatProperties2") == 0 ||
315 strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties2") == 0 ||
316 strcmp(name, "vkGetPhysicalDeviceMemoryProperties2") == 0 ||
317 strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties2") == 0 ||
318 strcmp(name, "vkGetPhysicalDeviceExternalBufferProperties") == 0 ||
319 strcmp(name, "vkGetPhysicalDeviceExternalFenceProperties") == 0 ||
320 strcmp(name, "vkGetPhysicalDeviceExternalSemaphoreProperties") == 0)
321 return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
322
323 // Per the spec, return NULL for nonexistent entrypoints.
324 return nullptr;
325 }
326
327 } // namespace vkstubhal
328
329 namespace {
330
331 #ifdef VK_USE_PLATFORM_ANDROID_KHR
332
333 int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
334
335 hw_module_methods_t goldfish_vulkan_module_methods = {
336 .open = OpenDevice
337 };
338
339 extern "C" __attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
340 .common = {
341 .tag = HARDWARE_MODULE_TAG,
342 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
343 .hal_api_version = HARDWARE_HAL_API_VERSION,
344 .id = HWVULKAN_HARDWARE_MODULE_ID,
345 .name = "Goldfish Vulkan Driver",
346 .author = "The Android Open Source Project",
347 .methods = &goldfish_vulkan_module_methods,
348 },
349 };
350
CloseDevice(struct hw_device_t *)351 int CloseDevice(struct hw_device_t* /*device*/) {
352 AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
353 // nothing to do - opening a device doesn't allocate any resources
354 return 0;
355 }
356
357 #endif
358
359 #define VK_HOST_CONNECTION(ret) \
360 HostConnection *hostCon = HostConnection::getOrCreate(VIRTIO_GPU_CAPSET_GFXSTREAM); \
361 if (!hostCon) { \
362 ALOGE("vulkan: Failed to get host connection\n"); \
363 return ret; \
364 } \
365 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
366 if (!rcEnc) { \
367 ALOGE("vulkan: Failed to get renderControl encoder context\n"); \
368 return ret; \
369 } \
370 gfxstream::vk::ResourceTracker::ThreadingCallbacks threadingCallbacks = { \
371 [] { \
372 auto hostCon = HostConnection::get(); \
373 hostCon->rcEncoder(); \
374 return hostCon; \
375 }, \
376 [](HostConnection* hostCon) { return hostCon->vkEncoder(); }, \
377 }; \
378 gfxstream::vk::ResourceTracker::get()->setThreadingCallbacks(threadingCallbacks); \
379 gfxstream::vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const()); \
380 gfxstream::vk::ResourceTracker::get()->setupCaps(); \
381 gfxstream::vk::ResourceTracker::get()->setSeqnoPtr(getSeqnoPtrForProcess()); \
382 auto hostSupportsVulkan = gfxstream::vk::ResourceTracker::get()->hostSupportsVulkan(); \
383 gfxstream::vk::VkEncoder *vkEnc = hostCon->vkEncoder(); \
384 if (!vkEnc) { \
385 ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
386 return ret; \
387 } \
388
389 VKAPI_ATTR
EnumerateInstanceExtensionProperties(const char * layer_name,uint32_t * count,VkExtensionProperties * properties)390 VkResult EnumerateInstanceExtensionProperties(
391 const char* layer_name,
392 uint32_t* count,
393 VkExtensionProperties* properties) {
394 AEMU_SCOPED_TRACE("goldfish_vulkan::EnumerateInstanceExtensionProperties");
395
396 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
397
398 if (!hostSupportsVulkan) {
399 return vkstubhal::EnumerateInstanceExtensionProperties(layer_name, count, properties);
400 }
401
402 if (layer_name) {
403 ALOGW(
404 "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
405 "with a layer name ('%s')",
406 layer_name);
407 }
408
409 VkResult res = gfxstream::vk::ResourceTracker::get()->on_vkEnumerateInstanceExtensionProperties(
410 vkEnc, VK_SUCCESS, layer_name, count, properties);
411
412 return res;
413 }
414
415 VKAPI_ATTR
CreateInstance(const VkInstanceCreateInfo * create_info,const VkAllocationCallbacks * allocator,VkInstance * out_instance)416 VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
417 const VkAllocationCallbacks* allocator,
418 VkInstance* out_instance) {
419 AEMU_SCOPED_TRACE("goldfish_vulkan::CreateInstance");
420
421 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
422
423 if (!hostSupportsVulkan) {
424 return vkstubhal::CreateInstance(create_info, allocator, out_instance);
425 }
426
427 VkResult res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance, true /* do lock */);
428
429 return res;
430 }
431
432 #ifdef VK_USE_PLATFORM_FUCHSIA
433 VKAPI_ATTR
GetMemoryZirconHandleFUCHSIA(VkDevice device,const VkMemoryGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)434 VkResult GetMemoryZirconHandleFUCHSIA(
435 VkDevice device,
436 const VkMemoryGetZirconHandleInfoFUCHSIA* pInfo,
437 uint32_t* pHandle) {
438 AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandleFUCHSIA");
439
440 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
441
442 if (!hostSupportsVulkan) {
443 return vkstubhal::GetMemoryZirconHandleFUCHSIA(device, pInfo, pHandle);
444 }
445
446 VkResult res = gfxstream::vk::ResourceTracker::get()->
447 on_vkGetMemoryZirconHandleFUCHSIA(
448 vkEnc, VK_SUCCESS,
449 device, pInfo, pHandle);
450
451 return res;
452 }
453
454 VKAPI_ATTR
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice device,VkExternalMemoryHandleTypeFlagBits handleType,uint32_t handle,VkMemoryZirconHandlePropertiesFUCHSIA * pProperties)455 VkResult GetMemoryZirconHandlePropertiesFUCHSIA(
456 VkDevice device,
457 VkExternalMemoryHandleTypeFlagBits handleType,
458 uint32_t handle,
459 VkMemoryZirconHandlePropertiesFUCHSIA* pProperties) {
460 AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandlePropertiesFUCHSIA");
461
462 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
463
464 if (!hostSupportsVulkan) {
465 return vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA(
466 device, handleType, handle, pProperties);
467 }
468
469 VkResult res = gfxstream::vk::ResourceTracker::get()->
470 on_vkGetMemoryZirconHandlePropertiesFUCHSIA(
471 vkEnc, VK_SUCCESS, device, handleType, handle, pProperties);
472
473 return res;
474 }
475
476 VKAPI_ATTR
GetSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkSemaphoreGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)477 VkResult GetSemaphoreZirconHandleFUCHSIA(
478 VkDevice device,
479 const VkSemaphoreGetZirconHandleInfoFUCHSIA* pInfo,
480 uint32_t* pHandle) {
481 AEMU_SCOPED_TRACE("goldfish_vulkan::GetSemaphoreZirconHandleFUCHSIA");
482
483 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
484
485 if (!hostSupportsVulkan) {
486 return vkstubhal::GetSemaphoreZirconHandleFUCHSIA(device, pInfo, pHandle);
487 }
488
489 VkResult res = gfxstream::vk::ResourceTracker::get()->
490 on_vkGetSemaphoreZirconHandleFUCHSIA(
491 vkEnc, VK_SUCCESS, device, pInfo, pHandle);
492
493 return res;
494 }
495
496 VKAPI_ATTR
ImportSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkImportSemaphoreZirconHandleInfoFUCHSIA * pInfo)497 VkResult ImportSemaphoreZirconHandleFUCHSIA(
498 VkDevice device,
499 const VkImportSemaphoreZirconHandleInfoFUCHSIA* pInfo) {
500 AEMU_SCOPED_TRACE("goldfish_vulkan::ImportSemaphoreZirconHandleFUCHSIA");
501
502 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
503
504 if (!hostSupportsVulkan) {
505 return vkstubhal::ImportSemaphoreZirconHandleFUCHSIA(device, pInfo);
506 }
507
508 VkResult res = gfxstream::vk::ResourceTracker::get()->
509 on_vkImportSemaphoreZirconHandleFUCHSIA(
510 vkEnc, VK_SUCCESS, device, pInfo);
511
512 return res;
513 }
514
515 VKAPI_ATTR
CreateBufferCollectionFUCHSIA(VkDevice device,const VkBufferCollectionCreateInfoFUCHSIA * pInfo,const VkAllocationCallbacks * pAllocator,VkBufferCollectionFUCHSIA * pCollection)516 VkResult CreateBufferCollectionFUCHSIA(
517 VkDevice device,
518 const VkBufferCollectionCreateInfoFUCHSIA* pInfo,
519 const VkAllocationCallbacks* pAllocator,
520 VkBufferCollectionFUCHSIA* pCollection) {
521 AEMU_SCOPED_TRACE("goldfish_vulkan::CreateBufferCollectionFUCHSIA");
522
523 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
524
525 if (!hostSupportsVulkan) {
526 return vkstubhal::CreateBufferCollectionFUCHSIA(
527 device, pInfo, pAllocator, pCollection);
528 }
529
530 VkResult res =
531 gfxstream::vk::ResourceTracker::get()->on_vkCreateBufferCollectionFUCHSIA(
532 vkEnc, VK_SUCCESS, device, pInfo, pAllocator, pCollection);
533
534 return res;
535 }
536
537 VKAPI_ATTR
DestroyBufferCollectionFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkAllocationCallbacks * pAllocator)538 void DestroyBufferCollectionFUCHSIA(VkDevice device,
539 VkBufferCollectionFUCHSIA collection,
540 const VkAllocationCallbacks* pAllocator) {
541 AEMU_SCOPED_TRACE("goldfish_vulkan::DestroyBufferCollectionFUCHSIA");
542
543 VK_HOST_CONNECTION()
544
545 if (!hostSupportsVulkan) {
546 vkstubhal::DestroyBufferCollectionFUCHSIA(device, collection,
547 pAllocator);
548 return;
549 }
550
551 gfxstream::vk::ResourceTracker::get()->on_vkDestroyBufferCollectionFUCHSIA(
552 vkEnc, VK_SUCCESS, device, collection, pAllocator);
553 }
554
555 VKAPI_ATTR
SetBufferCollectionBufferConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkBufferConstraintsInfoFUCHSIA * pBufferConstraintsInfo)556 VkResult SetBufferCollectionBufferConstraintsFUCHSIA(
557 VkDevice device,
558 VkBufferCollectionFUCHSIA collection,
559 const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo) {
560 AEMU_SCOPED_TRACE(
561 "goldfish_vulkan::SetBufferCollectionBufferConstraintsFUCHSIA");
562
563 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
564
565 if (!hostSupportsVulkan) {
566 return vkstubhal::SetBufferCollectionBufferConstraintsFUCHSIA(
567 device, collection, pBufferConstraintsInfo);
568 }
569
570 VkResult res =
571 gfxstream::vk::ResourceTracker::get()
572 ->on_vkSetBufferCollectionBufferConstraintsFUCHSIA(
573 vkEnc, VK_SUCCESS, device, collection, pBufferConstraintsInfo);
574
575 return res;
576 }
577
578 VKAPI_ATTR
SetBufferCollectionImageConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkImageConstraintsInfoFUCHSIA * pImageConstraintsInfo)579 VkResult SetBufferCollectionImageConstraintsFUCHSIA(
580 VkDevice device,
581 VkBufferCollectionFUCHSIA collection,
582 const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo) {
583 AEMU_SCOPED_TRACE(
584 "goldfish_vulkan::SetBufferCollectionBufferConstraintsFUCHSIA");
585
586 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
587
588 if (!hostSupportsVulkan) {
589 return vkstubhal::SetBufferCollectionImageConstraintsFUCHSIA(
590 device, collection, pImageConstraintsInfo);
591 }
592
593 VkResult res =
594 gfxstream::vk::ResourceTracker::get()
595 ->on_vkSetBufferCollectionImageConstraintsFUCHSIA(
596 vkEnc, VK_SUCCESS, device, collection, pImageConstraintsInfo);
597
598 return res;
599 }
600
601 VKAPI_ATTR
GetBufferCollectionPropertiesFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,VkBufferCollectionPropertiesFUCHSIA * pProperties)602 VkResult GetBufferCollectionPropertiesFUCHSIA(
603 VkDevice device,
604 VkBufferCollectionFUCHSIA collection,
605 VkBufferCollectionPropertiesFUCHSIA* pProperties) {
606 AEMU_SCOPED_TRACE("goldfish_vulkan::GetBufferCollectionPropertiesFUCHSIA");
607
608 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
609
610 if (!hostSupportsVulkan) {
611 return vkstubhal::GetBufferCollectionPropertiesFUCHSIA(
612 device, collection, pProperties);
613 }
614
615 VkResult res = gfxstream::vk::ResourceTracker::get()
616 ->on_vkGetBufferCollectionPropertiesFUCHSIA(
617 vkEnc, VK_SUCCESS, device, collection, pProperties);
618
619 return res;
620 }
621
622 #endif
623
currGuestTimeNs()624 uint64_t currGuestTimeNs() {
625 struct timespec ts;
626 #ifdef __APPLE__
627 clock_gettime(CLOCK_REALTIME, &ts);
628 #else
629 clock_gettime(CLOCK_BOOTTIME, &ts);
630 #endif
631 uint64_t res = (uint64_t)(ts.tv_sec * 1000000000ULL + ts.tv_nsec);
632 return res;
633 }
634
635 struct FrameTracingState {
636 uint32_t frameNumber = 0;
637 bool tracingEnabled = false;
onSwapBuffersSuccessful__anon7cffe3450111::FrameTracingState638 void onSwapBuffersSuccessful(ExtendedRCEncoderContext* rcEnc) {
639 #ifdef GFXSTREAM
640 bool current = android::base::isTracingEnabled();
641 // edge trigger
642 if (current && !tracingEnabled) {
643 if (rcEnc->hasHostSideTracing()) {
644 rcEnc->rcSetTracingForPuid(rcEnc, getPuid(), 1, currGuestTimeNs());
645 }
646 }
647 if (!current && tracingEnabled) {
648 if (rcEnc->hasHostSideTracing()) {
649 rcEnc->rcSetTracingForPuid(rcEnc, getPuid(), 0, currGuestTimeNs());
650 }
651 }
652 tracingEnabled = current;
653 #endif
654 ++frameNumber;
655 }
656 };
657
658 static FrameTracingState sFrameTracingState;
659
660 static PFN_vkVoidFunction sQueueSignalReleaseImageAndroidImpl = 0;
661
662 #ifdef VK_USE_PLATFORM_ANDROID_KHR
663 static VkResult
QueueSignalReleaseImageANDROID(VkQueue queue,uint32_t waitSemaphoreCount,const VkSemaphore * pWaitSemaphores,VkImage image,int * pNativeFenceFd)664 QueueSignalReleaseImageANDROID(
665 VkQueue queue,
666 uint32_t waitSemaphoreCount,
667 const VkSemaphore* pWaitSemaphores,
668 VkImage image,
669 int* pNativeFenceFd)
670 {
671 sFrameTracingState.onSwapBuffersSuccessful(HostConnection::get()->rcEncoder());
672 ((PFN_vkQueueSignalReleaseImageANDROID)sQueueSignalReleaseImageAndroidImpl)(queue, waitSemaphoreCount, pWaitSemaphores, image, pNativeFenceFd);
673 return VK_SUCCESS;
674 }
675 #endif
676
GetDeviceProcAddr(VkDevice device,const char * name)677 static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
678 AEMU_SCOPED_TRACE("goldfish_vulkan::GetDeviceProcAddr");
679
680 VK_HOST_CONNECTION(nullptr)
681
682 if (!hostSupportsVulkan) {
683 return nullptr;
684 }
685
686 #ifdef VK_USE_PLATFORM_FUCHSIA
687 if (!strcmp(name, "vkGetMemoryZirconHandleFUCHSIA")) {
688 return (PFN_vkVoidFunction)GetMemoryZirconHandleFUCHSIA;
689 }
690 if (!strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) {
691 return (PFN_vkVoidFunction)GetMemoryZirconHandlePropertiesFUCHSIA;
692 }
693 if (!strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA")) {
694 return (PFN_vkVoidFunction)GetSemaphoreZirconHandleFUCHSIA;
695 }
696 if (!strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA")) {
697 return (PFN_vkVoidFunction)ImportSemaphoreZirconHandleFUCHSIA;
698 }
699 if (!strcmp(name, "vkCreateBufferCollectionFUCHSIA")) {
700 return (PFN_vkVoidFunction)CreateBufferCollectionFUCHSIA;
701 }
702 if (!strcmp(name, "vkDestroyBufferCollectionFUCHSIA")) {
703 return (PFN_vkVoidFunction)DestroyBufferCollectionFUCHSIA;
704 }
705 if (!strcmp(name, "vkSetBufferCollectionImageConstraintsFUCHSIA")) {
706 return (PFN_vkVoidFunction)SetBufferCollectionImageConstraintsFUCHSIA;
707 }
708 if (!strcmp(name, "vkSetBufferCollectionBufferConstraintsFUCHSIA")) {
709 return (PFN_vkVoidFunction)SetBufferCollectionBufferConstraintsFUCHSIA;
710 }
711 if (!strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA")) {
712 return (PFN_vkVoidFunction)GetBufferCollectionPropertiesFUCHSIA;
713 }
714 #endif
715 #ifdef VK_USE_PLATFORM_ANDROID_KHR
716 if (!strcmp(name, "vkQueueSignalReleaseImageANDROID")) {
717 if (!sQueueSignalReleaseImageAndroidImpl) {
718 sQueueSignalReleaseImageAndroidImpl =
719 (PFN_vkVoidFunction)(
720 gfxstream::vk::goldfish_vulkan_get_device_proc_address(device, "vkQueueSignalReleaseImageANDROID"));
721 }
722 return (PFN_vkVoidFunction)QueueSignalReleaseImageANDROID;
723 }
724 #endif
725 if (!strcmp(name, "vkGetDeviceProcAddr")) {
726 return (PFN_vkVoidFunction)(GetDeviceProcAddr);
727 }
728 return (PFN_vkVoidFunction)(gfxstream::vk::goldfish_vulkan_get_device_proc_address(device, name));
729 }
730
731 VKAPI_ATTR
GetInstanceProcAddr(VkInstance instance,const char * name)732 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
733 AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
734
735 VK_HOST_CONNECTION(nullptr)
736
737 if (!hostSupportsVulkan) {
738 return vkstubhal::GetInstanceProcAddr(instance, name);
739 }
740
741 if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
742 return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
743 }
744 if (!strcmp(name, "vkCreateInstance")) {
745 return (PFN_vkVoidFunction)CreateInstance;
746 }
747 if (!strcmp(name, "vkGetDeviceProcAddr")) {
748 return (PFN_vkVoidFunction)(GetDeviceProcAddr);
749 }
750 #ifdef VK_USE_PLATFORM_ANDROID_KHR
751 if (!strcmp(name, "vkQueueSignalReleaseImageANDROID")) {
752 if (!sQueueSignalReleaseImageAndroidImpl) {
753 sQueueSignalReleaseImageAndroidImpl =
754 (PFN_vkVoidFunction)(
755 gfxstream::vk::goldfish_vulkan_get_instance_proc_address(instance, "vkQueueSignalReleaseImageANDROID"));
756 }
757 return (PFN_vkVoidFunction)QueueSignalReleaseImageANDROID;
758 }
759 #endif
760 return (PFN_vkVoidFunction)(gfxstream::vk::goldfish_vulkan_get_instance_proc_address(instance, name));
761 }
762
763 #ifdef VK_USE_PLATFORM_ANDROID_KHR
764
765 hwvulkan_device_t goldfish_vulkan_device = {
766 .common = {
767 .tag = HARDWARE_DEVICE_TAG,
768 .version = HWVULKAN_DEVICE_API_VERSION_0_1,
769 .module = &HAL_MODULE_INFO_SYM.common,
770 .close = CloseDevice,
771 },
772 .EnumerateInstanceExtensionProperties = EnumerateInstanceExtensionProperties,
773 .CreateInstance = CreateInstance,
774 .GetInstanceProcAddr = GetInstanceProcAddr,
775 };
776
OpenDevice(const hw_module_t *,const char * id,hw_device_t ** device)777 int OpenDevice(const hw_module_t* /*module*/,
778 const char* id,
779 hw_device_t** device) {
780 AEMU_SCOPED_TRACE("goldfish_vulkan::OpenDevice");
781
782 if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
783 *device = &goldfish_vulkan_device.common;
784 gfxstream::vk::ResourceTracker::get();
785 return 0;
786 }
787 return -ENOENT;
788 }
789
790 #elif VK_USE_PLATFORM_FUCHSIA
791
792 class VulkanDevice {
793 public:
VulkanDevice()794 VulkanDevice() : mHostSupportsGoldfish(IsAccessible(QEMU_PIPE_PATH)) {
795 InitLogger();
796 InitTraceProvider();
797 gfxstream::vk::ResourceTracker::get();
798 }
799
800 static void InitLogger();
801
IsAccessible(const char * name)802 static bool IsAccessible(const char* name) {
803 zx_handle_t handle = GetConnectToServiceFunction()(name);
804 if (handle == ZX_HANDLE_INVALID)
805 return false;
806
807 zxio_storage_t io_storage;
808 zx_status_t status = zxio_create(handle, &io_storage);
809 if (status != ZX_OK)
810 return false;
811
812 status = zxio_close(&io_storage.io, /*should_wait=*/true);
813 if (status != ZX_OK)
814 return false;
815
816 return true;
817 }
818
GetInstance()819 static VulkanDevice& GetInstance() {
820 static VulkanDevice g_instance;
821 return g_instance;
822 }
823
GetInstanceProcAddr(VkInstance instance,const char * name)824 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
825 if (!mHostSupportsGoldfish) {
826 return vkstubhal::GetInstanceProcAddr(instance, name);
827 }
828 return ::GetInstanceProcAddr(instance, name);
829 }
830
831 private:
832 void InitTraceProvider();
833
834 TraceProviderFuchsia mTraceProvider;
835 const bool mHostSupportsGoldfish;
836 };
837
InitLogger()838 void VulkanDevice::InitLogger() {
839 auto log_socket = ([] () -> std::optional<zx::socket> {
840 fidl::ClientEnd<fuchsia_logger::LogSink> channel{zx::channel{
841 GetConnectToServiceFunction()("/svc/fuchsia.logger.LogSink")}};
842 if (!channel.is_valid())
843 return std::nullopt;
844
845 zx::socket local_socket, remote_socket;
846 zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local_socket, &remote_socket);
847 if (status != ZX_OK)
848 return std::nullopt;
849
850 auto result = fidl::WireCall(channel)->Connect(std::move(remote_socket));
851
852 if (!result.ok())
853 return std::nullopt;
854
855 return local_socket;
856 })();
857 if (!log_socket)
858 return;
859
860 fx_logger_config_t config = {
861 .min_severity = FX_LOG_INFO,
862 .log_sink_socket = log_socket->release(),
863 .tags = nullptr,
864 .num_tags = 0,
865 };
866
867 fx_log_reconfigure(&config);
868 }
869
InitTraceProvider()870 void VulkanDevice::InitTraceProvider() {
871 if (!mTraceProvider.Initialize()) {
872 ALOGE("Trace provider failed to initialize");
873 }
874 }
875
876 extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction
vk_icdGetInstanceProcAddr(VkInstance instance,const char * name)877 vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) {
878 return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name);
879 }
880
881 extern "C" __attribute__((visibility("default"))) VkResult
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)882 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
883 *pSupportedVersion = std::min(*pSupportedVersion, 3u);
884 return VK_SUCCESS;
885 }
886
887 typedef VkResult(VKAPI_PTR *PFN_vkOpenInNamespaceAddr)(const char *pName, uint32_t handle);
888
889 namespace {
890
891 PFN_vkOpenInNamespaceAddr g_vulkan_connector;
892
LocalConnectToServiceFunction(const char * pName)893 zx_handle_t LocalConnectToServiceFunction(const char* pName) {
894 zx::channel remote_endpoint, local_endpoint;
895 zx_status_t status;
896 if ((status = zx::channel::create(0, &remote_endpoint, &local_endpoint)) != ZX_OK) {
897 ALOGE("zx::channel::create failed: %d", status);
898 return ZX_HANDLE_INVALID;
899 }
900 if ((status = g_vulkan_connector(pName, remote_endpoint.release())) != ZX_OK) {
901 ALOGE("vulkan_connector failed: %d", status);
902 return ZX_HANDLE_INVALID;
903 }
904 return local_endpoint.release();
905 }
906
907 }
908
909 extern "C" __attribute__((visibility("default"))) void
vk_icdInitializeOpenInNamespaceCallback(PFN_vkOpenInNamespaceAddr callback)910 vk_icdInitializeOpenInNamespaceCallback(PFN_vkOpenInNamespaceAddr callback) {
911 g_vulkan_connector = callback;
912 SetConnectToServiceFunction(&LocalConnectToServiceFunction);
913 }
914
915 #else
916 class VulkanDevice {
917 public:
VulkanDevice()918 VulkanDevice() {
919 gfxstream::vk::ResourceTracker::get();
920 }
921
GetInstance()922 static VulkanDevice& GetInstance() {
923 static VulkanDevice g_instance;
924 return g_instance;
925 }
926
GetInstanceProcAddr(VkInstance instance,const char * name)927 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
928 return ::GetInstanceProcAddr(instance, name);
929 }
930 };
931
932 extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction
vk_icdGetInstanceProcAddr(VkInstance instance,const char * name)933 vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) {
934 return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name);
935 }
936
937 extern "C" __attribute__((visibility("default"))) VkResult
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)938 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
939 *pSupportedVersion = std::min(*pSupportedVersion, 3u);
940 return VK_SUCCESS;
941 }
942
943 #endif
944
945 } // namespace
946