1 /*
2  * Copyright © 2021 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 #ifndef VK_INSTANCE_H
24 #define VK_INSTANCE_H
25 
26 #include "vk_dispatch_table.h"
27 #include "vk_extensions.h"
28 #include "vk_object.h"
29 
30 #include "c11/threads.h"
31 #include "util/list.h"
32 #include "util/u_debug.h"
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 struct vk_app_info {
39    /** VkApplicationInfo::pApplicationName */
40    const char*        app_name;
41 
42    /** VkApplicationInfo::applicationVersion */
43    uint32_t           app_version;
44 
45    /** VkApplicationInfo::pEngineName */
46    const char*        engine_name;
47 
48    /** VkApplicationInfo::engineVersion */
49    uint32_t           engine_version;
50 
51    /** VkApplicationInfo::apiVersion or `VK_API_VERSION_1_0`
52     *
53     * If the application does not provide a `pApplicationInfo` or the
54     * `apiVersion` field is 0, this is set to `VK_API_VERSION_1_0`.
55     */
56    uint32_t           api_version;
57 };
58 
59 struct _drmDevice;
60 struct vk_physical_device;
61 
62 enum vk_trace_mode {
63    /** Radeon Memory Visualizer */
64    VK_TRACE_MODE_RMV = 1 << 0,
65 
66    /** Number of common trace modes. */
67    VK_TRACE_MODE_COUNT = 1,
68 };
69 
70 /** Base struct for all `VkInstance` implementations
71  *
72  * This contains data structures necessary for detecting enabled extensions,
73  * handling entrypoint dispatch, and implementing `vkGetInstanceProcAddr()`.
74  * It also contains data copied from the `VkInstanceCreateInfo` such as the
75  * application information.
76  */
77 struct vk_instance {
78    struct vk_object_base base;
79 
80    /** Allocator used when creating this instance
81     *
82     * This is used as a fall-back for when a NULL pAllocator is passed into a
83     * device-level create function such as vkCreateImage().
84     */
85    VkAllocationCallbacks alloc;
86 
87    /** VkInstanceCreateInfo::pApplicationInfo */
88    struct vk_app_info app_info;
89 
90    /** Table of all supported instance extensions
91     *
92     * This is the static const struct passed by the driver as the
93     * `supported_extensions` parameter to `vk_instance_init()`.
94     */
95    const struct vk_instance_extension_table *supported_extensions;
96 
97    /** Table of all enabled instance extensions
98     *
99     * This is generated automatically as part of `vk_instance_init()` from
100     * VkInstanceCreateInfo::ppEnabledExtensionNames.
101     */
102    struct vk_instance_extension_table enabled_extensions;
103 
104    /** Instance-level dispatch table */
105    struct vk_instance_dispatch_table dispatch_table;
106 
107    /* VK_EXT_debug_report debug callbacks */
108    struct {
109       mtx_t callbacks_mutex;
110       struct list_head callbacks;
111    } debug_report;
112 
113    /* VK_EXT_debug_utils */
114    struct {
115       /* These callbacks are only used while creating or destroying an
116        * instance
117        */
118       struct list_head instance_callbacks;
119       mtx_t callbacks_mutex;
120       /* Persistent callbacks */
121       struct list_head callbacks;
122    } debug_utils;
123 
124    /** List of all physical devices and callbacks
125    *
126    * This is used for automatic physical device creation,
127    * deletion and enumeration.
128    */
129    struct {
130       struct list_head list;
131       bool enumerated;
132 
133       /** Enumerate physical devices for this instance
134        *
135        * The driver can implement this callback for custom physical device
136        * enumeration. The returned value must be a valid return code of
137        * vkEnumeratePhysicalDevices.
138        *
139        * Note that the loader calls vkEnumeratePhysicalDevices of all
140        * installed ICDs and fails device enumeration when any of the calls
141        * fails. The driver should return VK_SUCCESS when it does not find any
142        * compatible device.
143        *
144        * If this callback is not set, try_create_for_drm will be used for
145        * enumeration.
146        */
147       VkResult (*enumerate)(struct vk_instance *instance);
148 
149       /** Try to create a physical device for a drm device
150        *
151        * The returned value must be a valid return code of
152        * vkEnumeratePhysicalDevices, or VK_ERROR_INCOMPATIBLE_DRIVER. When
153        * VK_ERROR_INCOMPATIBLE_DRIVER is returned, the error and the drm
154        * device are silently ignored.
155        */
156       VkResult (*try_create_for_drm)(struct vk_instance *instance,
157                                      struct _drmDevice *device,
158                                      struct vk_physical_device **out);
159 
160       /** Handle the destruction of a physical device
161        *
162        * This callback has to be implemented when using common physical device
163        * management. The device pointer and any resource allocated for the
164        * device should be freed here.
165        */
166       void (*destroy)(struct vk_physical_device *pdevice);
167 
168       mtx_t mutex;
169    } physical_devices;
170 
171    /** Enabled tracing modes */
172    uint64_t trace_mode;
173 
174    uint32_t trace_frame;
175    char *trace_trigger_file;
176 };
177 
178 VK_DEFINE_HANDLE_CASTS(vk_instance, base, VkInstance,
179                        VK_OBJECT_TYPE_INSTANCE);
180 
181 /** Initialize a vk_instance
182  *
183  * Along with initializing the data structures in `vk_instance`, this function
184  * validates the Vulkan version number provided by the client and checks that
185  * every extension specified by
186  * `VkInstanceCreateInfo::ppEnabledExtensionNames` is actually supported by
187  * the implementation and returns `VK_ERROR_EXTENSION_NOT_PRESENT` if an
188  * unsupported extension is requested.
189  *
190  * @param[out] instance             The instance to initialize
191  * @param[in]  supported_extensions Table of all instance extensions supported
192  *                                  by this instance
193  * @param[in]  dispatch_table       Instance-level dispatch table
194  * @param[in]  pCreateInfo          VkInstanceCreateInfo pointer passed to
195  *                                  `vkCreateInstance()`
196  * @param[in]  alloc                Allocation callbacks used to create this
197  *                                  instance; must not be `NULL`
198  */
199 VkResult MUST_CHECK
200 vk_instance_init(struct vk_instance *instance,
201                  const struct vk_instance_extension_table *supported_extensions,
202                  const struct vk_instance_dispatch_table *dispatch_table,
203                  const VkInstanceCreateInfo *pCreateInfo,
204                  const VkAllocationCallbacks *alloc);
205 
206 /** Tears down a vk_instance
207  *
208  * @param[out] instance             The instance to tear down
209  */
210 void
211 vk_instance_finish(struct vk_instance *instance);
212 
213 /** Implementaiton of vkEnumerateInstanceExtensionProperties() */
214 VkResult
215 vk_enumerate_instance_extension_properties(
216     const struct vk_instance_extension_table *supported_extensions,
217     uint32_t *pPropertyCount,
218     VkExtensionProperties *pProperties);
219 
220 /** Implementaiton of vkGetInstanceProcAddr() */
221 PFN_vkVoidFunction
222 vk_instance_get_proc_addr(const struct vk_instance *instance,
223                           const struct vk_instance_entrypoint_table *entrypoints,
224                           const char *name);
225 
226 /** Unchecked version of vk_instance_get_proc_addr
227  *
228  * This is identical to `vk_instance_get_proc_addr()` except that it doesn't
229  * check whether extensions are enabled before returning function pointers.
230  * This is useful in window-system code where we may use extensions without
231  * the client explicitly enabling them.
232  */
233 PFN_vkVoidFunction
234 vk_instance_get_proc_addr_unchecked(const struct vk_instance *instance,
235                                     const char *name);
236 
237 /** Implementaiton of vk_icdGetPhysicalDeviceProcAddr() */
238 PFN_vkVoidFunction
239 vk_instance_get_physical_device_proc_addr(const struct vk_instance *instance,
240                                           const char *name);
241 
242 void
243 vk_instance_add_driver_trace_modes(struct vk_instance *instance,
244                                    const struct debug_control *modes);
245 
246 #ifdef __cplusplus
247 }
248 #endif
249 
250 #endif /* VK_INSTANCE_H */
251