/* * Copyright 2024 Valve Corporation * Copyright 2024 Alyssa Rosenzweig * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc. * SPDX-License-Identifier: MIT */ #include "hk_instance.h" #include "hk_entrypoints.h" #include "hk_physical_device.h" #include "vulkan/wsi/wsi_common.h" #include "util/build_id.h" #include "util/driconf.h" #include "util/mesa-sha1.h" VKAPI_ATTR VkResult VKAPI_CALL hk_EnumerateInstanceVersion(uint32_t *pApiVersion) { uint32_t version_override = vk_get_version_override(); *pApiVersion = version_override ? version_override : VK_MAKE_VERSION(1, 3, VK_HEADER_VERSION); return VK_SUCCESS; } static const struct vk_instance_extension_table instance_extensions = { #ifdef HK_USE_WSI_PLATFORM .KHR_get_surface_capabilities2 = true, .KHR_surface = true, .KHR_surface_protected_capabilities = true, .EXT_surface_maintenance1 = true, .EXT_swapchain_colorspace = true, #endif #ifdef VK_USE_PLATFORM_WAYLAND_KHR .KHR_wayland_surface = true, #endif #ifdef VK_USE_PLATFORM_XCB_KHR .KHR_xcb_surface = true, #endif #ifdef VK_USE_PLATFORM_XLIB_KHR .KHR_xlib_surface = true, #endif #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT .EXT_acquire_xlib_display = true, #endif #ifdef VK_USE_PLATFORM_DISPLAY_KHR .KHR_display = true, .KHR_get_display_properties2 = true, .EXT_direct_mode_display = true, .EXT_display_surface_counter = true, .EXT_acquire_drm_display = true, #endif #ifndef VK_USE_PLATFORM_WIN32_KHR .EXT_headless_surface = true, #endif .KHR_device_group_creation = true, .KHR_external_fence_capabilities = true, .KHR_external_memory_capabilities = true, .KHR_external_semaphore_capabilities = true, .KHR_get_physical_device_properties2 = true, .EXT_debug_report = true, .EXT_debug_utils = true, }; VKAPI_ATTR VkResult VKAPI_CALL hk_EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) { if (pLayerName) return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); return vk_enumerate_instance_extension_properties( &instance_extensions, pPropertyCount, pProperties); } static const driOptionDescription hk_dri_options[] = { DRI_CONF_SECTION_PERFORMANCE DRI_CONF_ADAPTIVE_SYNC(true) DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0) DRI_CONF_VK_X11_STRICT_IMAGE_COUNT(false) DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT(false) DRI_CONF_VK_KHR_PRESENT_WAIT(false) DRI_CONF_VK_XWAYLAND_WAIT_READY(false) DRI_CONF_SECTION_END DRI_CONF_SECTION_DEBUG DRI_CONF_FORCE_VK_VENDOR() DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false) DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false) DRI_CONF_SECTION_END}; static void hk_init_dri_options(struct hk_instance *instance) { driParseOptionInfo(&instance->available_dri_options, hk_dri_options, ARRAY_SIZE(hk_dri_options)); driParseConfigFiles( &instance->dri_options, &instance->available_dri_options, 0, "hk", NULL, NULL, instance->vk.app_info.app_name, instance->vk.app_info.app_version, instance->vk.app_info.engine_name, instance->vk.app_info.engine_version); instance->force_vk_vendor = driQueryOptioni(&instance->dri_options, "force_vk_vendor"); } VKAPI_ATTR VkResult VKAPI_CALL hk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { struct hk_instance *instance; VkResult result; if (pAllocator == NULL) pAllocator = vk_default_allocator(); instance = vk_alloc(pAllocator, sizeof(*instance), 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!instance) return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); struct vk_instance_dispatch_table dispatch_table; vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &hk_instance_entrypoints, true); vk_instance_dispatch_table_from_entrypoints( &dispatch_table, &wsi_instance_entrypoints, false); result = vk_instance_init(&instance->vk, &instance_extensions, &dispatch_table, pCreateInfo, pAllocator); if (result != VK_SUCCESS) goto fail_alloc; hk_init_dri_options(instance); instance->vk.physical_devices.try_create_for_drm = hk_create_drm_physical_device; instance->vk.physical_devices.destroy = hk_physical_device_destroy; const struct build_id_note *note = build_id_find_nhdr_for_addr(hk_CreateInstance); if (!note) { result = vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED, "Failed to find build-id"); goto fail_init; } unsigned build_id_len = build_id_length(note); if (build_id_len < SHA1_DIGEST_LENGTH) { result = vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED, "build-id too short. It needs to be a SHA"); goto fail_init; } static_assert(sizeof(instance->driver_build_sha) == SHA1_DIGEST_LENGTH); memcpy(instance->driver_build_sha, build_id_data(note), SHA1_DIGEST_LENGTH); *pInstance = hk_instance_to_handle(instance); return VK_SUCCESS; fail_init: vk_instance_finish(&instance->vk); fail_alloc: vk_free(pAllocator, instance); return result; } VKAPI_ATTR void VKAPI_CALL hk_DestroyInstance(VkInstance _instance, const VkAllocationCallbacks *pAllocator) { VK_FROM_HANDLE(hk_instance, instance, _instance); if (!instance) return; driDestroyOptionCache(&instance->dri_options); driDestroyOptionInfo(&instance->available_dri_options); vk_instance_finish(&instance->vk); vk_free(&instance->vk.alloc, instance); } VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL hk_GetInstanceProcAddr(VkInstance _instance, const char *pName) { VK_FROM_HANDLE(hk_instance, instance, _instance); return vk_instance_get_proc_addr(&instance->vk, &hk_instance_entrypoints, pName); } PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName) { return hk_GetInstanceProcAddr(instance, pName); }