1 //
2 // Copyright (C) 2024 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #ifndef VULKAN_XML_H_
18 #define VULKAN_XML_H_
19
20 #include <unistd.h>
21
22 #include <cstdint>
23
24 #include "berberis/base/bit_util.h"
25 #include "berberis/base/struct_check.h"
26 #include "berberis/guest_abi/function_wrappers.h"
27 #include "berberis/guest_abi/guest_arguments.h"
28 #include "berberis/guest_abi/guest_function_wrapper_signature.h"
29 #include "berberis/guest_abi/guest_params.h"
30 #include "berberis/guest_abi/guest_type.h"
31 #include "berberis/guest_state/guest_addr.h"
32 #include "berberis/guest_state/guest_state.h"
33 #include "berberis/runtime_primitives/guest_function_wrapper_impl.h"
34 #include "berberis/runtime_primitives/host_code.h"
35 #include "berberis/runtime_primitives/host_function_wrapper_impl.h"
36 #include "berberis/runtime_primitives/runtime_library.h"
37
38 #include "binary_search.h"
39 // Note: we only need these defines at the end of xvulkan_xml-inl.h and would like to not include it
40 // prematurely but vulkan_xml_define.h couldn't be included from vulkan_xml-inl.h when these two
41 // files are in different filegroups.
42 #include "vulkan_xml_define.h"
43
44 // These are explicitly written here as a workaround. These are platform types that are missing
45 // from vulkan_types. They are implicitly declared in the berberis namespace because the Vulkan
46 // structures that include them use the "struct X* y;" field syntax. However, they belong in the
47 // global namespace to avoid conflicts in files that include the host headers for these types,
48 // which are included via vulkan/vulkan.h.
49 struct AHardwareBuffer;
50 struct ANativeWindow;
51 struct Display;
52 struct wl_display;
53 struct xcb_connection_t;
54
55 namespace berberis {
56
57 template <typename ResultType, typename... ArgumentType>
WrapGuestFunctionIfNeeded(GuestType<ResultType (*)(ArgumentType...)> func,const char * name)58 inline ResultType (*WrapGuestFunctionIfNeeded(GuestType<ResultType (*)(ArgumentType...)> func,
59 const char* name))(ArgumentType...) {
60 auto host_func =
61 reinterpret_cast<ResultType (*)(ArgumentType...)>(UnwrapHostFunction(ToGuestAddr(func)));
62 if (host_func) {
63 return host_func;
64 }
65 return WrapGuestFunction(func, name);
66 }
67
68 template <GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi,
69 typename Func>
WrapHostFunctionIfNeeded(Func func,const char * name)70 inline GuestType<Func> WrapHostFunctionIfNeeded(Func func, const char* name) {
71 auto host_func = UnwrapHostFunction(ToGuestAddr(func));
72 if (!host_func) {
73 WrapHostFunction(func, name);
74 }
75 return func;
76 }
77
78 class GuestHolderBase {
79 public:
80 GuestHolderBase() = default;
81 virtual ~GuestHolderBase() = default;
82 };
83
84 class HostHolderBase {
85 public:
86 HostHolderBase() = default;
87 virtual ~HostHolderBase() = default;
88 };
89
90 // Note: anonymous namespace is subtly different from static: each anonymous namespace has internal
91 // unique name, but is imported into encompassing namespace.
92 //
93 // It's unclear whether it's valid to declare function in one such namespace and then define in the
94 // other one: MSVC says it's impossible, other compilers allow that.
95 //
96 // But even compilers which support such use are confused when friend delaration is used.
97 //
98 // Use of “static” works without any surprises: https://godbolt.org/z/sczb7r5Gn
99 static const void* ConvertOptionalStructures(GuestType<const void*> head,
100 std::unique_ptr<HostHolderBase>& holder,
101 bool& out_of_memory);
102 static void* ConvertOptionalStructures(GuestType<void*> head,
103 std::unique_ptr<HostHolderBase>& holder,
104 bool& out_of_memory);
105 static GuestType<const void*> ConvertOptionalStructures(const void* head,
106 std::unique_ptr<GuestHolderBase>& holder,
107 bool& out_of_memory);
108 static GuestType<void*> ConvertOptionalStructures(void* head,
109 std::unique_ptr<GuestHolderBase>& holder,
110 bool& out_of_memory);
111
112 namespace {
113
114 #define BERBERIS_VK_DEFINE_HANDLE(name) using name = struct name##_T*
115
116 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || \
117 defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || \
118 defined(__powerpc64__)
119 #define BERBERIS_VK_DEFINE_NON_DISPATCHABLE_HANDLE(name) \
120 BERBERIS_VK_DEFINE_HANDLE(name)
121 #else
122 #define BERBERIS_VK_DEFINE_NON_DISPATCHABLE_HANDLE(name) using name = std::uint64_t
123 #endif
124
125 #if defined(_WIN32)
126 // On Windows, Vulkan commands use the stdcall convention
127 #define BERBERIS_VKAPI_PTR __stdcall
128 #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
129 // 32bit Android ARMv6 or earlier don't support Vulkan by design.
130 #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
131 #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
132 // 32bit Android ARMv7+ are using aapcs-vfp.
133 #define BERBERIS_VKAPI_PTR __attribute__((pcs("aapcs-vfp")))
134 #else
135 // On other platforms, use the default calling convention
136 #define BERBERIS_VKAPI_PTR
137 #endif
138
139 // API Constants.
140 // TODO(232598137): Parse them from XML instead.
141 constexpr uint32_t BERBERIS_VK_TRUE = 1;
142 constexpr uint32_t BERBERIS_VK_FALSE = 0;
143
144 #include "vulkan_xml-inl.h" // generated file NOLINT [build/include]
145
146 #endif // VULKAN_XML_H_
147