mesa/src/panfrost/vulkan/panvk_instance.c
Erik Faye-Lund 8c2bfa279d panvk: support x11 wsi
This seems to be enough to get XCB working. From looking at what other
drivers does, it seems likely that XLib will just work, so let's enable
that as well.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29878>
2024-06-25 15:49:42 +00:00

250 lines
7.3 KiB
C

/*
* Copyright © 2021 Collabora Ltd.
*
* Derived from tu_device.c which is:
* Copyright © 2016 Red Hat.
* Copyright © 2016 Bas Nieuwenhuizen
* Copyright © 2015 Intel Corporation
*
* SPDX-License-Identifier: MIT
*/
#include "util/build_id.h"
#include "util/mesa-sha1.h"
#include "vk_alloc.h"
#include "vk_log.h"
#include "panvk_entrypoints.h"
#include "panvk_instance.h"
#include "panvk_physical_device.h"
#ifdef HAVE_VALGRIND
#include <memcheck.h>
#include <valgrind.h>
#define VG(x) x
#else
#define VG(x)
#endif
static const struct debug_control panvk_debug_options[] = {
{"startup", PANVK_DEBUG_STARTUP},
{"nir", PANVK_DEBUG_NIR},
{"trace", PANVK_DEBUG_TRACE},
{"sync", PANVK_DEBUG_SYNC},
{"afbc", PANVK_DEBUG_AFBC},
{"linear", PANVK_DEBUG_LINEAR},
{"dump", PANVK_DEBUG_DUMP},
{"no_known_warn", PANVK_DEBUG_NO_KNOWN_WARN},
{NULL, 0}};
VKAPI_ATTR VkResult VKAPI_CALL
panvk_EnumerateInstanceVersion(uint32_t *pApiVersion)
{
*pApiVersion = panvk_get_vk_version();
return VK_SUCCESS;
}
static const struct vk_instance_extension_table panvk_instance_extensions = {
.KHR_device_group_creation = true,
.KHR_get_physical_device_properties2 = true,
#ifdef PANVK_USE_WSI_PLATFORM
.KHR_surface = 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
.EXT_debug_report = true,
.EXT_debug_utils = true,
#ifndef VK_USE_PLATFORM_WIN32_KHR
.EXT_headless_surface = true,
#endif
};
static VkResult
panvk_physical_device_try_create(struct vk_instance *vk_instance,
struct _drmDevice *drm_device,
struct vk_physical_device **out)
{
struct panvk_instance *instance =
container_of(vk_instance, struct panvk_instance, vk);
if (!(drm_device->available_nodes & (1 << DRM_NODE_RENDER)) ||
drm_device->bustype != DRM_BUS_PLATFORM)
return VK_ERROR_INCOMPATIBLE_DRIVER;
struct panvk_physical_device *device =
vk_zalloc(&instance->vk.alloc, sizeof(*device), 8,
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (!device)
return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
VkResult result = panvk_physical_device_init(device, instance, drm_device);
if (result != VK_SUCCESS) {
vk_free(&instance->vk.alloc, device);
return result;
}
*out = &device->vk;
return VK_SUCCESS;
}
static void
panvk_destroy_physical_device(struct vk_physical_device *device)
{
panvk_physical_device_finish((struct panvk_physical_device *)device);
vk_free(&device->instance->alloc, device);
}
static void *
panvk_kmod_zalloc(const struct pan_kmod_allocator *allocator, size_t size,
bool transient)
{
const VkAllocationCallbacks *vkalloc = allocator->priv;
void *obj = vk_zalloc(vkalloc, size, 8,
transient ? VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
: VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
/* We force errno to -ENOMEM on host allocation failures so we can properly
* report it back as VK_ERROR_OUT_OF_HOST_MEMORY. */
errno = obj ? 0 : -ENOMEM;
return obj;
}
static void
panvk_kmod_free(const struct pan_kmod_allocator *allocator, void *data)
{
const VkAllocationCallbacks *vkalloc = allocator->priv;
return vk_free(vkalloc, data);
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkInstance *pInstance)
{
struct panvk_instance *instance;
VkResult result;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
const struct build_id_note *note =
build_id_find_nhdr_for_addr(panvk_CreateInstance);
if (!note) {
return vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED,
"Failed to find build-id");
}
unsigned build_id_len = build_id_length(note);
if (build_id_len < SHA1_DIGEST_LENGTH) {
return vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED,
"build-id too short. It needs to be a SHA");
}
pAllocator = pAllocator ?: vk_default_allocator();
instance = vk_zalloc(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, &panvk_instance_entrypoints, true);
vk_instance_dispatch_table_from_entrypoints(
&dispatch_table, &wsi_instance_entrypoints, false);
result = vk_instance_init(&instance->vk, &panvk_instance_extensions,
&dispatch_table, pCreateInfo, pAllocator);
if (result != VK_SUCCESS) {
vk_free(pAllocator, instance);
return vk_error(NULL, result);
}
instance->kmod.allocator = (struct pan_kmod_allocator){
.zalloc = panvk_kmod_zalloc,
.free = panvk_kmod_free,
.priv = &instance->vk.alloc,
};
instance->vk.physical_devices.try_create_for_drm =
panvk_physical_device_try_create;
instance->vk.physical_devices.destroy = panvk_destroy_physical_device;
instance->debug_flags =
parse_debug_string(getenv("PANVK_DEBUG"), panvk_debug_options);
if (instance->debug_flags & PANVK_DEBUG_STARTUP)
vk_logi(VK_LOG_NO_OBJS(instance), "Created an instance");
VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
STATIC_ASSERT(sizeof(instance->driver_build_sha) == SHA1_DIGEST_LENGTH);
memcpy(instance->driver_build_sha, build_id_data(note), SHA1_DIGEST_LENGTH);
*pInstance = panvk_instance_to_handle(instance);
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
panvk_DestroyInstance(VkInstance _instance,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(panvk_instance, instance, _instance);
if (!instance)
return;
vk_instance_finish(&instance->vk);
vk_free(&instance->vk.alloc, instance);
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
VkLayerProperties *pProperties)
{
*pPropertyCount = 0;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_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(
&panvk_instance_extensions, pPropertyCount, pProperties);
}
PFN_vkVoidFunction
panvk_GetInstanceProcAddr(VkInstance _instance, const char *pName)
{
VK_FROM_HANDLE(panvk_instance, instance, _instance);
return vk_instance_get_proc_addr(&instance->vk, &panvk_instance_entrypoints,
pName);
}
/* The loader wants us to expose a second GetInstanceProcAddr function
* to work around certain LD_PRELOAD issues seen in apps.
*/
PUBLIC
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
{
return panvk_GetInstanceProcAddr(instance, pName);
}