loader: Add better support for virtgpu nctx driver loading

In the case of virtio_gpu, if the drm native context capset is
supported, we should try loading the native driver before falling back
to virgl.

Previously this was done with hacks in pipe_virtio_gpu_create_screen(),
but this also requires virgl's driconf to be the superset of virgl and
all the nctx drivers.

Instead add an optional loader callback to probe for nctx support.  This
is called with the drm capset, if the host supports the drm context
type, to allow driver specific code to determine if the specific GPU is
supported, so we can cleanly fall back to virgl if it does not (for ex,
an old VM guest with a newer host, where mesa in the guest does not
support the new GPU, but mesa in the host does).

TODO: How to handle the dynamic loader case?

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28777>
This commit is contained in:
Rob Clark
2024-04-17 09:35:15 -07:00
committed by Marge Bot
parent 27ebf58ee8
commit 2ea4a59ab7
3 changed files with 52 additions and 6 deletions

View File

@@ -42,12 +42,17 @@
#include "frontend/drm_driver.h"
#include "pipe_loader_priv.h"
#include "util/log.h"
#include "util/os_file.h"
#include "util/u_memory.h"
#include "util/u_dl.h"
#include "util/u_debug.h"
#include "util/xmlconfig.h"
#include "virtio/virtio-gpu/drm_hw.h"
#include "virtio/virtio-gpu/virglrenderer_hw.h"
#include "virtgpu_drm.h"
#define DRM_RENDER_NODE_DEV_NAME_FORMAT "%s/renderD%d"
#define DRM_RENDER_NODE_MAX_NODES 63
#define DRM_RENDER_NODE_MIN_MINOR 128
@@ -121,6 +126,19 @@ get_driver_descriptor(const char *driver_name, struct util_dl_library **plib)
return NULL;
}
static int
get_nctx_caps(int fd, struct virgl_renderer_capset_drm *caps)
{
struct drm_virtgpu_get_caps args = {
.cap_set_id = VIRGL_RENDERER_CAPSET_DRM,
.cap_set_ver = 0,
.addr = (uintptr_t)caps,
.size = sizeof(*caps),
};
return drmIoctl(fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &args);
}
static bool
pipe_loader_drm_probe_fd_nodup(struct pipe_loader_device **dev, int fd, bool zink)
{
@@ -156,6 +174,26 @@ pipe_loader_drm_probe_fd_nodup(struct pipe_loader_device **dev, int fd, bool zin
ddev->base.driver_name = strdup("radeonsi");
}
if (strcmp(ddev->base.driver_name, "virtio_gpu") == 0) {
struct virgl_renderer_capset_drm caps;
if (get_nctx_caps(fd, &caps) == 0) {
#ifdef GALLIUM_STATIC_TARGETS
for (int i = 0; i < ARRAY_SIZE(driver_descriptors); i++) {
if (!driver_descriptors[i]->probe_nctx)
continue;
if (!driver_descriptors[i]->probe_nctx(fd, &caps))
continue;
FREE(ddev->base.driver_name);
ddev->base.driver_name = strdup(driver_descriptors[i]->driver_name);
break;
}
#else
mesa_logw("Dynamic pipe loader does not support virtgpu native context");
#endif
}
}
struct util_dl_library **plib = NULL;
#ifndef GALLIUM_STATIC_TARGETS
plib = &ddev->lib;

View File

@@ -10,12 +10,13 @@
/**
* Instantiate a drm_driver_descriptor struct.
*/
#define DEFINE_DRM_DRIVER_DESCRIPTOR(descriptor_name, driver, _driconf, _driconf_count, func) \
#define DEFINE_DRM_DRIVER_DESCRIPTOR(descriptor_name, driver, _driconf, _driconf_count, func, ...) \
const struct drm_driver_descriptor descriptor_name = { \
.driver_name = #driver, \
.driconf = _driconf, \
.driconf_count = _driconf_count, \
.create_screen = func, \
##__VA_ARGS__ \
};
/* The static pipe loader refers to the *_driver_descriptor structs for all
@@ -33,8 +34,8 @@ const struct drm_driver_descriptor descriptor_name = { \
#ifdef PIPE_LOADER_DYNAMIC
#define DRM_DRIVER_DESCRIPTOR(driver, driconf, driconf_count) \
PUBLIC DEFINE_DRM_DRIVER_DESCRIPTOR(driver_descriptor, driver, driconf, driconf_count, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR(driver, driconf, driconf_count, ...) \
PUBLIC DEFINE_DRM_DRIVER_DESCRIPTOR(driver_descriptor, driver, driconf, driconf_count, pipe_##driver##_create_screen, __VA_ARGS__)
#define DRM_DRIVER_DESCRIPTOR_STUB(driver)
@@ -42,8 +43,8 @@ const struct drm_driver_descriptor descriptor_name = { \
#else
#define DRM_DRIVER_DESCRIPTOR(driver, driconf, driconf_count) \
DEFINE_DRM_DRIVER_DESCRIPTOR(driver##_driver_descriptor, driver, driconf, driconf_count, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR(driver, driconf, driconf_count, ...) \
DEFINE_DRM_DRIVER_DESCRIPTOR(driver##_driver_descriptor, driver, driconf, driconf_count, pipe_##driver##_create_screen, __VA_ARGS__)
#define DRM_DRIVER_DESCRIPTOR_STUB(driver) \
static struct pipe_screen * \
@@ -56,7 +57,7 @@ const struct drm_driver_descriptor descriptor_name = { \
#define DRM_DRIVER_DESCRIPTOR_ALIAS(driver, alias, driconf, driconf_count) \
DEFINE_DRM_DRIVER_DESCRIPTOR(alias##_driver_descriptor, alias, driconf, \
driconf_count, pipe_##driver##_create_screen)
driconf_count, pipe_##driver##_create_screen, NULL)
#endif

View File

@@ -10,6 +10,7 @@ struct pipe_screen;
struct pipe_screen_config;
struct pipe_context;
struct pipe_resource;
struct virgl_renderer_capset_drm;
struct drm_driver_descriptor
{
@@ -35,6 +36,12 @@ struct drm_driver_descriptor
*/
struct pipe_screen* (*create_screen)(int drm_fd,
const struct pipe_screen_config *config);
/**
* Optional hook to probe for driver support for virtgpu native-context
* support.
*/
bool (*probe_nctx)(int drm_fd, const struct virgl_renderer_capset_drm *caps);
};
extern const struct drm_driver_descriptor driver_descriptor;