Skip to content

Commit

Permalink
drm/vmwgfx: Add support for UA view commands
Browse files Browse the repository at this point in the history
Virtual device now support new commands to manage unordered access
views. Allow them as part of user-space command buffer. This involves
adding UA view cotable, binding tracker info, new view type and command
verifier functions.

v2: fix comment typo
v3: style fixes (don't use deprecated PTR_RET)

Signed-off-by: Deepak Rawat <drawat.floss@gmail.com>
Signed-off-by: Neha Bhende <bhenden@vmware.com>
Reviewed-by: Thomas Hellström (VMware) <thomas_os@shipmail.org>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Signed-off-by: Roland Scheidegger <sroland@vmware.com>
  • Loading branch information
Deepak Rawat authored and Roland Scheidegger committed Mar 23, 2020
1 parent d2e90ab commit 5e8ec0d
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 18 deletions.
129 changes: 125 additions & 4 deletions drivers/gpu/drm/vmwgfx/vmwgfx_binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@
#define VMW_BINDING_PS_BIT 1
#define VMW_BINDING_SO_BIT 2
#define VMW_BINDING_VB_BIT 3
#define VMW_BINDING_NUM_BITS 4
#define VMW_BINDING_UAV_BIT 4
#define VMW_BINDING_CS_UAV_BIT 5
#define VMW_BINDING_NUM_BITS 6

#define VMW_BINDING_PS_SR_BIT 0

Expand All @@ -75,6 +77,7 @@
* @vertex_buffers: Vertex buffer bindings.
* @index_buffer: Index buffer binding.
* @per_shader: Per shader-type bindings.
* @ua_views: UAV bindings.
* @dirty: Bitmap tracking per binding-type changes that have not yet
* been emitted to the device.
* @dirty_vb: Bitmap tracking individual vertex buffer binding changes that
Expand All @@ -99,6 +102,7 @@ struct vmw_ctx_binding_state {
struct vmw_ctx_bindinfo_vb vertex_buffers[SVGA3D_DX_MAX_VERTEXBUFFERS];
struct vmw_ctx_bindinfo_ib index_buffer;
struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE];
struct vmw_ctx_bindinfo_uav ua_views[VMW_MAX_UAV_BIND_TYPE];

unsigned long dirty;
DECLARE_BITMAP(dirty_vb, SVGA3D_DX_MAX_VERTEXBUFFERS);
Expand All @@ -121,6 +125,9 @@ static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi,
bool rebind);
static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind);
static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind);
static int vmw_binding_scrub_uav(struct vmw_ctx_bindinfo *bi, bool rebind);
static int vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo *bi, bool rebind);

static void vmw_binding_build_asserts(void) __attribute__ ((unused));

typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
Expand Down Expand Up @@ -189,6 +196,12 @@ static const size_t vmw_binding_vb_offsets[] = {
static const size_t vmw_binding_ib_offsets[] = {
offsetof(struct vmw_ctx_binding_state, index_buffer),
};
static const size_t vmw_binding_uav_offsets[] = {
offsetof(struct vmw_ctx_binding_state, ua_views[0].views),
};
static const size_t vmw_binding_cs_uav_offsets[] = {
offsetof(struct vmw_ctx_binding_state, ua_views[1].views),
};

static const struct vmw_binding_info vmw_binding_infos[] = {
[vmw_ctx_binding_shader] = {
Expand Down Expand Up @@ -235,6 +248,14 @@ static const struct vmw_binding_info vmw_binding_infos[] = {
.size = sizeof(struct vmw_ctx_bindinfo_ib),
.offsets = vmw_binding_ib_offsets,
.scrub_func = vmw_binding_scrub_ib},
[vmw_ctx_binding_uav] = {
.size = sizeof(struct vmw_ctx_bindinfo_view),
.offsets = vmw_binding_uav_offsets,
.scrub_func = vmw_binding_scrub_uav},
[vmw_ctx_binding_cs_uav] = {
.size = sizeof(struct vmw_ctx_bindinfo_view),
.offsets = vmw_binding_cs_uav_offsets,
.scrub_func = vmw_binding_scrub_cs_uav},
};

/**
Expand Down Expand Up @@ -320,6 +341,18 @@ void vmw_binding_add(struct vmw_ctx_binding_state *cbs,
INIT_LIST_HEAD(&loc->res_list);
}

/**
* vmw_binding_add_uav_index - Add UAV index for tracking.
* @cbs: Pointer to the context binding state tracker.
* @slot: UAV type to which bind this index.
* @index: The splice index to track.
*/
void vmw_binding_add_uav_index(struct vmw_ctx_binding_state *cbs, uint32 slot,
uint32 index)
{
cbs->ua_views[slot].index = index;
}

/**
* vmw_binding_transfer: Transfer a context binding tracking entry.
*
Expand Down Expand Up @@ -459,6 +492,10 @@ void vmw_binding_state_commit(struct vmw_ctx_binding_state *to,
vmw_binding_transfer(to, from, entry);
vmw_binding_drop(entry);
}

/* Also transfer uav splice indices */
to->ua_views[0].index = from->ua_views[0].index;
to->ua_views[1].index = from->ua_views[1].index;
}

/**
Expand Down Expand Up @@ -1014,6 +1051,66 @@ static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs)
return 0;
}

static int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs)
{
const struct vmw_ctx_bindinfo *loc = &cbs->ua_views[0].views[0].bi;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetUAViews body;
} *cmd;
size_t cmd_size, view_id_size;
const struct vmw_resource *ctx = vmw_cbs_context(cbs);

vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_UAVIEWS);
view_id_size = cbs->bind_cmd_count*sizeof(uint32);
cmd_size = sizeof(*cmd) + view_id_size;
cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id);
if (!cmd)
return -ENOMEM;

cmd->header.id = SVGA_3D_CMD_DX_SET_UA_VIEWS;
cmd->header.size = sizeof(cmd->body) + view_id_size;

/* Splice index is specified user-space */
cmd->body.uavSpliceIndex = cbs->ua_views[0].index;

memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);

vmw_fifo_commit(ctx->dev_priv, cmd_size);

return 0;
}

static int vmw_emit_set_cs_uav(struct vmw_ctx_binding_state *cbs)
{
const struct vmw_ctx_bindinfo *loc = &cbs->ua_views[1].views[0].bi;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetCSUAViews body;
} *cmd;
size_t cmd_size, view_id_size;
const struct vmw_resource *ctx = vmw_cbs_context(cbs);

vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_UAVIEWS);
view_id_size = cbs->bind_cmd_count*sizeof(uint32);
cmd_size = sizeof(*cmd) + view_id_size;
cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id);
if (!cmd)
return -ENOMEM;

cmd->header.id = SVGA_3D_CMD_DX_SET_CS_UA_VIEWS;
cmd->header.size = sizeof(cmd->body) + view_id_size;

/* Start index is specified user-space */
cmd->body.startIndex = cbs->ua_views[1].index;

memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);

vmw_fifo_commit(ctx->dev_priv, cmd_size);

return 0;
}

/**
* vmw_binding_emit_dirty - Issue delayed binding commands
*
Expand Down Expand Up @@ -1045,6 +1142,12 @@ static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs)
case VMW_BINDING_VB_BIT:
ret = vmw_emit_set_vb(cbs);
break;
case VMW_BINDING_UAV_BIT:
ret = vmw_emit_set_uav(cbs);
break;
case VMW_BINDING_CS_UAV_BIT:
ret = vmw_emit_set_cs_uav(cbs);
break;
default:
BUG();
}
Expand Down Expand Up @@ -1171,6 +1274,22 @@ static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind)
return 0;
}

static int vmw_binding_scrub_uav(struct vmw_ctx_bindinfo *bi, bool rebind)
{
struct vmw_ctx_binding_state *cbs = vmw_context_binding_state(bi->ctx);

__set_bit(VMW_BINDING_UAV_BIT, &cbs->dirty);
return 0;
}

static int vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo *bi, bool rebind)
{
struct vmw_ctx_binding_state *cbs = vmw_context_binding_state(bi->ctx);

__set_bit(VMW_BINDING_CS_UAV_BIT, &cbs->dirty);
return 0;
}

/**
* vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state with
* memory accounting.
Expand Down Expand Up @@ -1257,8 +1376,8 @@ void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs)
* Each time a resource is put on the validation list as the result of a
* context binding referencing it, we need to determine whether that resource
* will be dirtied (written to by the GPU) as a result of the corresponding
* GPU operation. Currently rendertarget-, depth-stencil-, and
* stream-output-target bindings are capable of dirtying its resource.
* GPU operation. Currently rendertarget-, depth-stencil-, stream-output-target
* and unordered access view bindings are capable of dirtying its resource.
*
* Return: Whether the binding type dirties the resource its binding points to.
*/
Expand All @@ -1269,10 +1388,12 @@ u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type)
[vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET,
[vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET,
[vmw_ctx_binding_so] = VMW_RES_DIRTY_SET,
[vmw_ctx_binding_uav] = VMW_RES_DIRTY_SET,
[vmw_ctx_binding_cs_uav] = VMW_RES_DIRTY_SET,
};

/* Review this function as new bindings are added. */
BUILD_BUG_ON(vmw_ctx_binding_max != 11);
BUILD_BUG_ON(vmw_ctx_binding_max != 13);
return is_binding_dirtying[binding_type];
}

Expand Down
16 changes: 16 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

#define VMW_MAX_VIEW_BINDINGS 128

#define VMW_MAX_UAV_BIND_TYPE 2

struct vmw_private;
struct vmw_ctx_binding_state;

Expand All @@ -51,6 +53,8 @@ enum vmw_ctx_binding_type {
vmw_ctx_binding_so,
vmw_ctx_binding_vb,
vmw_ctx_binding_ib,
vmw_ctx_binding_uav,
vmw_ctx_binding_cs_uav,
vmw_ctx_binding_max
};

Expand Down Expand Up @@ -189,9 +193,21 @@ struct vmw_dx_shader_bindings {
unsigned long dirty;
};

/**
* struct vmw_ctx_bindinfo_uav - UAV context binding state.
* @views: UAV view bindings.
* @splice_index: The device splice index set by user-space.
*/
struct vmw_ctx_bindinfo_uav {
struct vmw_ctx_bindinfo_view views[SVGA3D_MAX_UAVIEWS];
uint32 index;
};

extern void vmw_binding_add(struct vmw_ctx_binding_state *cbs,
const struct vmw_ctx_bindinfo *ci,
u32 shader_slot, u32 slot);
extern void vmw_binding_add_uav_index(struct vmw_ctx_binding_state *cbs,
uint32 slot, uint32 splice_index);
extern void
vmw_binding_state_commit(struct vmw_ctx_binding_state *to,
struct vmw_ctx_binding_state *from);
Expand Down
26 changes: 18 additions & 8 deletions drivers/gpu/drm/vmwgfx/vmwgfx_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct vmw_user_context {
struct vmw_resource res;
struct vmw_ctx_binding_state *cbs;
struct vmw_cmdbuf_res_manager *man;
struct vmw_resource *cotables[SVGA_COTABLE_DX10_MAX];
struct vmw_resource *cotables[SVGA_COTABLE_MAX];
spinlock_t cotable_lock;
struct vmw_buffer_object *dx_query_mob;
};
Expand Down Expand Up @@ -116,12 +116,15 @@ static const struct vmw_res_func vmw_dx_context_func = {
* Context management:
*/

static void vmw_context_cotables_unref(struct vmw_user_context *uctx)
static void vmw_context_cotables_unref(struct vmw_private *dev_priv,
struct vmw_user_context *uctx)
{
struct vmw_resource *res;
int i;
u32 cotable_max = has_sm5_context(dev_priv) ?
SVGA_COTABLE_MAX : SVGA_COTABLE_DX10_MAX;

for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
for (i = 0; i < cotable_max; ++i) {
spin_lock(&uctx->cotable_lock);
res = uctx->cotables[i];
uctx->cotables[i] = NULL;
Expand Down Expand Up @@ -155,7 +158,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
!dev_priv->query_cid_valid)
__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
mutex_unlock(&dev_priv->cmdbuf_mutex);
vmw_context_cotables_unref(uctx);
vmw_context_cotables_unref(dev_priv, uctx);
return;
}

Expand Down Expand Up @@ -208,7 +211,9 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
spin_lock_init(&uctx->cotable_lock);

if (dx) {
for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
u32 cotable_max = has_sm5_context(dev_priv) ?
SVGA_COTABLE_MAX : SVGA_COTABLE_DX10_MAX;
for (i = 0; i < cotable_max; ++i) {
uctx->cotables[i] = vmw_cotable_alloc(dev_priv,
&uctx->res, i);
if (IS_ERR(uctx->cotables[i])) {
Expand All @@ -222,7 +227,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
return 0;

out_cotables:
vmw_context_cotables_unref(uctx);
vmw_context_cotables_unref(dev_priv, uctx);
out_err:
if (res_free)
res_free(res);
Expand Down Expand Up @@ -545,10 +550,12 @@ void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx,
{
struct vmw_user_context *uctx =
container_of(ctx, struct vmw_user_context, res);
u32 cotable_max = has_sm5_context(ctx->dev_priv) ?
SVGA_COTABLE_MAX : SVGA_COTABLE_DX10_MAX;
int i;

vmw_binding_state_scrub(uctx->cbs);
for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
for (i = 0; i < cotable_max; ++i) {
struct vmw_resource *res;

/* Avoid racing with ongoing cotable destruction. */
Expand Down Expand Up @@ -839,7 +846,10 @@ struct vmw_cmdbuf_res_manager *vmw_context_res_man(struct vmw_resource *ctx)
struct vmw_resource *vmw_context_cotable(struct vmw_resource *ctx,
SVGACOTableType cotable_type)
{
if (cotable_type >= SVGA_COTABLE_DX10_MAX)
u32 cotable_max = has_sm5_context(ctx->dev_priv) ?
SVGA_COTABLE_MAX : SVGA_COTABLE_DX10_MAX;

if (cotable_type >= cotable_max)
return ERR_PTR(-EINVAL);

return container_of(ctx, struct vmw_user_context, res)->
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ static const struct vmw_cotable_info co_info[] = {
{1, sizeof(SVGACOTableDXSamplerEntry), NULL},
{1, sizeof(SVGACOTableDXStreamOutputEntry), NULL},
{1, sizeof(SVGACOTableDXQueryEntry), NULL},
{1, sizeof(SVGACOTableDXShaderEntry), &vmw_dx_shader_cotable_list_scrub}
{1, sizeof(SVGACOTableDXShaderEntry), &vmw_dx_shader_cotable_list_scrub},
{1, sizeof(SVGACOTableDXUAViewEntry), &vmw_view_cotable_list_destroy}
};

/*
Expand All @@ -102,6 +103,7 @@ const SVGACOTableType vmw_cotable_scrub_order[] = {
SVGA_COTABLE_SAMPLER,
SVGA_COTABLE_STREAMOUTPUT,
SVGA_COTABLE_DXQUERY,
SVGA_COTABLE_UAVIEW,
};

static int vmw_cotable_bind(struct vmw_resource *res,
Expand Down
Loading

0 comments on commit 5e8ec0d

Please sign in to comment.