virgl: Support new resource-layout command
Support new vrend command that queries layout of a backing GBM buffer for a giver vrend resource. Use it for querying stride/modifier of a PIPE_SHARED resource, passing this info down to WSI for exported resources. Now venus is able to import vrend resources, making gamescope work in KMS mode on QEMU. Virgl doesn't use stride/modifier info of winsys when it imports classic vrend resources, hence this change only affects venus context when it imports virgl WSI buffers. Based on initial version of resource-layout command from Daniel Stone. Reviewed-by: Gert Wollny <gert.wollny@collabora.com> Acked-by: Yiwei Zhang <zzyiwei@gmail.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37646>
This commit is contained in:
committed by
Marge Bot
parent
29b64d6636
commit
25881c701a
@@ -1892,3 +1892,12 @@ int virgl_encode_clear_surface(struct virgl_context *ctx,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void virgl_encoder_get_layout(struct virgl_context *ctx,
|
||||
struct virgl_resource *out_res,
|
||||
struct virgl_resource *res)
|
||||
{
|
||||
virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_GET_PIPE_RESOURCE_LAYOUT, 0, VIRGL_RESOURCE_LAYOUT_SIZE));
|
||||
virgl_encoder_write_res(ctx, out_res);
|
||||
virgl_encoder_write_res(ctx, res);
|
||||
}
|
||||
|
||||
@@ -341,6 +341,10 @@ int virgl_encode_clear_surface(struct virgl_context *ctx,
|
||||
unsigned width, unsigned height,
|
||||
bool render_condition_enabled);
|
||||
|
||||
void virgl_encoder_get_layout(struct virgl_context *ctx,
|
||||
struct virgl_resource *out_res,
|
||||
struct virgl_resource *res);
|
||||
|
||||
enum virgl_formats pipe_to_virgl_format(enum pipe_format format);
|
||||
enum pipe_format virgl_to_pipe_format(enum virgl_formats format);
|
||||
#endif
|
||||
|
||||
@@ -642,6 +642,89 @@ static void virgl_resource_layout(struct pipe_resource *pt,
|
||||
metadata->total_size = 0;
|
||||
}
|
||||
|
||||
static void virgl_resource_free_gbm_layout(struct virgl_resource *res)
|
||||
{
|
||||
if (!res->metadata.gbm.res)
|
||||
return;
|
||||
|
||||
res->metadata.gbm.ctx->destroy(res->metadata.gbm.ctx);
|
||||
pipe_resource_reference((struct pipe_resource **)&res->metadata.gbm.res, NULL);
|
||||
}
|
||||
|
||||
static void virgl_resource_sync_gbm_layout(struct virgl_resource *res)
|
||||
{
|
||||
struct virgl_screen *vs = virgl_screen(res->b.screen);
|
||||
|
||||
simple_mtx_lock(&res->metadata.gbm.lock);
|
||||
if (res->metadata.gbm.res) {
|
||||
vs->vws->resource_wait(vs->vws, res->metadata.gbm.res->hw_res);
|
||||
|
||||
pipe_buffer_read(res->metadata.gbm.ctx,
|
||||
&res->metadata.gbm.res->b, 0,
|
||||
sizeof(res->metadata.gbm.layout),
|
||||
&res->metadata.gbm.layout);
|
||||
|
||||
virgl_resource_free_gbm_layout(res);
|
||||
}
|
||||
simple_mtx_unlock(&res->metadata.gbm.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
virgl_resource_async_query_gbm_layout(struct pipe_screen *screen,
|
||||
struct pipe_resource *resource,
|
||||
uint32_t bind)
|
||||
{
|
||||
struct virgl_resource *res = virgl_resource(resource);
|
||||
struct virgl_screen *vs = virgl_screen(screen);
|
||||
struct virgl_resource *out_res;
|
||||
struct virgl_context *vctx;
|
||||
struct pipe_context *ctx;
|
||||
|
||||
if (!(bind & PIPE_BIND_SHARED))
|
||||
return;
|
||||
|
||||
if (!(vs->caps.caps.v2.capability_bits_v2 & VIRGL_CAP_V2_RESOURCE_LAYOUT))
|
||||
return;
|
||||
|
||||
out_res = (struct virgl_resource *)
|
||||
pipe_buffer_create(&vs->base, PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING,
|
||||
sizeof(res->metadata.gbm.layout));
|
||||
if (!out_res)
|
||||
return;
|
||||
|
||||
ctx = screen->context_create(screen, NULL, 0);
|
||||
vctx = virgl_context(ctx);
|
||||
|
||||
virgl_encoder_get_layout(vctx, out_res, res);
|
||||
ctx->flush(ctx, NULL, 0);
|
||||
|
||||
/*
|
||||
* Async query must be completed by virgl_resource_sync_gbm_layout().
|
||||
* Returned layout will be zeroed if resource isn't backed by GBM buffer.
|
||||
*/
|
||||
res->metadata.gbm.res = out_res;
|
||||
res->metadata.gbm.ctx = ctx;
|
||||
}
|
||||
|
||||
static size_t virgl_resource_shared_tex_size(struct virgl_resource *res)
|
||||
{
|
||||
size_t aligned_stride = align(res->metadata.stride[0], 256);
|
||||
struct virgl_resource_metadata metadata = {};
|
||||
|
||||
/*
|
||||
* Size of a shared buffer is validated by WSI. WSI retrieves BO size
|
||||
* from resource's dmabuf with lseek(). When shared buffer is backed
|
||||
* by a GBM BO on host, WSI validation may fail for a classic resource
|
||||
* because we will tell WSI to use stride of the host's GBM BO that won't
|
||||
* match guest BO stride. Mitigate this problem by using stride aligned to
|
||||
* 256 bytes for estimated buffer size, which is a max possible alignment
|
||||
* that GPUs are using today.
|
||||
*/
|
||||
virgl_resource_layout(&res->b, &metadata, 0, aligned_stride, 0, 0);
|
||||
|
||||
return metadata.total_size;
|
||||
}
|
||||
|
||||
static struct pipe_resource *virgl_resource_create_front(struct pipe_screen *screen,
|
||||
const struct pipe_resource *templ,
|
||||
const void *map_front_private)
|
||||
@@ -657,6 +740,7 @@ static struct pipe_resource *virgl_resource_create_front(struct pipe_screen *scr
|
||||
vbind = pipe_to_virgl_bind(vs, templ->bind);
|
||||
vflags = pipe_to_virgl_flags(vs, templ->flags);
|
||||
virgl_resource_layout(&res->b, &res->metadata, 0, 0, 0, 0);
|
||||
simple_mtx_init(&res->metadata.gbm.lock, mtx_plain);
|
||||
|
||||
if ((vs->caps.caps.v2.capability_bits & VIRGL_CAP_APP_TWEAK_SUPPORT) &&
|
||||
vs->tweak_gles_emulate_bgra &&
|
||||
@@ -674,6 +758,8 @@ static struct pipe_resource *virgl_resource_create_front(struct pipe_screen *scr
|
||||
|
||||
if (res->use_staging)
|
||||
alloc_size = 1;
|
||||
else if (templ->bind & PIPE_BIND_SHARED)
|
||||
alloc_size = virgl_resource_shared_tex_size(res);
|
||||
else
|
||||
alloc_size = res->metadata.total_size;
|
||||
|
||||
@@ -700,6 +786,7 @@ static struct pipe_resource *virgl_resource_create_front(struct pipe_screen *scr
|
||||
virgl_buffer_init(res);
|
||||
} else {
|
||||
virgl_texture_init(res);
|
||||
virgl_resource_async_query_gbm_layout(screen, &res->b, templ->bind);
|
||||
}
|
||||
|
||||
return &res->b;
|
||||
@@ -829,6 +916,7 @@ static struct pipe_resource *virgl_resource_from_handle(struct pipe_screen *scre
|
||||
}
|
||||
|
||||
virgl_texture_init(res);
|
||||
virgl_resource_async_query_gbm_layout(screen, &res->b, PIPE_BIND_SHARED);
|
||||
|
||||
return &res->b;
|
||||
}
|
||||
@@ -848,7 +936,12 @@ virgl_resource_get_param(struct pipe_screen *screen,
|
||||
|
||||
switch(param) {
|
||||
case PIPE_RESOURCE_PARAM_MODIFIER:
|
||||
*value = res->metadata.modifier;
|
||||
virgl_resource_sync_gbm_layout(res);
|
||||
|
||||
if (res->metadata.gbm.layout.planes[0].stride)
|
||||
*value = res->metadata.gbm.layout.modifier;
|
||||
else
|
||||
*value = res->metadata.modifier;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -987,6 +1080,7 @@ void virgl_resource_destroy(struct pipe_screen *screen,
|
||||
util_range_destroy(&res->valid_buffer_range);
|
||||
|
||||
vs->vws->resource_reference(vs->vws, &res->hw_res, NULL);
|
||||
virgl_resource_free_gbm_layout(res);
|
||||
FREE(res);
|
||||
}
|
||||
|
||||
@@ -998,13 +1092,19 @@ bool virgl_resource_get_handle(struct pipe_screen *screen,
|
||||
{
|
||||
struct virgl_screen *vs = virgl_screen(screen);
|
||||
struct virgl_resource *res = virgl_resource(resource);
|
||||
int stride;
|
||||
|
||||
if (res->b.target == PIPE_BUFFER)
|
||||
return false;
|
||||
|
||||
return vs->vws->resource_get_handle(vs->vws, res->hw_res,
|
||||
res->metadata.stride[0],
|
||||
whandle);
|
||||
virgl_resource_sync_gbm_layout(res);
|
||||
|
||||
if (res->metadata.gbm.layout.planes[0].stride)
|
||||
stride = res->metadata.gbm.layout.planes[0].stride;
|
||||
else
|
||||
stride = res->metadata.stride[0];
|
||||
|
||||
return vs->vws->resource_get_handle(vs->vws, res->hw_res, stride, whandle);
|
||||
}
|
||||
|
||||
void virgl_resource_dirty(struct virgl_resource *res, uint32_t level)
|
||||
|
||||
@@ -41,6 +41,14 @@ struct winsys_handle;
|
||||
struct virgl_screen;
|
||||
struct virgl_context;
|
||||
|
||||
struct virgl_resource_gbm_metadata
|
||||
{
|
||||
struct virgl_resource_layout layout;
|
||||
struct virgl_resource *res;
|
||||
struct pipe_context *ctx;
|
||||
simple_mtx_t lock;
|
||||
};
|
||||
|
||||
struct virgl_resource_metadata
|
||||
{
|
||||
unsigned long level_offset[VR_MAX_TEXTURE_2D_LEVELS];
|
||||
@@ -48,6 +56,7 @@ struct virgl_resource_metadata
|
||||
unsigned layer_stride[VR_MAX_TEXTURE_2D_LEVELS];
|
||||
uint32_t plane, plane_offset, total_size;
|
||||
uint64_t modifier;
|
||||
struct virgl_resource_gbm_metadata gbm;
|
||||
};
|
||||
|
||||
struct virgl_resource {
|
||||
|
||||
@@ -627,6 +627,7 @@ enum virgl_formats {
|
||||
#define VIRGL_CAP_V2_GROUP_VOTE (1u << 15)
|
||||
#define VIRGL_CAP_V2_MIRROR_CLAMP_TO_EDGE (1u << 16)
|
||||
#define VIRGL_CAP_V2_MIRROR_CLAMP (1u << 17)
|
||||
#define VIRGL_CAP_V2_RESOURCE_LAYOUT (1u << 18)
|
||||
|
||||
/* virgl bind flags - these are compatible with mesa 10.5 gallium.
|
||||
* but are fixed, no other should be passed to virgl either.
|
||||
|
||||
@@ -45,6 +45,19 @@ struct virgl_memory_info
|
||||
uint32_t nr_device_memory_evictions; /**< # of evictions (monotonic counter) */
|
||||
};
|
||||
|
||||
#define VIRGL_RESOURCE_MAX_PLANES 4
|
||||
struct virgl_resource_layout
|
||||
{
|
||||
uint64_t modifier;
|
||||
uint32_t num_planes;
|
||||
uint32_t reserved1;
|
||||
struct {
|
||||
uint64_t offset;
|
||||
uint32_t stride;
|
||||
uint32_t size;
|
||||
} planes[VIRGL_RESOURCE_MAX_PLANES];
|
||||
};
|
||||
|
||||
enum virgl_object_type {
|
||||
VIRGL_OBJECT_NULL,
|
||||
VIRGL_OBJECT_BLEND,
|
||||
@@ -130,6 +143,7 @@ enum virgl_context_cmd {
|
||||
VIRGL_CCMD_END_FRAME,
|
||||
|
||||
VIRGL_CCMD_CLEAR_SURFACE,
|
||||
VIRGL_CCMD_GET_PIPE_RESOURCE_LAYOUT,
|
||||
|
||||
VIRGL_MAX_COMMANDS
|
||||
};
|
||||
@@ -780,4 +794,9 @@ enum vrend_tweak_type {
|
||||
#define VIRGL_CLEAR_SURFACE_WIDTH 9
|
||||
#define VIRGL_CLEAR_SURFACE_HEIGHT 10
|
||||
|
||||
/* VIRGL_CCMD_GET_PIPE_RESOURCE_LAYOUT */
|
||||
#define VIRGL_RESOURCE_LAYOUT_SIZE 2
|
||||
#define VIRGL_RESOURCE_LAYOUT_HANDLE_OUT 1
|
||||
#define VIRGL_RESOURCE_LAYOUT_HANDLE_TARGET 2
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user