• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Valve Corporation
3  * Copyright 2024 Alyssa Rosenzweig
4  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5  * SPDX-License-Identifier: MIT
6  */
7 #include "hk_instance.h"
8 
9 #include "hk_entrypoints.h"
10 #include "hk_physical_device.h"
11 
12 #include "vulkan/wsi/wsi_common.h"
13 
14 #include "util/build_id.h"
15 #include "util/driconf.h"
16 #include "util/mesa-sha1.h"
17 
18 VKAPI_ATTR VkResult VKAPI_CALL
hk_EnumerateInstanceVersion(uint32_t * pApiVersion)19 hk_EnumerateInstanceVersion(uint32_t *pApiVersion)
20 {
21    uint32_t version_override = vk_get_version_override();
22    *pApiVersion = version_override ? version_override
23                                    : VK_MAKE_VERSION(1, 4, VK_HEADER_VERSION);
24 
25    return VK_SUCCESS;
26 }
27 
28 static const struct vk_instance_extension_table instance_extensions = {
29 #ifdef HK_USE_WSI_PLATFORM
30    .KHR_get_surface_capabilities2 = true,
31    .KHR_surface = true,
32    .KHR_surface_protected_capabilities = true,
33    .EXT_surface_maintenance1 = true,
34    .EXT_swapchain_colorspace = true,
35 #endif
36 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
37    .KHR_wayland_surface = true,
38 #endif
39 #ifdef VK_USE_PLATFORM_XCB_KHR
40    .KHR_xcb_surface = true,
41 #endif
42 #ifdef VK_USE_PLATFORM_XLIB_KHR
43    .KHR_xlib_surface = true,
44 #endif
45 #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
46    .EXT_acquire_xlib_display = true,
47 #endif
48 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
49    .KHR_display = true,
50    .KHR_get_display_properties2 = true,
51    .EXT_direct_mode_display = true,
52    .EXT_display_surface_counter = true,
53    .EXT_acquire_drm_display = true,
54 #endif
55 #ifndef VK_USE_PLATFORM_WIN32_KHR
56    .EXT_headless_surface = true,
57 #endif
58    .KHR_device_group_creation = true,
59    .KHR_external_fence_capabilities = true,
60    .KHR_external_memory_capabilities = true,
61    .KHR_external_semaphore_capabilities = true,
62    .KHR_get_physical_device_properties2 = true,
63    .EXT_debug_report = true,
64    .EXT_debug_utils = true,
65 };
66 
67 VKAPI_ATTR VkResult VKAPI_CALL
hk_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)68 hk_EnumerateInstanceExtensionProperties(const char *pLayerName,
69                                         uint32_t *pPropertyCount,
70                                         VkExtensionProperties *pProperties)
71 {
72    if (pLayerName)
73       return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
74 
75    return vk_enumerate_instance_extension_properties(
76       &instance_extensions, pPropertyCount, pProperties);
77 }
78 
79 /* clang-format off */
80 static const driOptionDescription hk_dri_options[] = {
81    DRI_CONF_SECTION_PERFORMANCE
82       DRI_CONF_ADAPTIVE_SYNC(true)
83       DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
84       DRI_CONF_VK_X11_STRICT_IMAGE_COUNT(false)
85       DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT(false)
86       DRI_CONF_VK_KHR_PRESENT_WAIT(false)
87       DRI_CONF_VK_XWAYLAND_WAIT_READY(false)
88    DRI_CONF_SECTION_END
89 
90    DRI_CONF_SECTION_DEBUG
91       DRI_CONF_FORCE_VK_VENDOR()
92       DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false)
93       DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false)
94    DRI_CONF_SECTION_END
95 
96    DRI_CONF_SECTION_MISCELLANEOUS
97       DRI_CONF_HK_DISABLE_RGBA4_BORDER_COLOR_WORKAROUND(false)
98       DRI_CONF_HK_DISABLE_BORDER_EMULATION(false)
99    DRI_CONF_SECTION_END
100 };
101 /* clang-format on */
102 
103 static void
hk_init_dri_options(struct hk_instance * instance)104 hk_init_dri_options(struct hk_instance *instance)
105 {
106    driParseOptionInfo(&instance->available_dri_options, hk_dri_options,
107                       ARRAY_SIZE(hk_dri_options));
108    driParseConfigFiles(
109       &instance->dri_options, &instance->available_dri_options, 0, "hk", NULL,
110       NULL, instance->vk.app_info.app_name, instance->vk.app_info.app_version,
111       instance->vk.app_info.engine_name, instance->vk.app_info.engine_version);
112 
113    instance->force_vk_vendor =
114       driQueryOptioni(&instance->dri_options, "force_vk_vendor");
115 
116    instance->workaround_rgba4 = !driQueryOptionb(
117       &instance->dri_options, "hk_disable_rgba4_border_color_workaround");
118 
119    instance->no_border =
120       driQueryOptionb(&instance->dri_options, "hk_disable_border_emulation");
121 }
122 
123 VKAPI_ATTR VkResult VKAPI_CALL
hk_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)124 hk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
125                   const VkAllocationCallbacks *pAllocator,
126                   VkInstance *pInstance)
127 {
128    struct hk_instance *instance;
129    VkResult result;
130 
131    if (pAllocator == NULL)
132       pAllocator = vk_default_allocator();
133 
134    instance = vk_alloc(pAllocator, sizeof(*instance), 8,
135                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
136    if (!instance)
137       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
138 
139    struct vk_instance_dispatch_table dispatch_table;
140    vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
141                                                &hk_instance_entrypoints, true);
142    vk_instance_dispatch_table_from_entrypoints(
143       &dispatch_table, &wsi_instance_entrypoints, false);
144 
145    result = vk_instance_init(&instance->vk, &instance_extensions,
146                              &dispatch_table, pCreateInfo, pAllocator);
147    if (result != VK_SUCCESS)
148       goto fail_alloc;
149 
150    hk_init_dri_options(instance);
151 
152    instance->vk.physical_devices.try_create_for_drm =
153       hk_create_drm_physical_device;
154    instance->vk.physical_devices.destroy = hk_physical_device_destroy;
155 
156    const struct build_id_note *note =
157       build_id_find_nhdr_for_addr(hk_CreateInstance);
158    if (!note) {
159       result = vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED,
160                          "Failed to find build-id");
161       goto fail_init;
162    }
163 
164    unsigned build_id_len = build_id_length(note);
165    if (build_id_len < SHA1_DIGEST_LENGTH) {
166       result = vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED,
167                          "build-id too short.  It needs to be a SHA");
168       goto fail_init;
169    }
170 
171    static_assert(sizeof(instance->driver_build_sha) == SHA1_DIGEST_LENGTH);
172    memcpy(instance->driver_build_sha, build_id_data(note), SHA1_DIGEST_LENGTH);
173 
174    *pInstance = hk_instance_to_handle(instance);
175    return VK_SUCCESS;
176 
177 fail_init:
178    vk_instance_finish(&instance->vk);
179 fail_alloc:
180    vk_free(pAllocator, instance);
181 
182    return result;
183 }
184 
185 VKAPI_ATTR void VKAPI_CALL
hk_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)186 hk_DestroyInstance(VkInstance _instance,
187                    const VkAllocationCallbacks *pAllocator)
188 {
189    VK_FROM_HANDLE(hk_instance, instance, _instance);
190 
191    if (!instance)
192       return;
193 
194    driDestroyOptionCache(&instance->dri_options);
195    driDestroyOptionInfo(&instance->available_dri_options);
196 
197    vk_instance_finish(&instance->vk);
198    vk_free(&instance->vk.alloc, instance);
199 }
200 
201 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
hk_GetInstanceProcAddr(VkInstance _instance,const char * pName)202 hk_GetInstanceProcAddr(VkInstance _instance, const char *pName)
203 {
204    VK_FROM_HANDLE(hk_instance, instance, _instance);
205    return vk_instance_get_proc_addr(&instance->vk, &hk_instance_entrypoints,
206                                     pName);
207 }
208 
209 PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)210 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
211 {
212    return hk_GetInstanceProcAddr(instance, pName);
213 }
214