• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #ifndef VKR_COMMON_H
7 #define VKR_COMMON_H
8 
9 #include "config.h"
10 
11 #include <assert.h>
12 #include <errno.h>
13 #include <inttypes.h>
14 #include <stdatomic.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include "c11/threads.h"
22 #include "pipe/p_compiler.h"
23 #include "util/hash_table.h"
24 #include "util/os_misc.h"
25 #include "util/u_double_list.h"
26 #include "util/u_math.h"
27 #include "util/u_memory.h"
28 #include "util/u_pointer.h"
29 #include "util/u_thread.h"
30 #include "venus-protocol/vulkan.h"
31 #include "virgl_util.h"
32 #include "virglrenderer.h"
33 #include "vrend_debug.h"
34 
35 #include "vkr_renderer.h"
36 
37 /* cap instance and device api versions to this */
38 #define VKR_MAX_API_VERSION VK_API_VERSION_1_3
39 
40 #define VKR_DEBUG(category) (unlikely(vkr_debug_flags & VKR_DEBUG_##category))
41 
42 /* define a type-safe cast function */
43 #define VKR_DEFINE_OBJECT_CAST(vkr_type, vk_enum, vk_type)                               \
44    static inline struct vkr_##vkr_type *vkr_##vkr_type##_from_handle(vk_type handle)     \
45    {                                                                                     \
46       struct vkr_##vkr_type *obj = (struct vkr_##vkr_type *)(uintptr_t)handle;           \
47       if (obj) {                                                                         \
48          assert(obj->base.type == vk_enum);                                              \
49          assert(obj->base.id);                                                           \
50          assert(obj->base.handle.vkr_type);                                              \
51          assert((uintptr_t)obj->base.handle.vkr_type == obj->base.handle.u64);           \
52       }                                                                                  \
53       return obj;                                                                        \
54    }
55 
56 /* vkr_region_is_valid should be used to check for overflows */
57 #define VKR_REGION_INIT(offset, size)                                                    \
58    {                                                                                     \
59       .begin = (offset), .end = (offset) + (size)                                        \
60    }
61 
62 struct vn_info_extension_table;
63 struct vkr_context;
64 struct vkr_instance;
65 struct vkr_physical_device;
66 struct vkr_device;
67 struct vkr_queue;
68 struct vkr_fence;
69 struct vkr_semaphore;
70 struct vkr_event;
71 struct vkr_device_memory;
72 struct vkr_buffer;
73 struct vkr_buffer_view;
74 struct vkr_image;
75 struct vkr_image_view;
76 struct vkr_sampler;
77 struct vkr_sampler_ycbcr_conversion;
78 struct vkr_descriptor_set_layout;
79 struct vkr_descriptor_pool;
80 struct vkr_descriptor_set;
81 struct vkr_descriptor_update_template;
82 struct vkr_render_pass;
83 struct vkr_framebuffer;
84 struct vkr_query_pool;
85 struct vkr_shader_module;
86 struct vkr_pipeline_layout;
87 struct vkr_pipeline_cache;
88 struct vkr_pipeline;
89 struct vkr_command_pool;
90 struct vkr_command_buffer;
91 
92 typedef uint64_t vkr_object_id;
93 
94 enum vkr_debug_flags {
95    VKR_DEBUG_VALIDATE = 1 << 0,
96 };
97 
98 /* base class for all objects */
99 struct vkr_object {
100    VkObjectType type;
101    vkr_object_id id;
102 
103    union {
104       uint64_t u64;
105 
106       VkInstance instance;
107       VkPhysicalDevice physical_device;
108       VkDevice device;
109       VkQueue queue;
110       VkCommandBuffer command_buffer;
111 
112       VkBuffer buffer;
113       VkImage image;
114       VkSemaphore semaphore;
115       VkFence fence;
116       VkDeviceMemory device_memory;
117       VkEvent event;
118       VkQueryPool query_pool;
119       VkBufferView buffer_view;
120       VkImageView image_view;
121       VkShaderModule shader_module;
122       VkPipelineCache pipeline_cache;
123       VkPipelineLayout pipeline_layout;
124       VkPipeline pipeline;
125       VkRenderPass render_pass;
126       VkDescriptorSetLayout descriptor_set_layout;
127       VkSampler sampler;
128       VkDescriptorSet descriptor_set;
129       VkDescriptorPool descriptor_pool;
130       VkFramebuffer framebuffer;
131       VkCommandPool command_pool;
132       VkSamplerYcbcrConversion sampler_ycbcr_conversion;
133       VkDescriptorUpdateTemplate descriptor_update_template;
134    } handle;
135 
136    struct list_head track_head;
137 };
138 
139 struct object_array {
140    uint32_t count;
141    void **objects;
142    void *handle_storage;
143 
144    /* true if the ownership of the objects has been transferred (to
145     * vkr_context::object_table)
146     */
147    bool objects_stolen;
148 };
149 
150 struct vkr_region {
151    size_t begin;
152    size_t end;
153 };
154 
155 extern uint32_t vkr_renderer_flags;
156 extern uint32_t vkr_debug_flags;
157 
158 void
159 vkr_log(const char *fmt, ...);
160 
161 static inline uint32_t
vkr_api_version_cap_minor(uint32_t version,uint32_t cap)162 vkr_api_version_cap_minor(uint32_t version, uint32_t cap)
163 {
164    assert(VK_API_VERSION_MAJOR(version) == VK_API_VERSION_MAJOR(cap));
165    if (VK_API_VERSION_MINOR(version) > VK_API_VERSION_MINOR(cap))
166       version = cap - VK_API_VERSION_PATCH(cap) + VK_API_VERSION_PATCH(version);
167    return version;
168 }
169 
170 void
171 vkr_extension_table_init(struct vn_info_extension_table *table,
172                          const char *const *exts,
173                          uint32_t count);
174 
175 uint32_t
176 vkr_extension_get_spec_version(const char *name);
177 
178 bool
179 object_array_init(struct vkr_context *ctx,
180                   struct object_array *arr,
181                   uint32_t count,
182                   VkObjectType obj_type,
183                   size_t obj_size,
184                   size_t handle_size,
185                   const void *handles);
186 
187 void
188 object_array_fini(struct object_array *arr);
189 
190 static inline void *
vkr_find_struct(const void * chain,VkStructureType type)191 vkr_find_struct(const void *chain, VkStructureType type)
192 {
193    VkBaseOutStructure *s = (VkBaseOutStructure *)chain;
194    while (s) {
195       if (s->sType == type)
196          return s;
197       s = s->pNext;
198    }
199    return NULL;
200 }
201 
202 /*
203  * Find struct in the pNext of chain and return its previous struct.
204  */
205 static inline void *
vkr_find_prev_struct(const void * chain,VkStructureType type)206 vkr_find_prev_struct(const void *chain, VkStructureType type)
207 {
208    VkBaseOutStructure *prev = (VkBaseOutStructure *)chain;
209    while (prev->pNext) {
210       if (prev->pNext->sType == type)
211          return prev;
212       prev = prev->pNext;
213    }
214    return NULL;
215 }
216 
217 static inline bool
vkr_is_recognized_object_type(VkObjectType type)218 vkr_is_recognized_object_type(VkObjectType type)
219 {
220    switch (type) {
221    /* VK_VERSION_1_0 */
222    case VK_OBJECT_TYPE_INSTANCE:
223    case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
224    case VK_OBJECT_TYPE_DEVICE:
225    case VK_OBJECT_TYPE_QUEUE:
226    case VK_OBJECT_TYPE_SEMAPHORE:
227    case VK_OBJECT_TYPE_COMMAND_BUFFER:
228    case VK_OBJECT_TYPE_FENCE:
229    case VK_OBJECT_TYPE_DEVICE_MEMORY:
230    case VK_OBJECT_TYPE_BUFFER:
231    case VK_OBJECT_TYPE_IMAGE:
232    case VK_OBJECT_TYPE_EVENT:
233    case VK_OBJECT_TYPE_QUERY_POOL:
234    case VK_OBJECT_TYPE_BUFFER_VIEW:
235    case VK_OBJECT_TYPE_IMAGE_VIEW:
236    case VK_OBJECT_TYPE_SHADER_MODULE:
237    case VK_OBJECT_TYPE_PIPELINE_CACHE:
238    case VK_OBJECT_TYPE_PIPELINE_LAYOUT:
239    case VK_OBJECT_TYPE_RENDER_PASS:
240    case VK_OBJECT_TYPE_PIPELINE:
241    case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:
242    case VK_OBJECT_TYPE_SAMPLER:
243    case VK_OBJECT_TYPE_DESCRIPTOR_POOL:
244    case VK_OBJECT_TYPE_DESCRIPTOR_SET:
245    case VK_OBJECT_TYPE_FRAMEBUFFER:
246    case VK_OBJECT_TYPE_COMMAND_POOL:
247    /* VK_VERSION_1_1 */
248    case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:
249    case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:
250       return true;
251    default:
252       return false;
253    }
254 }
255 
256 static inline void *
vkr_object_alloc(size_t size,VkObjectType type,vkr_object_id id)257 vkr_object_alloc(size_t size, VkObjectType type, vkr_object_id id)
258 {
259    assert(size >= sizeof(struct vkr_object));
260    assert(vkr_is_recognized_object_type(type));
261 
262    struct vkr_object *obj = calloc(1, size);
263    if (!obj)
264       return NULL;
265 
266    /* obj is only half-initialized */
267    obj->type = type;
268    obj->id = id;
269 
270    return obj;
271 }
272 
273 static inline bool
vkr_region_is_valid(const struct vkr_region * region)274 vkr_region_is_valid(const struct vkr_region *region)
275 {
276    return region->begin <= region->end;
277 }
278 
279 static inline size_t
vkr_region_size(const struct vkr_region * region)280 vkr_region_size(const struct vkr_region *region)
281 {
282    return region->end - region->begin;
283 }
284 
285 static inline bool
vkr_region_is_aligned(const struct vkr_region * region,size_t align)286 vkr_region_is_aligned(const struct vkr_region *region, size_t align)
287 {
288    assert(util_is_power_of_two_nonzero(align));
289    return !((region->begin | region->end) & (align - 1));
290 }
291 
292 static inline bool
vkr_region_is_disjoint(const struct vkr_region * region,const struct vkr_region * other)293 vkr_region_is_disjoint(const struct vkr_region *region, const struct vkr_region *other)
294 {
295    return region->begin >= other->end || region->end <= other->begin;
296 }
297 
298 static inline bool
vkr_region_is_within(const struct vkr_region * region,const struct vkr_region * other)299 vkr_region_is_within(const struct vkr_region *region, const struct vkr_region *other)
300 {
301    /* note that when region regresses to a point at other->end, both this
302     * function and vkr_region_is_disjoint return true
303     */
304    return region->begin >= other->begin && region->end <= other->end;
305 }
306 
307 static inline struct vkr_region
vkr_region_make_relative(const struct vkr_region * region)308 vkr_region_make_relative(const struct vkr_region *region)
309 {
310    return (struct vkr_region){
311       .end = region->end - region->begin,
312    };
313 }
314 
315 #endif /* VKR_COMMON_H */
316