• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC
3  * SPDX-License-Identifier: MIT
4  *
5  * based in part on anv and radv which are:
6  * Copyright © 2015 Intel Corporation
7  * Copyright © 2016 Red Hat.
8  * Copyright © 2016 Bas Nieuwenhuizen
9  */
10 
11 #include "vn_instance.h"
12 
13 #include "util/driconf.h"
14 #include "venus-protocol/vn_protocol_driver_info.h"
15 #include "venus-protocol/vn_protocol_driver_instance.h"
16 #include "venus-protocol/vn_protocol_driver_transport.h"
17 
18 #include "vn_icd.h"
19 #include "vn_physical_device.h"
20 #include "vn_renderer.h"
21 #include "vn_ring.h"
22 
23 /*
24  * Instance extensions add instance-level or physical-device-level
25  * functionalities.  It seems renderer support is either unnecessary or
26  * optional.  We should be able to advertise them or lie about them locally.
27  */
28 static const struct vk_instance_extension_table
29    vn_instance_supported_extensions = {
30       /* promoted to VK_VERSION_1_1 */
31       .KHR_device_group_creation = true,
32       .KHR_external_fence_capabilities = true,
33       .KHR_external_memory_capabilities = true,
34       .KHR_external_semaphore_capabilities = true,
35       .KHR_get_physical_device_properties2 = true,
36 
37 #ifdef VN_USE_WSI_PLATFORM
38       .KHR_get_surface_capabilities2 = true,
39       .KHR_surface = true,
40       .KHR_surface_protected_capabilities = true,
41 #endif
42 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
43       .KHR_wayland_surface = true,
44 #endif
45 #ifdef VK_USE_PLATFORM_XCB_KHR
46       .KHR_xcb_surface = true,
47 #endif
48 #ifdef VK_USE_PLATFORM_XLIB_KHR
49       .KHR_xlib_surface = true,
50 #endif
51 #ifndef VK_USE_PLATFORM_WIN32_KHR
52       .EXT_headless_surface = true,
53 #endif
54    };
55 
56 static const driOptionDescription vn_dri_options[] = {
57    /* clang-format off */
58    DRI_CONF_SECTION_PERFORMANCE
59       DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT(false)
60       DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
61       DRI_CONF_VK_X11_STRICT_IMAGE_COUNT(false)
62       DRI_CONF_VK_XWAYLAND_WAIT_READY(true)
63       DRI_CONF_VENUS_IMPLICIT_FENCING(false)
64       DRI_CONF_VENUS_WSI_MULTI_PLANE_MODIFIERS(false)
65    DRI_CONF_SECTION_END
66    DRI_CONF_SECTION_DEBUG
67       DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false)
68       DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false)
69    DRI_CONF_SECTION_END
70    /* clang-format on */
71 };
72 
73 static VkResult
vn_instance_init_renderer_versions(struct vn_instance * instance)74 vn_instance_init_renderer_versions(struct vn_instance *instance)
75 {
76    uint32_t instance_version = 0;
77    VkResult result = vn_call_vkEnumerateInstanceVersion(instance->ring.ring,
78                                                         &instance_version);
79    if (result != VK_SUCCESS) {
80       if (VN_DEBUG(INIT))
81          vn_log(instance, "failed to enumerate renderer instance version");
82       return result;
83    }
84 
85    if (instance_version < VN_MIN_RENDERER_VERSION) {
86       if (VN_DEBUG(INIT)) {
87          vn_log(instance, "unsupported renderer instance version %d.%d",
88                 VK_VERSION_MAJOR(instance_version),
89                 VK_VERSION_MINOR(instance_version));
90       }
91       return VK_ERROR_INITIALIZATION_FAILED;
92    }
93 
94    if (VN_DEBUG(INIT)) {
95       vn_log(instance, "renderer instance version %d.%d.%d",
96              VK_VERSION_MAJOR(instance_version),
97              VK_VERSION_MINOR(instance_version),
98              VK_VERSION_PATCH(instance_version));
99    }
100 
101    /* request at least VN_MIN_RENDERER_VERSION internally */
102    instance->renderer_api_version =
103       MAX2(instance->base.base.app_info.api_version, VN_MIN_RENDERER_VERSION);
104 
105    /* instance version for internal use is capped */
106    instance_version = MIN3(instance_version, instance->renderer_api_version,
107                            instance->renderer->info.vk_xml_version);
108    assert(instance_version >= VN_MIN_RENDERER_VERSION);
109 
110    instance->renderer_version = instance_version;
111 
112    return VK_SUCCESS;
113 }
114 
115 static inline void
vn_instance_fini_ring(struct vn_instance * instance)116 vn_instance_fini_ring(struct vn_instance *instance)
117 {
118    vn_watchdog_fini(&instance->ring.watchdog);
119 
120    list_for_each_entry_safe(struct vn_tls_ring, tls_ring,
121                             &instance->ring.tls_rings, vk_head)
122       vn_tls_destroy_ring(tls_ring);
123 
124    vn_ring_destroy(instance->ring.ring);
125 }
126 
127 static VkResult
vn_instance_init_ring(struct vn_instance * instance)128 vn_instance_init_ring(struct vn_instance *instance)
129 {
130    /* 32-bit seqno for renderer roundtrips */
131    static const size_t extra_size = sizeof(uint32_t);
132 
133    /* default instance ring size */
134    static const size_t buf_size = 128 * 1024;
135 
136    /* order of 4 for performant async cmd enqueue */
137    static const uint8_t direct_order = 4;
138 
139    struct vn_ring_layout layout;
140    vn_ring_get_layout(buf_size, extra_size, &layout);
141 
142    instance->ring.ring = vn_ring_create(instance, &layout, direct_order,
143                                         false /* is_tls_ring */);
144    if (!instance->ring.ring)
145       return VK_ERROR_OUT_OF_HOST_MEMORY;
146 
147    list_inithead(&instance->ring.tls_rings);
148 
149    vn_watchdog_init(&instance->ring.watchdog);
150 
151    return VK_SUCCESS;
152 }
153 
154 static VkResult
vn_instance_init_renderer(struct vn_instance * instance)155 vn_instance_init_renderer(struct vn_instance *instance)
156 {
157    const VkAllocationCallbacks *alloc = &instance->base.base.alloc;
158 
159    VkResult result = vn_renderer_create(instance, alloc, &instance->renderer);
160    if (result != VK_SUCCESS)
161       return result;
162 
163    struct vn_renderer_info *renderer_info = &instance->renderer->info;
164    uint32_t version = vn_info_wire_format_version();
165    if (renderer_info->wire_format_version != version) {
166       if (VN_DEBUG(INIT)) {
167          vn_log(instance, "wire format version %d != %d",
168                 renderer_info->wire_format_version, version);
169       }
170       return VK_ERROR_INITIALIZATION_FAILED;
171    }
172 
173    version = vn_info_vk_xml_version();
174    if (renderer_info->vk_xml_version > version)
175       renderer_info->vk_xml_version = version;
176    if (renderer_info->vk_xml_version < VN_MIN_RENDERER_VERSION) {
177       if (VN_DEBUG(INIT)) {
178          vn_log(instance, "vk xml version %d.%d.%d < %d.%d.%d",
179                 VK_VERSION_MAJOR(renderer_info->vk_xml_version),
180                 VK_VERSION_MINOR(renderer_info->vk_xml_version),
181                 VK_VERSION_PATCH(renderer_info->vk_xml_version),
182                 VK_VERSION_MAJOR(VN_MIN_RENDERER_VERSION),
183                 VK_VERSION_MINOR(VN_MIN_RENDERER_VERSION),
184                 VK_VERSION_PATCH(VN_MIN_RENDERER_VERSION));
185       }
186       return VK_ERROR_INITIALIZATION_FAILED;
187    }
188 
189    uint32_t spec_version =
190       vn_extension_get_spec_version("VK_EXT_command_serialization");
191    if (renderer_info->vk_ext_command_serialization_spec_version >
192        spec_version) {
193       renderer_info->vk_ext_command_serialization_spec_version = spec_version;
194    }
195 
196    spec_version = vn_extension_get_spec_version("VK_MESA_venus_protocol");
197    if (renderer_info->vk_mesa_venus_protocol_spec_version > spec_version)
198       renderer_info->vk_mesa_venus_protocol_spec_version = spec_version;
199 
200    if (VN_DEBUG(INIT)) {
201       vn_log(instance, "connected to renderer");
202       vn_log(instance, "wire format version %d",
203              renderer_info->wire_format_version);
204       vn_log(instance, "vk xml version %d.%d.%d",
205              VK_VERSION_MAJOR(renderer_info->vk_xml_version),
206              VK_VERSION_MINOR(renderer_info->vk_xml_version),
207              VK_VERSION_PATCH(renderer_info->vk_xml_version));
208       vn_log(instance, "VK_EXT_command_serialization spec version %d",
209              renderer_info->vk_ext_command_serialization_spec_version);
210       vn_log(instance, "VK_MESA_venus_protocol spec version %d",
211              renderer_info->vk_mesa_venus_protocol_spec_version);
212    }
213 
214    return VK_SUCCESS;
215 }
216 
217 /* instance commands */
218 
219 VkResult
vn_EnumerateInstanceVersion(uint32_t * pApiVersion)220 vn_EnumerateInstanceVersion(uint32_t *pApiVersion)
221 {
222    *pApiVersion = VN_MAX_API_VERSION;
223    return VK_SUCCESS;
224 }
225 
226 VkResult
vn_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)227 vn_EnumerateInstanceExtensionProperties(const char *pLayerName,
228                                         uint32_t *pPropertyCount,
229                                         VkExtensionProperties *pProperties)
230 {
231    if (pLayerName)
232       return vn_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
233 
234    return vk_enumerate_instance_extension_properties(
235       &vn_instance_supported_extensions, pPropertyCount, pProperties);
236 }
237 
238 VkResult
vn_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)239 vn_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
240                                     VkLayerProperties *pProperties)
241 {
242    *pPropertyCount = 0;
243    return VK_SUCCESS;
244 }
245 
246 VkResult
vn_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)247 vn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
248                   const VkAllocationCallbacks *pAllocator,
249                   VkInstance *pInstance)
250 {
251    vn_trace_init();
252    VN_TRACE_FUNC();
253 
254    const VkAllocationCallbacks *alloc =
255       pAllocator ? pAllocator : vk_default_allocator();
256    struct vn_instance *instance;
257    VkResult result;
258 
259    vn_env_init();
260 
261    instance = vk_zalloc(alloc, sizeof(*instance), VN_DEFAULT_ALIGN,
262                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
263    if (!instance)
264       return vn_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
265 
266    struct vk_instance_dispatch_table dispatch_table;
267    vk_instance_dispatch_table_from_entrypoints(
268       &dispatch_table, &vn_instance_entrypoints, true);
269    vk_instance_dispatch_table_from_entrypoints(
270       &dispatch_table, &wsi_instance_entrypoints, false);
271    result = vn_instance_base_init(&instance->base,
272                                   &vn_instance_supported_extensions,
273                                   &dispatch_table, pCreateInfo, alloc);
274    if (result != VK_SUCCESS) {
275       vk_free(alloc, instance);
276       return vn_error(NULL, result);
277    }
278 
279    VkInstance instance_handle = vn_instance_to_handle(instance);
280    /* ring_idx = 0 reserved for CPU timeline */
281    instance->ring_idx_used_mask = 0x1;
282 
283    mtx_init(&instance->physical_device.mutex, mtx_plain);
284    mtx_init(&instance->ring_idx_mutex, mtx_plain);
285 
286    if (!vn_icd_supports_api_version(
287           instance->base.base.app_info.api_version)) {
288       result = VK_ERROR_INCOMPATIBLE_DRIVER;
289       goto out_mtx_destroy;
290    }
291 
292    if (pCreateInfo->enabledLayerCount) {
293       result = VK_ERROR_LAYER_NOT_PRESENT;
294       goto out_mtx_destroy;
295    }
296 
297    result = vn_instance_init_renderer(instance);
298    if (result == VK_ERROR_INITIALIZATION_FAILED) {
299       *pInstance = instance_handle;
300       return VK_SUCCESS;
301    }
302    if (result != VK_SUCCESS)
303       goto out_mtx_destroy;
304 
305    vn_cs_renderer_protocol_info_init(instance);
306 
307    vn_renderer_shmem_pool_init(instance->renderer, &instance->cs_shmem_pool,
308                                8u << 20);
309 
310    vn_renderer_shmem_pool_init(instance->renderer,
311                                &instance->reply_shmem_pool, 1u << 20);
312 
313    result = vn_instance_init_ring(instance);
314    if (result != VK_SUCCESS)
315       goto out_shmem_pool_fini;
316 
317    result = vn_instance_init_renderer_versions(instance);
318    if (result != VK_SUCCESS)
319       goto out_ring_fini;
320 
321    VkInstanceCreateInfo local_create_info = *pCreateInfo;
322    local_create_info.ppEnabledExtensionNames = NULL;
323    local_create_info.enabledExtensionCount = 0;
324    pCreateInfo = &local_create_info;
325 
326    VkApplicationInfo local_app_info;
327    if (instance->base.base.app_info.api_version <
328        instance->renderer_api_version) {
329       if (pCreateInfo->pApplicationInfo) {
330          local_app_info = *pCreateInfo->pApplicationInfo;
331          local_app_info.apiVersion = instance->renderer_api_version;
332       } else {
333          local_app_info = (const VkApplicationInfo){
334             .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
335             .apiVersion = instance->renderer_api_version,
336          };
337       }
338       local_create_info.pApplicationInfo = &local_app_info;
339    }
340 
341    result = vn_call_vkCreateInstance(instance->ring.ring, pCreateInfo, NULL,
342                                      &instance_handle);
343    if (result != VK_SUCCESS)
344       goto out_ring_fini;
345 
346    driParseOptionInfo(&instance->available_dri_options, vn_dri_options,
347                       ARRAY_SIZE(vn_dri_options));
348    driParseConfigFiles(&instance->dri_options,
349                        &instance->available_dri_options, 0, "venus", NULL,
350                        NULL, instance->base.base.app_info.app_name,
351                        instance->base.base.app_info.app_version,
352                        instance->base.base.app_info.engine_name,
353                        instance->base.base.app_info.engine_version);
354 
355    instance->renderer->info.has_implicit_fencing =
356       driQueryOptionb(&instance->dri_options, "venus_implicit_fencing");
357    instance->enable_wsi_multi_plane_modifiers = driQueryOptionb(
358       &instance->dri_options, "venus_wsi_multi_plane_modifiers");
359 
360    if (VN_DEBUG(INIT)) {
361       vn_log(instance, "supports multi-plane wsi format modifiers: %s",
362              instance->enable_wsi_multi_plane_modifiers ? "yes" : "no");
363    }
364 
365    const char *engine_name = instance->base.base.app_info.engine_name;
366    if (engine_name) {
367       instance->engine_is_zink = strcmp(engine_name, "mesa zink") == 0;
368    }
369 
370    *pInstance = instance_handle;
371 
372    return VK_SUCCESS;
373 
374 out_ring_fini:
375    vn_instance_fini_ring(instance);
376 
377 out_shmem_pool_fini:
378    vn_renderer_shmem_pool_fini(instance->renderer,
379                                &instance->reply_shmem_pool);
380    vn_renderer_shmem_pool_fini(instance->renderer, &instance->cs_shmem_pool);
381    vn_renderer_destroy(instance->renderer, alloc);
382 
383 out_mtx_destroy:
384    mtx_destroy(&instance->physical_device.mutex);
385    mtx_destroy(&instance->ring_idx_mutex);
386 
387    vn_instance_base_fini(&instance->base);
388    vk_free(alloc, instance);
389 
390    return vn_error(NULL, result);
391 }
392 
393 void
vn_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)394 vn_DestroyInstance(VkInstance _instance,
395                    const VkAllocationCallbacks *pAllocator)
396 {
397    VN_TRACE_FUNC();
398    struct vn_instance *instance = vn_instance_from_handle(_instance);
399    const VkAllocationCallbacks *alloc =
400       pAllocator ? pAllocator : &instance->base.base.alloc;
401 
402    if (!instance)
403       return;
404 
405    if (instance->physical_device.initialized) {
406       for (uint32_t i = 0; i < instance->physical_device.device_count; i++)
407          vn_physical_device_fini(&instance->physical_device.devices[i]);
408       vk_free(alloc, instance->physical_device.devices);
409       vk_free(alloc, instance->physical_device.groups);
410    }
411    mtx_destroy(&instance->physical_device.mutex);
412    mtx_destroy(&instance->ring_idx_mutex);
413 
414    if (instance->renderer) {
415       vn_call_vkDestroyInstance(instance->ring.ring, _instance, NULL);
416 
417       vn_instance_fini_ring(instance);
418 
419       vn_renderer_shmem_pool_fini(instance->renderer,
420                                   &instance->reply_shmem_pool);
421 
422       vn_renderer_shmem_pool_fini(instance->renderer, &instance->cs_shmem_pool);
423 
424       vn_renderer_destroy(instance->renderer, alloc);
425    }
426 
427    driDestroyOptionCache(&instance->dri_options);
428    driDestroyOptionInfo(&instance->available_dri_options);
429 
430    vn_instance_base_fini(&instance->base);
431    vk_free(alloc, instance);
432 }
433 
434 PFN_vkVoidFunction
vn_GetInstanceProcAddr(VkInstance _instance,const char * pName)435 vn_GetInstanceProcAddr(VkInstance _instance, const char *pName)
436 {
437    struct vn_instance *instance = vn_instance_from_handle(_instance);
438    return vk_instance_get_proc_addr(&instance->base.base,
439                                     &vn_instance_entrypoints, pName);
440 }
441