1 /*
2 * Copyright 2023 Google LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <fidl/fuchsia.logger/cpp/wire.h>
7 #include <lib/syslog/global.h>
8 #include <lib/zx/channel.h>
9 #include <lib/zx/socket.h>
10 #include <lib/zxio/zxio.h>
11 #include <unistd.h>
12
13 #include "TraceProviderFuchsia.h"
14 #include "services/service_connector.h"
15
16 class VulkanDevice {
17 public:
VulkanDevice()18 VulkanDevice() : mHostSupportsGoldfish(IsAccessible(QEMU_PIPE_PATH)) {
19 InitLogger();
20 InitTraceProvider();
21 gfxstream::vk::ResourceTracker::get();
22 }
23
24 static void InitLogger();
25
IsAccessible(const char * name)26 static bool IsAccessible(const char* name) {
27 zx_handle_t handle = GetConnectToServiceFunction()(name);
28 if (handle == ZX_HANDLE_INVALID) return false;
29
30 zxio_storage_t io_storage;
31 zx_status_t status = zxio_create(handle, &io_storage);
32 if (status != ZX_OK) return false;
33
34 status = zxio_close(&io_storage.io, /*should_wait=*/true);
35 if (status != ZX_OK) return false;
36
37 return true;
38 }
39
GetInstance()40 static VulkanDevice& GetInstance() {
41 static VulkanDevice g_instance;
42 return g_instance;
43 }
44
GetInstanceProcAddr(VkInstance instance,const char * name)45 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
46 return ::GetInstanceProcAddr(instance, name);
47 }
48
49 private:
50 void InitTraceProvider();
51
52 TraceProviderFuchsia mTraceProvider;
53 const bool mHostSupportsGoldfish;
54 };
55
InitLogger()56 void VulkanDevice::InitLogger() {
57 auto log_socket = ([]() -> std::optional<zx::socket> {
58 fidl::ClientEnd<fuchsia_logger::LogSink> channel{
59 zx::channel{GetConnectToServiceFunction()("/svc/fuchsia.logger.LogSink")}};
60 if (!channel.is_valid()) return std::nullopt;
61
62 zx::socket local_socket, remote_socket;
63 zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local_socket, &remote_socket);
64 if (status != ZX_OK) return std::nullopt;
65
66 auto result = fidl::WireCall(channel)->Connect(std::move(remote_socket));
67
68 if (!result.ok()) return std::nullopt;
69
70 return local_socket;
71 })();
72 if (!log_socket) return;
73
74 fx_logger_config_t config = {
75 .min_severity = FX_LOG_INFO,
76 .log_sink_socket = log_socket->release(),
77 .tags = nullptr,
78 .num_tags = 0,
79 };
80
81 fx_log_reconfigure(&config);
82 }
83
InitTraceProvider()84 void VulkanDevice::InitTraceProvider() {
85 if (!mTraceProvider.Initialize()) {
86 ALOGE("Trace provider failed to initialize");
87 }
88 }
89
90 typedef VkResult(VKAPI_PTR* PFN_vkOpenInNamespaceAddr)(const char* pName, uint32_t handle);
91
92 namespace {
93
94 PFN_vkOpenInNamespaceAddr g_vulkan_connector;
95
LocalConnectToServiceFunction(const char * pName)96 zx_handle_t LocalConnectToServiceFunction(const char* pName) {
97 zx::channel remote_endpoint, local_endpoint;
98 zx_status_t status;
99 if ((status = zx::channel::create(0, &remote_endpoint, &local_endpoint)) != ZX_OK) {
100 ALOGE("zx::channel::create failed: %d", status);
101 return ZX_HANDLE_INVALID;
102 }
103 if ((status = g_vulkan_connector(pName, remote_endpoint.release())) != ZX_OK) {
104 ALOGE("vulkan_connector failed: %d", status);
105 return ZX_HANDLE_INVALID;
106 }
107 return local_endpoint.release();
108 }
109
110 } // namespace
111
vk_icdInitializeOpenInNamespaceCallback(PFN_vkOpenInNamespaceAddr callback)112 extern "C" __attribute__((visibility("default"))) void vk_icdInitializeOpenInNamespaceCallback(
113 PFN_vkOpenInNamespaceAddr callback) {
114 g_vulkan_connector = callback;
115 SetConnectToServiceFunction(&LocalConnectToServiceFunction);
116 }
117