1 /*
2 * Copyright 2018 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5 #include "Resources.h"
6
7 #include <stdlib.h>
8
9 #include "util/log.h"
10
11 #define GOLDFISH_VK_OBJECT_DEBUG 0
12
13 #if GOLDFISH_VK_OBJECT_DEBUG
14 #define D(fmt, ...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__);
15 #else
16 #ifndef D
17 #define D(fmt, ...)
18 #endif
19 #endif
20
21 extern "C" {
22
23 #if defined(__ANDROID__) || defined(__Fuchsia__)
24 #define SET_HWVULKAN_DISPATCH_MAGIC res->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
25 #elif defined(__linux__)
26 #define SET_HWVULKAN_DISPATCH_MAGIC res->loaderData.loaderMagic = ICD_LOADER_MAGIC;
27 #else
28 #define SET_HWVULKAN_DISPATCH_MAGIC
29 #endif
30
31 #define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL(type) \
32 type new_from_host_##type(type underlying) { \
33 struct goldfish_##type* res = \
34 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
35 if (!res) { \
36 mesa_loge("FATAL: Failed to alloc " #type " handle"); \
37 abort(); \
38 } \
39 SET_HWVULKAN_DISPATCH_MAGIC \
40 res->underlying = (uint64_t)underlying; \
41 res->lastUsedEncoder = nullptr; \
42 res->sequenceNumber = 0; \
43 res->privateEncoder = 0; \
44 res->privateStream = 0; \
45 res->flags = 0; \
46 res->poolObjects = 0; \
47 res->subObjects = 0; \
48 res->superObjects = 0; \
49 res->userPtr = 0; \
50 return reinterpret_cast<type>(res); \
51 }
52
53 #define GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_IMPL(type) \
54 type new_from_host_##type(type underlying) { \
55 struct goldfish_##type* res = \
56 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
57 res->underlying = (uint64_t)underlying; \
58 res->poolObjects = 0; \
59 res->subObjects = 0; \
60 res->superObjects = 0; \
61 res->userPtr = 0; \
62 return reinterpret_cast<type>(res); \
63 }
64
65 #define GOLDFISH_VK_AS_GOLDFISH_IMPL(type) \
66 struct goldfish_##type* as_goldfish_##type(type toCast) { \
67 return reinterpret_cast<goldfish_##type*>(toCast); \
68 }
69
70 #define GOLDFISH_VK_GET_HOST_IMPL(type) \
71 type get_host_##type(type toUnwrap) { \
72 if (!toUnwrap) return VK_NULL_HANDLE; \
73 auto as_goldfish = as_goldfish_##type(toUnwrap); \
74 return (type)(as_goldfish->underlying); \
75 }
76
77 #define GOLDFISH_VK_DELETE_GOLDFISH_IMPL(type) \
78 void delete_goldfish_##type(type toDelete) { \
79 D("guest %p", toDelete); \
80 free(as_goldfish_##type(toDelete)); \
81 }
82
83 #define GOLDFISH_VK_IDENTITY_IMPL(type) \
84 type vk_handle_identity_##type(type handle) { return handle; }
85
86 #define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_U64_IMPL(type) \
87 type new_from_host_u64_##type(uint64_t underlying) { \
88 struct goldfish_##type* res = \
89 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
90 if (!res) { \
91 mesa_loge("FATAL: Failed to alloc " #type " handle"); \
92 abort(); \
93 } \
94 SET_HWVULKAN_DISPATCH_MAGIC \
95 res->underlying = underlying; \
96 res->lastUsedEncoder = nullptr; \
97 res->sequenceNumber = 0; \
98 res->privateEncoder = 0; \
99 res->privateStream = 0; \
100 res->flags = 0; \
101 res->poolObjects = 0; \
102 res->subObjects = 0; \
103 res->superObjects = 0; \
104 res->userPtr = 0; \
105 return reinterpret_cast<type>(res); \
106 }
107
108 #define GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_U64_IMPL(type) \
109 type new_from_host_u64_##type(uint64_t underlying) { \
110 struct goldfish_##type* res = \
111 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
112 res->underlying = underlying; \
113 D("guest %p: host u64: 0x%llx", res, (unsigned long long)res->underlying); \
114 res->poolObjects = 0; \
115 res->subObjects = 0; \
116 res->superObjects = 0; \
117 res->userPtr = 0; \
118 return reinterpret_cast<type>(res); \
119 }
120
121 #define GOLDFISH_VK_GET_HOST_U64_IMPL(type) \
122 uint64_t get_host_u64_##type(type toUnwrap) { \
123 if (!toUnwrap) return 0; \
124 auto as_goldfish = as_goldfish_##type(toUnwrap); \
125 D("guest %p: host u64: 0x%llx", toUnwrap, (unsigned long long)as_goldfish->underlying); \
126 return as_goldfish->underlying; \
127 }
128
129 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL)
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)130 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)
131 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_IMPL)
132 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_IMPL)
133 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_IMPL)
134 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_U64_IMPL)
135 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_IMPL)
136
137 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)
138 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_IMPL)
139 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_IMPL)
140 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_IMPL)
141 GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(
142 GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_IMPL)
143 GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(
144 GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_U64_IMPL)
145 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_IMPL)
146
147 VkDescriptorPool new_from_host_VkDescriptorPool(VkDescriptorPool underlying) {
148 struct goldfish_VkDescriptorPool* res =
149 static_cast<goldfish_VkDescriptorPool*>(malloc(sizeof(goldfish_VkDescriptorPool)));
150 res->underlying = (uint64_t)underlying;
151 res->allocInfo = nullptr;
152 return reinterpret_cast<VkDescriptorPool>(res);
153 }
154
new_from_host_u64_VkDescriptorPool(uint64_t underlying)155 VkDescriptorPool new_from_host_u64_VkDescriptorPool(uint64_t underlying) {
156 return new_from_host_VkDescriptorPool((VkDescriptorPool)underlying);
157 }
158
new_from_host_VkDescriptorSet(VkDescriptorSet underlying)159 VkDescriptorSet new_from_host_VkDescriptorSet(VkDescriptorSet underlying) {
160 struct goldfish_VkDescriptorSet* res =
161 static_cast<goldfish_VkDescriptorSet*>(malloc(sizeof(goldfish_VkDescriptorSet)));
162 res->underlying = (uint64_t)underlying;
163 res->reified = nullptr;
164 return reinterpret_cast<VkDescriptorSet>(res);
165 }
166
new_from_host_u64_VkDescriptorSet(uint64_t underlying)167 VkDescriptorSet new_from_host_u64_VkDescriptorSet(uint64_t underlying) {
168 return new_from_host_VkDescriptorSet((VkDescriptorSet)underlying);
169 }
170
new_from_host_VkDescriptorSetLayout(VkDescriptorSetLayout underlying)171 VkDescriptorSetLayout new_from_host_VkDescriptorSetLayout(VkDescriptorSetLayout underlying) {
172 struct goldfish_VkDescriptorSetLayout* res = static_cast<goldfish_VkDescriptorSetLayout*>(
173 malloc(sizeof(goldfish_VkDescriptorSetLayout)));
174 res->underlying = (uint64_t)underlying;
175 res->layoutInfo = nullptr;
176 return reinterpret_cast<VkDescriptorSetLayout>(res);
177 }
178
new_from_host_u64_VkDescriptorSetLayout(uint64_t underlying)179 VkDescriptorSetLayout new_from_host_u64_VkDescriptorSetLayout(uint64_t underlying) {
180 return new_from_host_VkDescriptorSetLayout((VkDescriptorSetLayout)underlying);
181 }
182
183 } // extern "C"
184
185 namespace gfxstream {
186 namespace vk {
187
appendObject(struct goldfish_vk_object_list ** begin,void * val)188 void appendObject(struct goldfish_vk_object_list** begin, void* val) {
189 D("for %p", val);
190 struct goldfish_vk_object_list* o = new goldfish_vk_object_list;
191 o->next = nullptr;
192 o->obj = val;
193 D("new ptr: %p", o);
194 if (!*begin) {
195 D("first");
196 *begin = o;
197 return;
198 }
199
200 struct goldfish_vk_object_list* q = *begin;
201 struct goldfish_vk_object_list* p = q;
202
203 while (q) {
204 p = q;
205 q = q->next;
206 }
207
208 D("set next of %p to %p", p, o);
209 p->next = o;
210 }
211
eraseObject(struct goldfish_vk_object_list ** begin,void * val)212 void eraseObject(struct goldfish_vk_object_list** begin, void* val) {
213 D("for val %p", val);
214 if (!*begin) {
215 D("val %p notfound", val);
216 return;
217 }
218
219 struct goldfish_vk_object_list* q = *begin;
220 struct goldfish_vk_object_list* p = q;
221
222 while (q) {
223 struct goldfish_vk_object_list* n = q->next;
224 if (val == q->obj) {
225 D("val %p found, delete", val);
226 delete q;
227 if (*begin == q) {
228 D("val %p set begin to %p:", val, n);
229 *begin = n;
230 } else {
231 D("val %p set pnext to %p:", val, n);
232 p->next = n;
233 }
234 return;
235 }
236 p = q;
237 q = n;
238 }
239
240 D("val %p notfound after looping", val);
241 }
242
eraseObjects(struct goldfish_vk_object_list ** begin)243 void eraseObjects(struct goldfish_vk_object_list** begin) {
244 struct goldfish_vk_object_list* q = *begin;
245 struct goldfish_vk_object_list* p = q;
246
247 while (q) {
248 p = q;
249 q = q->next;
250 delete p;
251 }
252
253 *begin = nullptr;
254 }
255
forAllObjects(struct goldfish_vk_object_list * begin,std::function<void (void *)> func)256 void forAllObjects(struct goldfish_vk_object_list* begin, std::function<void(void*)> func) {
257 struct goldfish_vk_object_list* q = begin;
258 struct goldfish_vk_object_list* p = q;
259
260 D("call");
261 while (q) {
262 D("iter");
263 p = q;
264 q = q->next;
265 func(p->obj);
266 }
267 }
268
269 } // namespace vk
270 } // namespace gfxstream
271