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