mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-24 06:18:10 +02:00
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>
250 lines
7.3 KiB
C
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);
|
|
}
|