From c6eb84ff30a829d92ae966eccc1f765cbc2fc64a Mon Sep 17 00:00:00 2001 From: Rohan Garg Date: Thu, 25 Feb 2021 18:13:22 +0100 Subject: [PATCH] virgl: Add support for querying detailed memory info This allows for virgl guests to expose GL_NVX_gpu_memory_info and GL_ATI_meminfo when the extensions are supported on the host. Signed-off-by: Rohan Garg Reviewed-by: Gert Wollny Part-of: --- src/gallium/drivers/virgl/virgl_encode.c | 6 ++++ src/gallium/drivers/virgl/virgl_encode.h | 2 ++ src/gallium/drivers/virgl/virgl_screen.c | 43 ++++++++++++++++++++++++ src/virtio/virtio-gpu/virgl_hw.h | 1 + src/virtio/virtio-gpu/virgl_protocol.h | 11 ++++++ 5 files changed, 63 insertions(+) diff --git a/src/gallium/drivers/virgl/virgl_encode.c b/src/gallium/drivers/virgl/virgl_encode.c index d93fb85098a..1040e2cacf7 100644 --- a/src/gallium/drivers/virgl/virgl_encode.c +++ b/src/gallium/drivers/virgl/virgl_encode.c @@ -1505,3 +1505,9 @@ void virgl_encode_end_transfers(struct virgl_cmd_buf *buf) virgl_encoder_write_dword(buf, command); } } + +void virgl_encode_get_memory_info(struct virgl_context *ctx, struct virgl_resource *res) +{ + virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_GET_MEMORY_INFO, 0, 1)); + virgl_encoder_write_res(ctx, res); +} diff --git a/src/gallium/drivers/virgl/virgl_encode.h b/src/gallium/drivers/virgl/virgl_encode.h index a1f9a884d48..074f0ff3bcc 100644 --- a/src/gallium/drivers/virgl/virgl_encode.h +++ b/src/gallium/drivers/virgl/virgl_encode.h @@ -308,5 +308,7 @@ void virgl_encode_end_transfers(struct virgl_cmd_buf *buf); int virgl_encode_tweak(struct virgl_context *ctx, enum vrend_tweak_type tweak, uint32_t value); +void virgl_encode_get_memory_info(struct virgl_context *ctx, struct virgl_resource *res); + enum virgl_formats pipe_to_virgl_format(enum pipe_format format); #endif diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c index 24c692df405..be1b5dfc907 100644 --- a/src/gallium/drivers/virgl/virgl_screen.c +++ b/src/gallium/drivers/virgl/virgl_screen.c @@ -26,6 +26,7 @@ #include "util/u_screen.h" #include "util/u_video.h" #include "util/u_math.h" +#include "util/u_inlines.h" #include "util/os_time.h" #include "util/xmlconfig.h" #include "pipe/p_defines.h" @@ -38,6 +39,7 @@ #include "virgl_public.h" #include "virgl_context.h" #include "virtio-gpu/virgl_protocol.h" +#include "virgl_encode.h" int virgl_debug = 0; static const struct debug_named_value virgl_debug_options[] = { @@ -333,6 +335,8 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param) * in virgl_encode_shader_state(). */ return 0; + case PIPE_CAP_QUERY_MEMORY_INFO: + return vscreen->caps.caps.v2.capability_bits_v2 & VIRGL_CAP_V2_MEMINFO; default: return u_pipe_screen_get_param_defaults(screen, param); } @@ -836,6 +840,44 @@ fixup_formats(union virgl_caps *caps, struct virgl_supported_format_mask *mask) mask->bitmask[i] = caps->v1.sampler.bitmask[i]; } +static void virgl_query_memory_info(struct pipe_screen *screen, struct pipe_memory_info *info) +{ + struct virgl_screen *vscreen = virgl_screen(screen); + struct pipe_context *ctx = screen->context_create(screen, NULL, 0); + struct virgl_context *vctx = virgl_context(ctx); + struct virgl_resource *res; + struct virgl_memory_info virgl_info = {0}; + const static struct pipe_resource templ = { + .target = PIPE_BUFFER, + .format = PIPE_FORMAT_R8_UNORM, + .bind = PIPE_BIND_CUSTOM, + .width0 = sizeof(struct virgl_memory_info), + .height0 = 1, + .depth0 = 1, + .array_size = 1, + .last_level = 0, + .nr_samples = 0, + .flags = 0 + }; + + res = (struct virgl_resource*) screen->resource_create(screen, &templ); + + virgl_encode_get_memory_info(vctx, res); + ctx->flush(ctx, NULL, 0); + vscreen->vws->resource_wait(vscreen->vws, res->hw_res); + pipe_buffer_read(ctx, &res->u.b, 0, sizeof(struct virgl_memory_info), &virgl_info); + + info->avail_device_memory = virgl_info.avail_device_memory; + info->avail_staging_memory = virgl_info.avail_staging_memory; + info->device_memory_evicted = virgl_info.device_memory_evicted; + info->nr_device_memory_evictions = virgl_info.nr_device_memory_evictions; + info->total_device_memory = virgl_info.total_device_memory; + info->total_staging_memory = virgl_info.total_staging_memory; + + screen->resource_destroy(screen, &res->u.b); + ctx->destroy(ctx); +} + struct pipe_screen * virgl_create_screen(struct virgl_winsys *vws, const struct pipe_screen_config *config) { @@ -877,6 +919,7 @@ virgl_create_screen(struct virgl_winsys *vws, const struct pipe_screen_config *c //screen->base.fence_signalled = virgl_fence_signalled; screen->base.fence_finish = virgl_fence_finish; screen->base.fence_get_fd = virgl_fence_get_fd; + screen->base.query_memory_info = virgl_query_memory_info; virgl_init_screen_resource_functions(&screen->base); diff --git a/src/virtio/virtio-gpu/virgl_hw.h b/src/virtio/virtio-gpu/virgl_hw.h index c77d1fcec1f..ecabd8d5c42 100644 --- a/src/virtio/virtio-gpu/virgl_hw.h +++ b/src/virtio/virtio-gpu/virgl_hw.h @@ -440,6 +440,7 @@ enum virgl_formats { #define VIRGL_CAP_V2_BLEND_EQUATION (1 << 0) #define VIRGL_CAP_V2_UNTYPED_RESOURCE (1 << 1) #define VIRGL_CAP_V2_VIDEO_MEMORY (1 << 2) +#define VIRGL_CAP_V2_MEMINFO (1 << 3) /* virgl bind flags - these are compatible with mesa 10.5 gallium. * but are fixed, no other should be passed to virgl either. diff --git a/src/virtio/virtio-gpu/virgl_protocol.h b/src/virtio/virtio-gpu/virgl_protocol.h index f6c7164dafc..d8d7b16dc89 100644 --- a/src/virtio/virtio-gpu/virgl_protocol.h +++ b/src/virtio/virtio-gpu/virgl_protocol.h @@ -35,6 +35,16 @@ struct virgl_host_query_state { uint64_t result; }; +struct virgl_memory_info +{ + uint32_t total_device_memory; /**< size of device memory, e.g. VRAM */ + uint32_t avail_device_memory; /**< free device memory at the moment */ + uint32_t total_staging_memory; /**< size of staging memory, e.g. GART */ + uint32_t avail_staging_memory; /**< free staging memory at the moment */ + uint32_t device_memory_evicted; /**< size of memory evicted (monotonic counter) */ + uint32_t nr_device_memory_evictions; /**< # of evictions (monotonic counter) */ +}; + enum virgl_object_type { VIRGL_OBJECT_NULL, VIRGL_OBJECT_BLEND, @@ -103,6 +113,7 @@ enum virgl_context_cmd { VIRGL_CCMD_CLEAR_TEXTURE, VIRGL_CCMD_PIPE_RESOURCE_CREATE, VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE, + VIRGL_CCMD_GET_MEMORY_INFO, VIRGL_MAX_COMMANDS };