mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 22:00:13 +01:00
zink: Fix enumerate devices when running compositor
When we try to run a compositor on top of Zink, we hit a lockup when enumerating the Vulkan devices. The vulkan_device_select tries to reorder the devices and gets stuck waiting for the Xserver. With this patch, we avoid this issue by detecting when we are running a compositor and disabling the X and Wayland instance extensions. And code is added to try to pick the same device as the display. Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Igor Torrente <igor.torrente@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24222>
This commit is contained in:
parent
71db99e566
commit
6d60115be7
6 changed files with 119 additions and 23 deletions
|
|
@ -171,6 +171,8 @@ pipe_loader_create_screen_vk(struct pipe_loader_device *dev, bool sw_vk)
|
||||||
pipe_loader_load_options(dev);
|
pipe_loader_load_options(dev);
|
||||||
config.options_info = &dev->option_info;
|
config.options_info = &dev->option_info;
|
||||||
config.options = &dev->option_cache;
|
config.options = &dev->option_cache;
|
||||||
|
config.dev_major = dev->dev_major;
|
||||||
|
config.dev_minor = dev->dev_minor;
|
||||||
|
|
||||||
return dev->ops->create_screen(dev, &config, sw_vk);
|
return dev->ops->create_screen(dev, &config, sw_vk);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ struct pipe_loader_device {
|
||||||
} pci;
|
} pci;
|
||||||
} u; /**< Discriminated by \a type */
|
} u; /**< Discriminated by \a type */
|
||||||
|
|
||||||
|
int64_t dev_major;
|
||||||
|
int64_t dev_minor;
|
||||||
char *driver_name;
|
char *driver_name;
|
||||||
const struct pipe_loader_ops *ops;
|
const struct pipe_loader_ops *ops;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,10 @@ EXTENSIONS = [
|
||||||
nonstandard=True),
|
nonstandard=True),
|
||||||
Extension("VK_KHR_surface"),
|
Extension("VK_KHR_surface"),
|
||||||
Extension("VK_EXT_headless_surface"),
|
Extension("VK_EXT_headless_surface"),
|
||||||
Extension("VK_KHR_wayland_surface"),
|
Extension("VK_KHR_wayland_surface",
|
||||||
|
conditions=["!display_dev"]),
|
||||||
Extension("VK_KHR_xcb_surface",
|
Extension("VK_KHR_xcb_surface",
|
||||||
conditions=["!instance_info->disable_xcb_surface"]),
|
conditions=["!instance_info->disable_xcb_surface && !display_dev"]),
|
||||||
Extension("VK_KHR_win32_surface"),
|
Extension("VK_KHR_win32_surface"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -93,7 +94,7 @@ struct zink_instance_info {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
zink_create_instance(struct zink_screen *screen);
|
zink_create_instance(struct zink_screen *screen, bool display_dev);
|
||||||
|
|
||||||
void
|
void
|
||||||
zink_verify_instance_extensions(struct zink_screen *screen);
|
zink_verify_instance_extensions(struct zink_screen *screen);
|
||||||
|
|
@ -124,7 +125,7 @@ impl_code = """
|
||||||
#include "zink_screen.h"
|
#include "zink_screen.h"
|
||||||
|
|
||||||
bool
|
bool
|
||||||
zink_create_instance(struct zink_screen *screen)
|
zink_create_instance(struct zink_screen *screen, bool display_dev)
|
||||||
{
|
{
|
||||||
struct zink_instance_info *instance_info = &screen->instance_info;
|
struct zink_instance_info *instance_info = &screen->instance_info;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1512,13 +1512,59 @@ zink_destroy_screen(struct pipe_screen *pscreen)
|
||||||
glsl_type_singleton_decref();
|
glsl_type_singleton_decref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zink_get_display_device(const struct zink_screen *screen, uint32_t pdev_count,
|
||||||
|
const VkPhysicalDevice *pdevs, int64_t dev_major,
|
||||||
|
int64_t dev_minor)
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceDrmPropertiesEXT drm_props = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT,
|
||||||
|
};
|
||||||
|
VkPhysicalDeviceProperties2 props = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||||
|
.pNext = &drm_props,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < pdev_count; ++i) {
|
||||||
|
VKSCR(GetPhysicalDeviceProperties2)(pdevs[i], &props);
|
||||||
|
if (drm_props.renderMajor == dev_major &&
|
||||||
|
drm_props.renderMinor == dev_minor)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesa_loge("ZINK: could not find the Display GPU, choosing default device!");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zink_get_cpu_device_type(const struct zink_screen *screen, uint32_t pdev_count,
|
||||||
|
const VkPhysicalDevice *pdevs)
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceProperties props;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < pdev_count; ++i) {
|
||||||
|
VKSCR(GetPhysicalDeviceProperties)(pdevs[i], &props);
|
||||||
|
|
||||||
|
/* if user wants cpu, only give them cpu */
|
||||||
|
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesa_loge("ZINK: CPU device requested but none found!");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
choose_pdev(struct zink_screen *screen)
|
choose_pdev(struct zink_screen *screen, int64_t dev_major, int64_t dev_minor)
|
||||||
{
|
{
|
||||||
bool cpu = debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false) ||
|
bool cpu = debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false) ||
|
||||||
debug_get_bool_option("D3D_ALWAYS_SOFTWARE", false);
|
debug_get_bool_option("D3D_ALWAYS_SOFTWARE", false);
|
||||||
if (cpu) {
|
|
||||||
uint32_t i, pdev_count;
|
if (cpu || (dev_major > 0 && dev_major < 255)) {
|
||||||
|
uint32_t pdev_count;
|
||||||
|
int idx;
|
||||||
VkPhysicalDevice *pdevs;
|
VkPhysicalDevice *pdevs;
|
||||||
VkResult result = VKSCR(EnumeratePhysicalDevices)(screen->instance, &pdev_count, NULL);
|
VkResult result = VKSCR(EnumeratePhysicalDevices)(screen->instance, &pdev_count, NULL);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
|
|
@ -1537,25 +1583,21 @@ choose_pdev(struct zink_screen *screen)
|
||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
assert(pdev_count > 0);
|
assert(pdev_count > 0);
|
||||||
|
|
||||||
VkPhysicalDeviceProperties props;
|
if (cpu)
|
||||||
int idx = -1;
|
idx = zink_get_cpu_device_type(screen, pdev_count, pdevs);
|
||||||
for (i = 0; i < pdev_count; ++i) {
|
else
|
||||||
VKSCR(GetPhysicalDeviceProperties)(pdevs[i], &props);
|
idx = zink_get_display_device(screen, pdev_count, pdevs, dev_major,
|
||||||
|
dev_minor);
|
||||||
|
|
||||||
/* if user wants cpu, only give them cpu */
|
|
||||||
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
|
|
||||||
idx = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
/* valid cpu device */
|
/* valid cpu device */
|
||||||
screen->pdev = pdevs[idx];
|
screen->pdev = pdevs[idx];
|
||||||
|
|
||||||
free(pdevs);
|
free(pdevs);
|
||||||
if (idx == -1) {
|
|
||||||
mesa_loge("ZINK: CPU device requested but none found!");
|
if (idx == -1)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
VkPhysicalDevice pdev;
|
VkPhysicalDevice pdev;
|
||||||
unsigned pdev_count = 1;
|
unsigned pdev_count = 1;
|
||||||
|
|
@ -2838,7 +2880,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
|
||||||
screen->instance_info.disable_xcb_surface = driQueryOptionb(config->options, "disable_xcb_surface");
|
screen->instance_info.disable_xcb_surface = driQueryOptionb(config->options, "disable_xcb_surface");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!zink_create_instance(screen))
|
if (!zink_create_instance(screen, config->dev_major > 0 && config->dev_major < 255))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (zink_debug & ZINK_DEBUG_VALIDATION) {
|
if (zink_debug & ZINK_DEBUG_VALIDATION) {
|
||||||
|
|
@ -2862,7 +2904,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
|
||||||
(zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen))
|
(zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen))
|
||||||
debug_printf("ZINK: failed to setup debug utils\n");
|
debug_printf("ZINK: failed to setup debug utils\n");
|
||||||
|
|
||||||
choose_pdev(screen);
|
choose_pdev(screen, config->dev_major, config->dev_minor);
|
||||||
if (screen->pdev == VK_NULL_HANDLE) {
|
if (screen->pdev == VK_NULL_HANDLE) {
|
||||||
mesa_loge("ZINK: failed to choose pdev");
|
mesa_loge("ZINK: failed to choose pdev");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,13 @@
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBDRM
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/dri3.h>
|
#include <xcb/dri3.h>
|
||||||
|
|
@ -109,6 +116,43 @@ static const __DRIextension *drivk_sw_screen_extensions[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
kopper_render_rdev(int fd, struct pipe_loader_device *pipe_loader)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
pipe_loader->dev_major = -1;
|
||||||
|
pipe_loader->dev_minor = -1;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBDRM
|
||||||
|
struct stat stx;
|
||||||
|
drmDevicePtr dev;
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (drmGetDevice2(fd, 0, &dev))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(!(dev->available_nodes & (1 << DRM_NODE_RENDER))) {
|
||||||
|
ret = -1;
|
||||||
|
goto free_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stat(dev->nodes[DRM_NODE_RENDER], &stx)) {
|
||||||
|
ret = -1;
|
||||||
|
goto free_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_loader->dev_major = major(stx.st_rdev);
|
||||||
|
pipe_loader->dev_minor = minor(stx.st_rdev);
|
||||||
|
|
||||||
|
free_device:
|
||||||
|
drmFreeDevice(&dev);
|
||||||
|
#endif //HAVE_LIBDRM
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static const __DRIconfig **
|
static const __DRIconfig **
|
||||||
kopper_init_screen(struct dri_screen *screen)
|
kopper_init_screen(struct dri_screen *screen)
|
||||||
{
|
{
|
||||||
|
|
@ -130,8 +174,11 @@ kopper_init_screen(struct dri_screen *screen)
|
||||||
else
|
else
|
||||||
success = pipe_loader_vk_probe_dri(&screen->dev, NULL);
|
success = pipe_loader_vk_probe_dri(&screen->dev, NULL);
|
||||||
|
|
||||||
if (success)
|
if (success) {
|
||||||
|
if (kopper_render_rdev(screen->fd, screen->dev))
|
||||||
|
goto fail;
|
||||||
pscreen = pipe_loader_create_screen(screen->dev);
|
pscreen = pipe_loader_create_screen(screen->dev);
|
||||||
|
}
|
||||||
|
|
||||||
if (!pscreen)
|
if (!pscreen)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -799,6 +799,8 @@ struct pipe_screen {
|
||||||
struct pipe_screen_config {
|
struct pipe_screen_config {
|
||||||
struct driOptionCache *options;
|
struct driOptionCache *options;
|
||||||
const struct driOptionCache *options_info;
|
const struct driOptionCache *options_info;
|
||||||
|
int64_t dev_major;
|
||||||
|
int64_t dev_minor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue