From 612774c4a67d10b9960741cc954d69f6e5ef1f88 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Mon, 14 Oct 2024 16:40:35 +0200 Subject: [PATCH] radeonsi: enable virtio native context support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Reviewed-by: Marek Olšák Part-of: --- .../auxiliary/target-helpers/drm_helper.h | 4 +- src/gallium/drivers/radeonsi/meson.build | 10 ++++- src/gallium/drivers/radeonsi/si_pipe.c | 37 +++++++++++++++---- src/gallium/drivers/radeonsi/si_public.h | 3 ++ src/gallium/include/winsys/radeon_winsys.h | 2 +- src/gallium/targets/dril/meson.build | 3 +- src/gallium/winsys/amdgpu/drm/amdgpu_bo.c | 14 ++++++- src/gallium/winsys/amdgpu/drm/amdgpu_cs.cpp | 8 ++++ src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c | 9 +++-- src/gallium/winsys/amdgpu/drm/meson.build | 8 +++- 10 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/gallium/auxiliary/target-helpers/drm_helper.h b/src/gallium/auxiliary/target-helpers/drm_helper.h index 4392fa14879..3ddab30af49 100644 --- a/src/gallium/auxiliary/target-helpers/drm_helper.h +++ b/src/gallium/auxiliary/target-helpers/drm_helper.h @@ -210,8 +210,8 @@ pipe_radeonsi_create_screen(int fd, const struct pipe_screen_config *config) const driOptionDescription radeonsi_driconf[] = { #include "radeonsi/driinfo_radeonsi.h" }; -DRM_DRIVER_DESCRIPTOR(radeonsi, radeonsi_driconf, ARRAY_SIZE(radeonsi_driconf)) - +DRM_DRIVER_DESCRIPTOR(radeonsi, radeonsi_driconf, ARRAY_SIZE(radeonsi_driconf), + .probe_nctx = si_virtgpu_probe_nctx) #else DRM_DRIVER_DESCRIPTOR_STUB(radeonsi) #endif diff --git a/src/gallium/drivers/radeonsi/meson.build b/src/gallium/drivers/radeonsi/meson.build index 09e31d41fa3..735c5d2ee07 100644 --- a/src/gallium/drivers/radeonsi/meson.build +++ b/src/gallium/drivers/radeonsi/meson.build @@ -104,7 +104,7 @@ files_libradeonsi = files( ) radeonsi_include_dirs = [inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_amd_common, - inc_amd_common_llvm, inc_gallium_drivers, inc_compiler, inc_amd, inc_amd_vpe] + inc_amd_common_llvm, inc_gallium_drivers, inc_compiler, inc_amd, inc_amd_vpe, inc_virtio_gpu] radeonsi_deps = [dep_llvm, dep_clock, dep_libdrm, idep_nir_headers, idep_amdgfxregs_h, idep_mesautil, idep_aco, idep_u_tracepoints, idep_si_tracepoints] if with_perfetto @@ -141,16 +141,22 @@ foreach ver : ['6', '7', '8', '9', '10', '103', '11', '115', '12'] ) endforeach +libradeonsi_cflags = [] +if with_amdgpu_virtio + libradeonsi_cflags += ['-DHAVE_AMDGPU_VIRTIO'] +endif + libradeonsi = static_library( 'radeonsi', [files_libradeonsi, sid_tables_h], + c_args : libradeonsi_cflags, include_directories : radeonsi_include_dirs, gnu_symbol_visibility : 'hidden', dependencies : radeonsi_deps, ) driver_radeonsi = declare_dependency( - compile_args : '-DGALLIUM_RADEONSI', + compile_args : ['-DGALLIUM_RADEONSI'] + libradeonsi_cflags, link_with : radeonsi_gfx_libs + [ libradeonsi, libradeonwinsys, libamdgpuwinsys, libamd_common, libamd_common_llvm, libvpe ], diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 458c1a6b0c3..e1760f23c95 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -31,6 +31,10 @@ #include "ac_llvm_util.h" #endif +#if HAVE_AMDGPU_VIRTIO +#include "virtio/virtio-gpu/drm_hw.h" +#endif + #include static struct pipe_context *si_create_context(struct pipe_screen *screen, unsigned flags); @@ -478,6 +482,18 @@ static void si_set_frontend_noop(struct pipe_context *ctx, bool enable) sctx->is_noop = enable; } +/* Function used by the pipe_loader to decide which driver to use when + * the KMD is virtio_gpu. + */ +bool si_virtgpu_probe_nctx(int fd, const struct virgl_renderer_capset_drm *caps) +{ + #ifdef HAVE_AMDGPU_VIRTIO + return caps->context_type == VIRTGPU_DRM_CONTEXT_AMDGPU; + #else + return false; + #endif +} + static struct pipe_context *si_create_context(struct pipe_screen *screen, unsigned flags) { struct si_screen *sscreen = (struct si_screen *)screen; @@ -1555,13 +1571,20 @@ struct pipe_screen *radeonsi_screen_create(int fd, const struct pipe_screen_conf driParseConfigFiles(config->options, config->options_info, 0, "radeonsi", NULL, NULL, NULL, 0, NULL, 0); - switch (version->version_major) { - case 2: - rw = radeon_drm_winsys_create(fd, config, radeonsi_screen_create_impl); - break; - case 3: - rw = amdgpu_winsys_create(fd, config, radeonsi_screen_create_impl); - break; +#ifdef HAVE_AMDGPU_VIRTIO + if (strcmp(version->name, "virtio_gpu") == 0) { + rw = amdgpu_winsys_create(fd, config, radeonsi_screen_create_impl, true); + } else +#endif + { + switch (version->version_major) { + case 2: + rw = radeon_drm_winsys_create(fd, config, radeonsi_screen_create_impl); + break; + case 3: + rw = amdgpu_winsys_create(fd, config, radeonsi_screen_create_impl, false); + break; + } } si_driver_ds_init(); diff --git a/src/gallium/drivers/radeonsi/si_public.h b/src/gallium/drivers/radeonsi/si_public.h index b56e5de3606..ea8c4cc8f7a 100644 --- a/src/gallium/drivers/radeonsi/si_public.h +++ b/src/gallium/drivers/radeonsi/si_public.h @@ -9,7 +9,10 @@ struct pipe_screen; struct pipe_screen_config; +struct virgl_renderer_capset_drm; struct pipe_screen *radeonsi_screen_create(int fd, const struct pipe_screen_config *config); +bool si_virtgpu_probe_nctx(int fd, const struct virgl_renderer_capset_drm *caps); + #endif diff --git a/src/gallium/include/winsys/radeon_winsys.h b/src/gallium/include/winsys/radeon_winsys.h index fe81edecdef..bc704fe4075 100644 --- a/src/gallium/include/winsys/radeon_winsys.h +++ b/src/gallium/include/winsys/radeon_winsys.h @@ -970,7 +970,7 @@ typedef struct pipe_screen *(*radeon_screen_create_t)(struct radeon_winsys *, /* These functions create the radeon_winsys instance for the corresponding kernel driver. */ struct radeon_winsys * amdgpu_winsys_create(int fd, const struct pipe_screen_config *config, - radeon_screen_create_t screen_create); + radeon_screen_create_t screen_create, bool is_virtio); struct radeon_winsys * radeon_drm_winsys_create(int fd, const struct pipe_screen_config *config, radeon_screen_create_t screen_create); diff --git a/src/gallium/targets/dril/meson.build b/src/gallium/targets/dril/meson.build index fad5c4784f6..7cfa982ffe1 100644 --- a/src/gallium/targets/dril/meson.build +++ b/src/gallium/targets/dril/meson.build @@ -117,7 +117,8 @@ foreach d : [[with_gallium_kmsro, [ [with_gallium_r600, 'r600_dri.so'], [with_gallium_svga, 'vmwgfx_dri.so'], [with_gallium_virgl or - (with_gallium_freedreno and freedreno_kmds.contains('virtio')), + (with_gallium_freedreno and freedreno_kmds.contains('virtio')) or + (with_gallium_radeonsi and with_amdgpu_virtio), 'virtio_gpu_dri.so'], [with_gallium_lima, 'lima_dri.so'], [with_gallium_d3d12, 'd3d12_dri.so'], diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c index b528a44c075..6a6a11930c1 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c @@ -1599,6 +1599,7 @@ static struct pb_buffer_lean *amdgpu_bo_from_handle(struct radeon_winsys *rws, switch (whandle->type) { case WINSYS_HANDLE_TYPE_SHARED: + assert(!aws->info.is_virtio); /* Legacy-path, not handled */ type = amdgpu_bo_handle_type_gem_flink_name; break; case WINSYS_HANDLE_TYPE_FD: @@ -1735,11 +1736,22 @@ static bool amdgpu_bo_get_handle(struct radeon_winsys *rws, switch (whandle->type) { case WINSYS_HANDLE_TYPE_SHARED: + /* This is a legacy code-path, not supported by virtio. */ + assert(!aws->info.is_virtio); type = amdgpu_bo_handle_type_gem_flink_name; break; case WINSYS_HANDLE_TYPE_KMS: if (sws->fd == aws->fd) { - whandle->handle = bo->kms_handle; + /* For virtio we can't return kms_handle, because it's not a GEM handle, + * but a resource ID. Instead, repurpose the deprecated type + * amdgpu_bo_handle_type_kms_noimport to request a GEM handle. + */ + if (aws->info.is_virtio) + ac_drm_bo_export(aws->dev, bo->bo, + amdgpu_bo_handle_type_kms_noimport, + &whandle->handle); + else + whandle->handle = bo->kms_handle; if (bo->is_shared) return true; diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.cpp b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.cpp index 4d834cef338..97cd68cf759 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.cpp +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.cpp @@ -212,6 +212,10 @@ bool amdgpu_fence_wait(struct pipe_fence_handle *fence, uint64_t timeout, abs_timeout, 0, NULL)) return false; + /* Check that guest-side syncobj agrees with the user fence. */ + if (user_fence_cpu && afence->aws->info.is_virtio) + assert(afence->seq_no <= *user_fence_cpu); + afence->signalled = true; return true; } @@ -1171,6 +1175,10 @@ static unsigned amdgpu_cs_get_buffer_list(struct radeon_cmdbuf *rcs, struct amdgpu_buffer_list *real_buffers = &cs->buffer_lists[AMDGPU_BO_REAL]; unsigned num_real_buffers = real_buffers->num_buffers; +#if HAVE_AMDGPU_VIRTIO + assert(!cs->ws->info.is_virtio); +#endif + if (list) { for (unsigned i = 0; i < num_real_buffers; i++) { list[i].bo_size = real_buffers->buffers[i].bo->base.size; diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c index f454ed29dfe..fe988add5d8 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c @@ -373,7 +373,7 @@ amdgpu_drm_winsys_get_fd(struct radeon_winsys *rws) PUBLIC struct radeon_winsys * amdgpu_winsys_create(int fd, const struct pipe_screen_config *config, - radeon_screen_create_t screen_create) + radeon_screen_create_t screen_create, bool is_virtio) { struct amdgpu_screen_winsys *sws; struct amdgpu_winsys *aws; @@ -395,9 +395,10 @@ amdgpu_winsys_create(int fd, const struct pipe_screen_config *config, /* Initialize the amdgpu device. This should always return the same pointer * for the same fd. */ - r = ac_drm_device_initialize(fd, false, &drm_major, &drm_minor, &dev); + r = ac_drm_device_initialize(fd, is_virtio, &drm_major, &drm_minor, &dev); if (r) { - fprintf(stderr, "amdgpu: amdgpu_device_initialize failed.\n"); + fprintf(stderr, "amdgpu: amd%s_device_initialize failed.\n", + is_virtio ? "vgpu" : "gpu"); goto fail; } @@ -459,6 +460,8 @@ amdgpu_winsys_create(int fd, const struct pipe_screen_config *config, goto fail_alloc; simple_mtx_init(&aws->vm_ioctl_lock, mtx_plain); + aws->info.is_virtio = is_virtio; + /* Only aws and buffer functions are used. */ aws->dummy_sws.aws = aws; amdgpu_bo_init_functions(&aws->dummy_sws); diff --git a/src/gallium/winsys/amdgpu/drm/meson.build b/src/gallium/winsys/amdgpu/drm/meson.build index a79701c550e..d0580595744 100644 --- a/src/gallium/winsys/amdgpu/drm/meson.build +++ b/src/gallium/winsys/amdgpu/drm/meson.build @@ -1,6 +1,11 @@ # Copyright © 2017 Dylan Baker # SPDX-License-Identifier: MIT +c_args = [] +if with_amdgpu_virtio + c_args += '-DHAVE_AMDGPU_VIRTIO' +endif + libamdgpuwinsys = static_library( 'amdgpuwinsys', files( @@ -10,9 +15,10 @@ libamdgpuwinsys = static_library( ), include_directories : [ inc_amd, inc_gallium, inc_gallium_aux, inc_include, inc_src, - inc_amd_common, inc_amd_common_llvm, + inc_amd_common, inc_amd_common_llvm, inc_virtio_gpu ], gnu_symbol_visibility : 'hidden', link_with : libamdgpu_addrlib, dependencies : [dep_llvm, dep_libdrm_amdgpu, idep_amdgfxregs_h, idep_mesautil], + c_args : c_args )