diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader.c b/src/gallium/auxiliary/pipe-loader/pipe_loader.c index 5b69599ee4f..d09eaf3531d 100644 --- a/src/gallium/auxiliary/pipe-loader/pipe_loader.c +++ b/src/gallium/auxiliary/pipe-loader/pipe_loader.c @@ -171,6 +171,8 @@ pipe_loader_create_screen_vk(struct pipe_loader_device *dev, bool sw_vk) pipe_loader_load_options(dev); config.options_info = &dev->option_info; 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); } diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader.h b/src/gallium/auxiliary/pipe-loader/pipe_loader.h index eb3c691c702..12d8396a42a 100644 --- a/src/gallium/auxiliary/pipe-loader/pipe_loader.h +++ b/src/gallium/auxiliary/pipe-loader/pipe_loader.h @@ -64,6 +64,8 @@ struct pipe_loader_device { } pci; } u; /**< Discriminated by \a type */ + int64_t dev_major; + int64_t dev_minor; char *driver_name; const struct pipe_loader_ops *ops; diff --git a/src/gallium/drivers/zink/zink_instance.py b/src/gallium/drivers/zink/zink_instance.py index 9a2e2167161..663218aaa75 100644 --- a/src/gallium/drivers/zink/zink_instance.py +++ b/src/gallium/drivers/zink/zink_instance.py @@ -43,9 +43,10 @@ EXTENSIONS = [ nonstandard=True), Extension("VK_KHR_surface"), Extension("VK_EXT_headless_surface"), - Extension("VK_KHR_wayland_surface"), + Extension("VK_KHR_wayland_surface", + conditions=["!display_dev"]), Extension("VK_KHR_xcb_surface", - conditions=["!instance_info->disable_xcb_surface"]), + conditions=["!instance_info->disable_xcb_surface && !display_dev"]), Extension("VK_KHR_win32_surface"), ] @@ -93,7 +94,7 @@ struct zink_instance_info { }; bool -zink_create_instance(struct zink_screen *screen); +zink_create_instance(struct zink_screen *screen, bool display_dev); void zink_verify_instance_extensions(struct zink_screen *screen); @@ -124,7 +125,7 @@ impl_code = """ #include "zink_screen.h" 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; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index a2c30d96a13..c1c61ffbd88 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1512,13 +1512,59 @@ zink_destroy_screen(struct pipe_screen *pscreen) 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 -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) || 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; VkResult result = VKSCR(EnumeratePhysicalDevices)(screen->instance, &pdev_count, NULL); if (result != VK_SUCCESS) { @@ -1537,25 +1583,21 @@ choose_pdev(struct zink_screen *screen) assert(result == VK_SUCCESS); assert(pdev_count > 0); - VkPhysicalDeviceProperties props; - int idx = -1; - for (i = 0; i < pdev_count; ++i) { - VKSCR(GetPhysicalDeviceProperties)(pdevs[i], &props); + if (cpu) + idx = zink_get_cpu_device_type(screen, pdev_count, pdevs); + else + 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) /* valid cpu device */ screen->pdev = pdevs[idx]; + free(pdevs); - if (idx == -1) { - mesa_loge("ZINK: CPU device requested but none found!"); + + if (idx == -1) return; - } + } else { VkPhysicalDevice pdev; 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"); } - if (!zink_create_instance(screen)) + if (!zink_create_instance(screen, config->dev_major > 0 && config->dev_major < 255)) goto fail; 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)) 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) { mesa_loge("ZINK: failed to choose pdev"); goto fail; diff --git a/src/gallium/frontends/dri/kopper.c b/src/gallium/frontends/dri/kopper.c index e83102881bf..27c897fb2ac 100644 --- a/src/gallium/frontends/dri/kopper.c +++ b/src/gallium/frontends/dri/kopper.c @@ -43,6 +43,13 @@ #include +#ifdef HAVE_LIBDRM +#include +#include +#include +#include +#endif + #ifdef VK_USE_PLATFORM_XCB_KHR #include #include @@ -109,6 +116,43 @@ static const __DRIextension *drivk_sw_screen_extensions[] = { 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 ** kopper_init_screen(struct dri_screen *screen) { @@ -130,8 +174,11 @@ kopper_init_screen(struct dri_screen *screen) else 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); + } if (!pscreen) goto fail; diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index 0c3c096bc36..bdd40fe1dab 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -799,6 +799,8 @@ struct pipe_screen { struct pipe_screen_config { struct driOptionCache *options; const struct driOptionCache *options_info; + int64_t dev_major; + int64_t dev_minor; };