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 <fuchsia/logger/llcpp/fidl.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 <lib/zxio/inception.h>
27 #include <unistd.h>
28
29 #include "services/service_connector.h"
30 #endif
31
32 #include "HostConnection.h"
33 #include "ResourceTracker.h"
34 #include "VkEncoder.h"
35
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
200 VkResult
CreateBufferCollectionFUCHSIA(VkDevice,const VkBufferCollectionCreateInfoFUCHSIA *,const VkAllocationCallbacks *,VkBufferCollectionFUCHSIA *)201 CreateBufferCollectionFUCHSIA(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
209 void
DestroyBufferCollectionFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkAllocationCallbacks *)210 DestroyBufferCollectionFUCHSIA(VkDevice /*device*/,
211 VkBufferCollectionFUCHSIA /*collection*/,
212 const VkAllocationCallbacks* /*pAllocator*/) {
213 AEMU_SCOPED_TRACE("vkstubhal::DestroyBufferCollectionFUCHSIA");
214 }
215
216 VkResult
SetBufferCollectionConstraintsFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,const VkImageCreateInfo *)217 SetBufferCollectionConstraintsFUCHSIA(VkDevice /*device*/,
218 VkBufferCollectionFUCHSIA /*collection*/,
219 const VkImageCreateInfo* /*pImageInfo*/) {
220 AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionConstraintsFUCHSIA");
221 return VK_SUCCESS;
222 }
223
224 VkResult
GetBufferCollectionPropertiesFUCHSIA(VkDevice,VkBufferCollectionFUCHSIA,VkBufferCollectionPropertiesFUCHSIA *)225 GetBufferCollectionPropertiesFUCHSIA(VkDevice /*device*/,
226 VkBufferCollectionFUCHSIA /*collection*/,
227 VkBufferCollectionPropertiesFUCHSIA* /*pProperties*/) {
228 AEMU_SCOPED_TRACE("vkstubhal::GetBufferCollectionPropertiesFUCHSIA");
229 return VK_SUCCESS;
230 }
231 #endif
232
GetInstanceProcAddr(VkInstance instance,const char * name)233 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
234 const char* name) {
235 AEMU_SCOPED_TRACE("vkstubhal::GetInstanceProcAddr");
236 if (strcmp(name, "vkCreateInstance") == 0)
237 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
238 if (strcmp(name, "vkDestroyInstance") == 0)
239 return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
240 if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
241 return reinterpret_cast<PFN_vkVoidFunction>(
242 EnumerateInstanceExtensionProperties);
243 if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
244 return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
245 if (strcmp(name, "vkEnumerateInstanceVersion") == 0)
246 return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
247 if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
248 return reinterpret_cast<PFN_vkVoidFunction>(
249 EnumeratePhysicalDeviceGroups);
250 if (strcmp(name, "vkEnumeratePhysicalDeviceGroupsKHR") == 0)
251 return reinterpret_cast<PFN_vkVoidFunction>(
252 EnumeratePhysicalDeviceGroups);
253 if (strcmp(name, "vkGetInstanceProcAddr") == 0)
254 return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
255 if (strcmp(name, "vkCreateDebugReportCallbackEXT") == 0)
256 return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT);
257 if (strcmp(name, "vkDestroyDebugReportCallbackEXT") == 0)
258 return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT);
259 if (strcmp(name, "vkDebugReportMessageEXT") == 0)
260 return reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT);
261 if (strcmp(name, "vkCreateDebugUtilsMessengerEXT") == 0)
262 return reinterpret_cast<PFN_vkVoidFunction>(CreateDebugUtilsMessengerEXT);
263 if (strcmp(name, "vkDestroyDebugUtilsMessengerEXT") == 0)
264 return reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugUtilsMessengerEXT);
265 if (strcmp(name, "vkSubmitDebugUtilsMessageEXT") == 0)
266 return reinterpret_cast<PFN_vkVoidFunction>(SubmitDebugUtilsMessageEXT);
267 #ifdef VK_USE_PLATFORM_FUCHSIA
268 if (strcmp(name, "vkGetMemoryZirconHandleFUCHSIA") == 0)
269 return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandleFUCHSIA);
270 if (strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA") == 0)
271 return reinterpret_cast<PFN_vkVoidFunction>(GetMemoryZirconHandlePropertiesFUCHSIA);
272 if (strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA") == 0)
273 return reinterpret_cast<PFN_vkVoidFunction>(GetSemaphoreZirconHandleFUCHSIA);
274 if (strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA") == 0)
275 return reinterpret_cast<PFN_vkVoidFunction>(ImportSemaphoreZirconHandleFUCHSIA);
276 if (strcmp(name, "vkCreateBufferCollectionFUCHSIA") == 0)
277 return reinterpret_cast<PFN_vkVoidFunction>(CreateBufferCollectionFUCHSIA);
278 if (strcmp(name, "vkDestroyBufferCollectionFUCHSIA") == 0)
279 return reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferCollectionFUCHSIA);
280 if (strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA") == 0)
281 return reinterpret_cast<PFN_vkVoidFunction>(SetBufferCollectionConstraintsFUCHSIA);
282 if (strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA") == 0)
283 return reinterpret_cast<PFN_vkVoidFunction>(GetBufferCollectionPropertiesFUCHSIA);
284 #endif
285 // Return NoOp for entrypoints that should never be called.
286 if (strcmp(name, "vkGetPhysicalDeviceFeatures") == 0 ||
287 strcmp(name, "vkGetPhysicalDeviceProperties") == 0 ||
288 strcmp(name, "vkGetPhysicalDeviceFormatProperties") == 0 ||
289 strcmp(name, "vkGetPhysicalDeviceImageFormatProperties") == 0 ||
290 strcmp(name, "vkGetPhysicalDeviceMemoryProperties") == 0 ||
291 strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties") == 0 ||
292 strcmp(name, "vkGetDeviceProcAddr") == 0 ||
293 strcmp(name, "vkCreateDevice") == 0 ||
294 strcmp(name, "vkEnumerateDeviceExtensionProperties") == 0 ||
295 strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties") == 0 ||
296 strcmp(name, "vkGetPhysicalDeviceFeatures2") == 0 ||
297 strcmp(name, "vkGetPhysicalDeviceProperties2") == 0 ||
298 strcmp(name, "vkGetPhysicalDeviceFormatProperties2") == 0 ||
299 strcmp(name, "vkGetPhysicalDeviceImageFormatProperties2") == 0 ||
300 strcmp(name, "vkGetPhysicalDeviceQueueFamilyProperties2") == 0 ||
301 strcmp(name, "vkGetPhysicalDeviceMemoryProperties2") == 0 ||
302 strcmp(name, "vkGetPhysicalDeviceSparseImageFormatProperties2") == 0 ||
303 strcmp(name, "vkGetPhysicalDeviceExternalBufferProperties") == 0 ||
304 strcmp(name, "vkGetPhysicalDeviceExternalFenceProperties") == 0 ||
305 strcmp(name, "vkGetPhysicalDeviceExternalSemaphoreProperties") == 0)
306 return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
307
308 // Per the spec, return NULL for nonexistent entrypoints.
309 return nullptr;
310 }
311
312 } // namespace vkstubhal
313
314 namespace {
315
316 #ifdef VK_USE_PLATFORM_ANDROID_KHR
317
318 int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
319
320 hw_module_methods_t goldfish_vulkan_module_methods = {
321 .open = OpenDevice
322 };
323
324 extern "C" __attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
325 .common = {
326 .tag = HARDWARE_MODULE_TAG,
327 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
328 .hal_api_version = HARDWARE_HAL_API_VERSION,
329 .id = HWVULKAN_HARDWARE_MODULE_ID,
330 .name = "Goldfish Vulkan Driver",
331 .author = "The Android Open Source Project",
332 .methods = &goldfish_vulkan_module_methods,
333 },
334 };
335
CloseDevice(struct hw_device_t *)336 int CloseDevice(struct hw_device_t* /*device*/) {
337 AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
338 // nothing to do - opening a device doesn't allocate any resources
339 return 0;
340 }
341
342 #endif
343
344 #define VK_HOST_CONNECTION(ret) \
345 HostConnection *hostCon = HostConnection::get(); \
346 if (!hostCon) { \
347 ALOGE("vulkan: Failed to get host connection\n"); \
348 return ret; \
349 } \
350 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
351 if (!rcEnc) { \
352 ALOGE("vulkan: Failed to get renderControl encoder context\n"); \
353 return ret; \
354 } \
355 goldfish_vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const()); \
356 goldfish_vk::ResourceTracker::ThreadingCallbacks threadingCallbacks = { \
357 [] { auto hostCon = HostConnection::get(); \
358 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
359 return hostCon; }, \
360 [](HostConnection* hostCon) { return hostCon->vkEncoder(); }, \
361 }; \
362 goldfish_vk::ResourceTracker::get()->setThreadingCallbacks(threadingCallbacks); \
363 auto hostSupportsVulkan = goldfish_vk::ResourceTracker::get()->hostSupportsVulkan(); \
364 goldfish_vk::VkEncoder *vkEnc = hostCon->vkEncoder(); \
365 if (!vkEnc) { \
366 ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
367 return ret; \
368 } \
369
370 VKAPI_ATTR
EnumerateInstanceExtensionProperties(const char * layer_name,uint32_t * count,VkExtensionProperties * properties)371 VkResult EnumerateInstanceExtensionProperties(
372 const char* layer_name,
373 uint32_t* count,
374 VkExtensionProperties* properties) {
375 AEMU_SCOPED_TRACE("goldfish_vulkan::EnumerateInstanceExtensionProperties");
376
377 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
378
379 if (!hostSupportsVulkan) {
380 return vkstubhal::EnumerateInstanceExtensionProperties(layer_name, count, properties);
381 }
382
383 if (layer_name) {
384 ALOGW(
385 "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
386 "with a layer name ('%s')",
387 layer_name);
388 }
389
390 VkResult res = goldfish_vk::ResourceTracker::get()->on_vkEnumerateInstanceExtensionProperties(
391 vkEnc, VK_SUCCESS, layer_name, count, properties);
392
393 return res;
394 }
395
396 VKAPI_ATTR
CreateInstance(const VkInstanceCreateInfo * create_info,const VkAllocationCallbacks * allocator,VkInstance * out_instance)397 VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
398 const VkAllocationCallbacks* allocator,
399 VkInstance* out_instance) {
400 AEMU_SCOPED_TRACE("goldfish_vulkan::CreateInstance");
401
402 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
403
404 if (!hostSupportsVulkan) {
405 return vkstubhal::CreateInstance(create_info, allocator, out_instance);
406 }
407
408 VkResult res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance);
409
410 return res;
411 }
412
413 #ifdef VK_USE_PLATFORM_FUCHSIA
414 VKAPI_ATTR
GetMemoryZirconHandleFUCHSIA(VkDevice device,const VkMemoryGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)415 VkResult GetMemoryZirconHandleFUCHSIA(
416 VkDevice device,
417 const VkMemoryGetZirconHandleInfoFUCHSIA* pInfo,
418 uint32_t* pHandle) {
419 AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandleFUCHSIA");
420
421 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
422
423 if (!hostSupportsVulkan) {
424 return vkstubhal::GetMemoryZirconHandleFUCHSIA(device, pInfo, pHandle);
425 }
426
427 VkResult res = goldfish_vk::ResourceTracker::get()->
428 on_vkGetMemoryZirconHandleFUCHSIA(
429 vkEnc, VK_SUCCESS,
430 device, pInfo, pHandle);
431
432 return res;
433 }
434
435 VKAPI_ATTR
GetMemoryZirconHandlePropertiesFUCHSIA(VkDevice device,VkExternalMemoryHandleTypeFlagBits handleType,uint32_t handle,VkMemoryZirconHandlePropertiesFUCHSIA * pProperties)436 VkResult GetMemoryZirconHandlePropertiesFUCHSIA(
437 VkDevice device,
438 VkExternalMemoryHandleTypeFlagBits handleType,
439 uint32_t handle,
440 VkMemoryZirconHandlePropertiesFUCHSIA* pProperties) {
441 AEMU_SCOPED_TRACE("goldfish_vulkan::GetMemoryZirconHandlePropertiesFUCHSIA");
442
443 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
444
445 if (!hostSupportsVulkan) {
446 return vkstubhal::GetMemoryZirconHandlePropertiesFUCHSIA(
447 device, handleType, handle, pProperties);
448 }
449
450 VkResult res = goldfish_vk::ResourceTracker::get()->
451 on_vkGetMemoryZirconHandlePropertiesFUCHSIA(
452 vkEnc, VK_SUCCESS, device, handleType, handle, pProperties);
453
454 return res;
455 }
456
457 VKAPI_ATTR
GetSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkSemaphoreGetZirconHandleInfoFUCHSIA * pInfo,uint32_t * pHandle)458 VkResult GetSemaphoreZirconHandleFUCHSIA(
459 VkDevice device,
460 const VkSemaphoreGetZirconHandleInfoFUCHSIA* pInfo,
461 uint32_t* pHandle) {
462 AEMU_SCOPED_TRACE("goldfish_vulkan::GetSemaphoreZirconHandleFUCHSIA");
463
464 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
465
466 if (!hostSupportsVulkan) {
467 return vkstubhal::GetSemaphoreZirconHandleFUCHSIA(device, pInfo, pHandle);
468 }
469
470 VkResult res = goldfish_vk::ResourceTracker::get()->
471 on_vkGetSemaphoreZirconHandleFUCHSIA(
472 vkEnc, VK_SUCCESS, device, pInfo, pHandle);
473
474 return res;
475 }
476
477 VKAPI_ATTR
ImportSemaphoreZirconHandleFUCHSIA(VkDevice device,const VkImportSemaphoreZirconHandleInfoFUCHSIA * pInfo)478 VkResult ImportSemaphoreZirconHandleFUCHSIA(
479 VkDevice device,
480 const VkImportSemaphoreZirconHandleInfoFUCHSIA* pInfo) {
481 AEMU_SCOPED_TRACE("goldfish_vulkan::ImportSemaphoreZirconHandleFUCHSIA");
482
483 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
484
485 if (!hostSupportsVulkan) {
486 return vkstubhal::ImportSemaphoreZirconHandleFUCHSIA(device, pInfo);
487 }
488
489 VkResult res = goldfish_vk::ResourceTracker::get()->
490 on_vkImportSemaphoreZirconHandleFUCHSIA(
491 vkEnc, VK_SUCCESS, device, pInfo);
492
493 return res;
494 }
495
496 VKAPI_ATTR
CreateBufferCollectionFUCHSIA(VkDevice device,const VkBufferCollectionCreateInfoFUCHSIA * pInfo,const VkAllocationCallbacks * pAllocator,VkBufferCollectionFUCHSIA * pCollection)497 VkResult CreateBufferCollectionFUCHSIA(
498 VkDevice device,
499 const VkBufferCollectionCreateInfoFUCHSIA* pInfo,
500 const VkAllocationCallbacks* pAllocator,
501 VkBufferCollectionFUCHSIA* pCollection) {
502 AEMU_SCOPED_TRACE("goldfish_vulkan::CreateBufferCollectionFUCHSIA");
503
504 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
505
506 if (!hostSupportsVulkan) {
507 return vkstubhal::CreateBufferCollectionFUCHSIA(device, pInfo, pAllocator, pCollection);
508 }
509
510 VkResult res = goldfish_vk::ResourceTracker::get()->
511 on_vkCreateBufferCollectionFUCHSIA(
512 vkEnc, VK_SUCCESS, device, pInfo, pAllocator, pCollection);
513
514 return res;
515 }
516
517 VKAPI_ATTR
DestroyBufferCollectionFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkAllocationCallbacks * pAllocator)518 void DestroyBufferCollectionFUCHSIA(
519 VkDevice device,
520 VkBufferCollectionFUCHSIA collection,
521 const VkAllocationCallbacks* pAllocator) {
522 AEMU_SCOPED_TRACE("goldfish_vulkan::DestroyBufferCollectionFUCHSIA");
523
524 VK_HOST_CONNECTION()
525
526 if (!hostSupportsVulkan) {
527 vkstubhal::DestroyBufferCollectionFUCHSIA(device, collection, pAllocator);
528 return;
529 }
530
531 goldfish_vk::ResourceTracker::get()->
532 on_vkDestroyBufferCollectionFUCHSIA(
533 vkEnc, VK_SUCCESS, device, collection, pAllocator);
534 }
535
536 VKAPI_ATTR
SetBufferCollectionConstraintsFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,const VkImageCreateInfo * pImageInfo)537 VkResult SetBufferCollectionConstraintsFUCHSIA(
538 VkDevice device,
539 VkBufferCollectionFUCHSIA collection,
540 const VkImageCreateInfo* pImageInfo) {
541 AEMU_SCOPED_TRACE("goldfish_vulkan::SetBufferCollectionConstraintsFUCHSIA");
542
543 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
544
545 if (!hostSupportsVulkan) {
546 return vkstubhal::SetBufferCollectionConstraintsFUCHSIA(device, collection, pImageInfo);
547 }
548
549 VkResult res = goldfish_vk::ResourceTracker::get()->
550 on_vkSetBufferCollectionConstraintsFUCHSIA(
551 vkEnc, VK_SUCCESS, device, collection, pImageInfo);
552
553 return res;
554 }
555
556 VKAPI_ATTR
GetBufferCollectionPropertiesFUCHSIA(VkDevice device,VkBufferCollectionFUCHSIA collection,VkBufferCollectionPropertiesFUCHSIA * pProperties)557 VkResult GetBufferCollectionPropertiesFUCHSIA(
558 VkDevice device,
559 VkBufferCollectionFUCHSIA collection,
560 VkBufferCollectionPropertiesFUCHSIA* pProperties) {
561 AEMU_SCOPED_TRACE("goldfish_vulkan::GetBufferCollectionPropertiesFUCHSIA");
562
563 VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
564
565 if (!hostSupportsVulkan) {
566 return vkstubhal::GetBufferCollectionPropertiesFUCHSIA(device, collection, pProperties);
567 }
568
569 VkResult res = goldfish_vk::ResourceTracker::get()->
570 on_vkGetBufferCollectionPropertiesFUCHSIA(
571 vkEnc, VK_SUCCESS, device, collection, pProperties);
572
573 return res;
574 }
575 #endif
576
GetDeviceProcAddr(VkDevice device,const char * name)577 static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
578 AEMU_SCOPED_TRACE("goldfish_vulkan::GetDeviceProcAddr");
579
580 VK_HOST_CONNECTION(nullptr)
581
582 if (!hostSupportsVulkan) {
583 return nullptr;
584 }
585
586 #ifdef VK_USE_PLATFORM_FUCHSIA
587 if (!strcmp(name, "vkGetMemoryZirconHandleFUCHSIA")) {
588 return (PFN_vkVoidFunction)GetMemoryZirconHandleFUCHSIA;
589 }
590 if (!strcmp(name, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) {
591 return (PFN_vkVoidFunction)GetMemoryZirconHandlePropertiesFUCHSIA;
592 }
593 if (!strcmp(name, "vkGetSemaphoreZirconHandleFUCHSIA")) {
594 return (PFN_vkVoidFunction)GetSemaphoreZirconHandleFUCHSIA;
595 }
596 if (!strcmp(name, "vkImportSemaphoreZirconHandleFUCHSIA")) {
597 return (PFN_vkVoidFunction)ImportSemaphoreZirconHandleFUCHSIA;
598 }
599 if (!strcmp(name, "vkCreateBufferCollectionFUCHSIA")) {
600 return (PFN_vkVoidFunction)CreateBufferCollectionFUCHSIA;
601 }
602 if (!strcmp(name, "vkDestroyBufferCollectionFUCHSIA")) {
603 return (PFN_vkVoidFunction)DestroyBufferCollectionFUCHSIA;
604 }
605 if (!strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA")) {
606 return (PFN_vkVoidFunction)SetBufferCollectionConstraintsFUCHSIA;
607 }
608 if (!strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA")) {
609 return (PFN_vkVoidFunction)GetBufferCollectionPropertiesFUCHSIA;
610 }
611 #endif
612 if (!strcmp(name, "vkGetDeviceProcAddr")) {
613 return (PFN_vkVoidFunction)(GetDeviceProcAddr);
614 }
615 return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_device_proc_address(device, name));
616 }
617
618 VKAPI_ATTR
GetInstanceProcAddr(VkInstance instance,const char * name)619 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
620 AEMU_SCOPED_TRACE("goldfish_vulkan::GetInstanceProcAddr");
621
622 VK_HOST_CONNECTION(nullptr)
623
624 if (!hostSupportsVulkan) {
625 return vkstubhal::GetInstanceProcAddr(instance, name);
626 }
627
628 if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
629 return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
630 }
631 if (!strcmp(name, "vkCreateInstance")) {
632 return (PFN_vkVoidFunction)CreateInstance;
633 }
634 if (!strcmp(name, "vkGetDeviceProcAddr")) {
635 return (PFN_vkVoidFunction)(GetDeviceProcAddr);
636 }
637 return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_instance_proc_address(instance, name));
638 }
639
640 #ifdef VK_USE_PLATFORM_ANDROID_KHR
641
642 hwvulkan_device_t goldfish_vulkan_device = {
643 .common = {
644 .tag = HARDWARE_DEVICE_TAG,
645 .version = HWVULKAN_DEVICE_API_VERSION_0_1,
646 .module = &HAL_MODULE_INFO_SYM.common,
647 .close = CloseDevice,
648 },
649 .EnumerateInstanceExtensionProperties = EnumerateInstanceExtensionProperties,
650 .CreateInstance = CreateInstance,
651 .GetInstanceProcAddr = GetInstanceProcAddr,
652 };
653
OpenDevice(const hw_module_t *,const char * id,hw_device_t ** device)654 int OpenDevice(const hw_module_t* /*module*/,
655 const char* id,
656 hw_device_t** device) {
657 AEMU_SCOPED_TRACE("goldfish_vulkan::OpenDevice");
658
659 if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
660 *device = &goldfish_vulkan_device.common;
661 goldfish_vk::ResourceTracker::get();
662 return 0;
663 }
664 return -ENOENT;
665 }
666
667 #endif
668
669 #ifdef VK_USE_PLATFORM_FUCHSIA
670
671 class VulkanDevice {
672 public:
VulkanDevice()673 VulkanDevice() : mHostSupportsGoldfish(IsAccessible(QEMU_PIPE_PATH)) {
674 InitLogger();
675 goldfish_vk::ResourceTracker::get();
676 }
677
678 static void InitLogger();
679
IsAccessible(const char * name)680 static bool IsAccessible(const char* name) {
681 zx_handle_t handle = GetConnectToServiceFunction()(name);
682 if (handle == ZX_HANDLE_INVALID)
683 return false;
684
685 zxio_storage_t io_storage;
686 zx_status_t status = zxio_remote_init(&io_storage, handle, ZX_HANDLE_INVALID);
687 if (status != ZX_OK)
688 return false;
689
690 zxio_node_attr_t attr;
691 status = zxio_attr_get(&io_storage.io, &attr);
692 zxio_close(&io_storage.io);
693 if (status != ZX_OK)
694 return false;
695
696 return true;
697 }
698
GetInstance()699 static VulkanDevice& GetInstance() {
700 static VulkanDevice g_instance;
701 return g_instance;
702 }
703
GetInstanceProcAddr(VkInstance instance,const char * name)704 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
705 if (!mHostSupportsGoldfish) {
706 return vkstubhal::GetInstanceProcAddr(instance, name);
707 }
708 return ::GetInstanceProcAddr(instance, name);
709 }
710
711 private:
712 const bool mHostSupportsGoldfish;
713 };
714
InitLogger()715 void VulkanDevice::InitLogger() {
716 zx_handle_t channel = GetConnectToServiceFunction()("/svc/fuchsia.logger.LogSink");
717 if (channel == ZX_HANDLE_INVALID)
718 return;
719
720 zx::socket local_socket, remote_socket;
721 zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local_socket, &remote_socket);
722 if (status != ZX_OK)
723 return;
724
725 auto result = llcpp::fuchsia::logger::LogSink::Call::Connect(
726 zx::unowned_channel(channel), std::move(remote_socket));
727 zx_handle_close(channel);
728
729 if (result.status() != ZX_OK)
730 return;
731
732 fx_logger_config_t config = {.min_severity = FX_LOG_INFO,
733 .console_fd = -1,
734 .log_service_channel = local_socket.release(),
735 .tags = nullptr,
736 .num_tags = 0};
737
738 fx_log_init_with_config(&config);
739 }
740
741 extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction
vk_icdGetInstanceProcAddr(VkInstance instance,const char * name)742 vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) {
743 return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name);
744 }
745
746 extern "C" __attribute__((visibility("default"))) VkResult
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)747 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
748 *pSupportedVersion = std::min(*pSupportedVersion, 3u);
749 return VK_SUCCESS;
750 }
751
752 typedef VkResult(VKAPI_PTR *PFN_vkConnectToServiceAddr)(const char *pName, uint32_t handle);
753
754 namespace {
755
756 PFN_vkConnectToServiceAddr g_vulkan_connector;
757
LocalConnectToServiceFunction(const char * pName)758 zx_handle_t LocalConnectToServiceFunction(const char* pName) {
759 zx::channel remote_endpoint, local_endpoint;
760 zx_status_t status;
761 if ((status = zx::channel::create(0, &remote_endpoint, &local_endpoint)) != ZX_OK) {
762 ALOGE("zx::channel::create failed: %d", status);
763 return ZX_HANDLE_INVALID;
764 }
765 if ((status = g_vulkan_connector(pName, remote_endpoint.release())) != ZX_OK) {
766 ALOGE("vulkan_connector failed: %d", status);
767 return ZX_HANDLE_INVALID;
768 }
769 return local_endpoint.release();
770 }
771
772 }
773
774 extern "C" __attribute__((visibility("default"))) void
vk_icdInitializeConnectToServiceCallback(PFN_vkConnectToServiceAddr callback)775 vk_icdInitializeConnectToServiceCallback(PFN_vkConnectToServiceAddr callback) {
776 g_vulkan_connector = callback;
777 SetConnectToServiceFunction(&LocalConnectToServiceFunction);
778 }
779
780 #endif
781
782 } // namespace
783