This series is:
Reviewed-by: Gurchetan Singh <gurchetansi...@chromium.org> On Tue, Jul 31, 2018 at 3:29 PM Dave Airlie <airl...@gmail.com> wrote: > > From: Dave Airlie <airl...@redhat.com> > > This hooks up compute shader creation and launch grid support. > --- > src/gallium/drivers/virgl/virgl_context.c | 55 ++++++++++++++++++++++++++-- > src/gallium/drivers/virgl/virgl_encode.c | 25 ++++++++++++- > src/gallium/drivers/virgl/virgl_encode.h | 3 ++ > src/gallium/drivers/virgl/virgl_hw.h | 5 +++ > src/gallium/drivers/virgl/virgl_protocol.h | 11 ++++++ > src/gallium/drivers/virgl/virgl_screen.c | 59 > ++++++++++++++++++++++++++++-- > src/gallium/drivers/virgl/virgl_winsys.h | 2 + > 7 files changed, 153 insertions(+), 7 deletions(-) > > diff --git a/src/gallium/drivers/virgl/virgl_context.c > b/src/gallium/drivers/virgl/virgl_context.c > index d224b68cfcd..ae1da337994 100644 > --- a/src/gallium/drivers/virgl/virgl_context.c > +++ b/src/gallium/drivers/virgl/virgl_context.c > @@ -506,7 +506,7 @@ static void *virgl_shader_encoder(struct pipe_context > *ctx, > handle = virgl_object_assign_handle(); > /* encode VS state */ > ret = virgl_encode_shader_state(vctx, handle, type, > - &shader->stream_output, > + &shader->stream_output, 0, > new_tokens); > if (ret) { > return NULL; > @@ -961,7 +961,7 @@ static void virgl_set_shader_buffers(struct pipe_context > *ctx, > pipe_resource_reference(&vctx->ssbos[shader][idx], NULL); > } > > - uint32_t max_shader_buffer = shader == PIPE_SHADER_FRAGMENT ? > + uint32_t max_shader_buffer = (shader == PIPE_SHADER_FRAGMENT || shader == > PIPE_SHADER_COMPUTE) ? > rs->caps.caps.v2.max_shader_buffer_frag_compute : > rs->caps.caps.v2.max_shader_buffer_other_stages; > if (!max_shader_buffer) > @@ -989,7 +989,7 @@ static void virgl_set_shader_images(struct pipe_context > *ctx, > pipe_resource_reference(&vctx->images[shader][idx], NULL); > } > > - uint32_t max_shader_images = shader == PIPE_SHADER_FRAGMENT ? > + uint32_t max_shader_images = (shader == PIPE_SHADER_FRAGMENT || shader == > PIPE_SHADER_COMPUTE) ? > rs->caps.caps.v2.max_shader_image_frag_compute : > rs->caps.caps.v2.max_shader_image_other_stages; > if (!max_shader_images) > @@ -1008,6 +1008,50 @@ static void virgl_memory_barrier(struct pipe_context > *ctx, > virgl_encode_memory_barrier(vctx, flags); > } > > +static void *virgl_create_compute_state(struct pipe_context *ctx, > + const struct pipe_compute_state > *state) > +{ > + struct virgl_context *vctx = virgl_context(ctx); > + uint32_t handle; > + const struct tgsi_token *new_tokens = state->prog; > + struct pipe_stream_output_info so_info = {}; > + int ret; > + > + handle = virgl_object_assign_handle(); > + ret = virgl_encode_shader_state(vctx, handle, PIPE_SHADER_COMPUTE, > + &so_info, > + state->req_local_mem, > + new_tokens); > + if (ret) { > + return NULL; > + } > + > + return (void *)(unsigned long)handle; > +} > + > +static void virgl_bind_compute_state(struct pipe_context *ctx, void *state) > +{ > + uint32_t handle = (unsigned long)state; > + struct virgl_context *vctx = virgl_context(ctx); > + > + virgl_encode_bind_shader(vctx, handle, PIPE_SHADER_COMPUTE); > +} > + > +static void virgl_delete_compute_state(struct pipe_context *ctx, void *state) > +{ > + uint32_t handle = (unsigned long)state; > + struct virgl_context *vctx = virgl_context(ctx); > + > + virgl_encode_delete_object(vctx, handle, VIRGL_OBJECT_SHADER); > +} > + > +static void virgl_launch_grid(struct pipe_context *ctx, > + const struct pipe_grid_info *info) > +{ > + struct virgl_context *vctx = virgl_context(ctx); > + virgl_encode_launch_grid(vctx, info); > +} > + > static void > virgl_context_destroy( struct pipe_context *ctx ) > { > @@ -1118,6 +1162,11 @@ struct pipe_context *virgl_context_create(struct > pipe_screen *pscreen, > vctx->base.delete_gs_state = virgl_delete_gs_state; > vctx->base.delete_fs_state = virgl_delete_fs_state; > > + vctx->base.create_compute_state = virgl_create_compute_state; > + vctx->base.bind_compute_state = virgl_bind_compute_state; > + vctx->base.delete_compute_state = virgl_delete_compute_state; > + vctx->base.launch_grid = virgl_launch_grid; > + > vctx->base.clear = virgl_clear; > vctx->base.draw_vbo = virgl_draw_vbo; > vctx->base.flush = virgl_flush_from_st; > diff --git a/src/gallium/drivers/virgl/virgl_encode.c > b/src/gallium/drivers/virgl/virgl_encode.c > index 1d193ae6c7f..0cb5184d193 100644 > --- a/src/gallium/drivers/virgl/virgl_encode.c > +++ b/src/gallium/drivers/virgl/virgl_encode.c > @@ -241,6 +241,7 @@ int virgl_encode_shader_state(struct virgl_context *ctx, > uint32_t handle, > uint32_t type, > const struct pipe_stream_output_info *so_info, > + uint32_t cs_req_local_mem, > const struct tgsi_token *tokens) > { > char *str, *sptr; > @@ -298,7 +299,10 @@ int virgl_encode_shader_state(struct virgl_context *ctx, > > virgl_emit_shader_header(ctx, handle, len, type, offlen, num_tokens); > > - virgl_emit_shader_streamout(ctx, first_pass ? so_info : NULL); > + if (type == PIPE_SHADER_COMPUTE) > + virgl_encoder_write_dword(ctx->cbuf, cs_req_local_mem); > + else > + virgl_emit_shader_streamout(ctx, first_pass ? so_info : NULL); > > virgl_encoder_write_block(ctx->cbuf, (uint8_t *)sptr, length); > > @@ -980,3 +984,22 @@ int virgl_encode_memory_barrier(struct virgl_context > *ctx, > virgl_encoder_write_dword(ctx->cbuf, flags); > return 0; > } > + > +int virgl_encode_launch_grid(struct virgl_context *ctx, > + const struct pipe_grid_info *grid_info) > +{ > + virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_LAUNCH_GRID, 0, > VIRGL_LAUNCH_GRID_SIZE)); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->block[0]); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->block[1]); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->block[2]); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->grid[0]); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->grid[1]); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->grid[2]); > + if (grid_info->indirect) { > + struct virgl_resource *res = virgl_resource(grid_info->indirect); > + virgl_encoder_write_res(ctx, res); > + } else > + virgl_encoder_write_dword(ctx->cbuf, 0); > + virgl_encoder_write_dword(ctx->cbuf, grid_info->indirect_offset); > + return 0; > +} > diff --git a/src/gallium/drivers/virgl/virgl_encode.h > b/src/gallium/drivers/virgl/virgl_encode.h > index e353c3d04d5..c982eb954f3 100644 > --- a/src/gallium/drivers/virgl/virgl_encode.h > +++ b/src/gallium/drivers/virgl/virgl_encode.h > @@ -90,6 +90,7 @@ extern int virgl_encode_shader_state(struct virgl_context > *ctx, > uint32_t handle, > uint32_t type, > const struct pipe_stream_output_info > *so_info, > + uint32_t cs_req_local_mem, > const struct tgsi_token *tokens); > > int virgl_encode_stream_output_info(struct virgl_context *ctx, > @@ -269,4 +270,6 @@ int virgl_encode_set_shader_images(struct virgl_context > *ctx, > const struct pipe_image_view *images); > int virgl_encode_memory_barrier(struct virgl_context *ctx, > unsigned flags); > +int virgl_encode_launch_grid(struct virgl_context *ctx, > + const struct pipe_grid_info *grid_info); > #endif > diff --git a/src/gallium/drivers/virgl/virgl_hw.h > b/src/gallium/drivers/virgl/virgl_hw.h > index 6bb11f6598a..d58b347020b 100644 > --- a/src/gallium/drivers/virgl/virgl_hw.h > +++ b/src/gallium/drivers/virgl/virgl_hw.h > @@ -206,6 +206,7 @@ enum virgl_formats { > #define VIRGL_CAP_TGSI_PRECISE (1 << 4) > #define VIRGL_CAP_TXQS (1 << 5) > #define VIRGL_CAP_MEMORY_BARRIER (1 << 6) > +#define VIRGL_CAP_COMPUTE_SHADER (1 << 7) > > #define VIRGL_BIND_DEPTH_STENCIL (1 << 0) > #define VIRGL_BIND_RENDER_TARGET (1 << 1) > @@ -312,6 +313,10 @@ struct virgl_caps_v2 { > uint32_t max_shader_image_frag_compute; > uint32_t max_shader_image_other_stages; > uint32_t max_image_samples; > + uint32_t max_compute_work_group_invocations; > + uint32_t max_compute_shared_memory_size; > + uint32_t max_compute_grid_size[3]; > + uint32_t max_compute_block_size[3]; > }; > > union virgl_caps { > diff --git a/src/gallium/drivers/virgl/virgl_protocol.h > b/src/gallium/drivers/virgl/virgl_protocol.h > index 0c38b1fc2ed..b94b7528c0c 100644 > --- a/src/gallium/drivers/virgl/virgl_protocol.h > +++ b/src/gallium/drivers/virgl/virgl_protocol.h > @@ -89,6 +89,7 @@ enum virgl_context_cmd { > VIRGL_CCMD_SET_SHADER_BUFFERS, > VIRGL_CCMD_SET_SHADER_IMAGES, > VIRGL_CCMD_MEMORY_BARRIER, > + VIRGL_CCMD_LAUNCH_GRID, > }; > > /* > @@ -518,4 +519,14 @@ enum virgl_context_cmd { > #define VIRGL_MEMORY_BARRIER_SIZE 1 > #define VIRGL_MEMORY_BARRIER_FLAGS 1 > > +#define VIRGL_LAUNCH_GRID_SIZE 8 > +#define VIRGL_LAUNCH_BLOCK_X 1 > +#define VIRGL_LAUNCH_BLOCK_Y 2 > +#define VIRGL_LAUNCH_BLOCK_Z 3 > +#define VIRGL_LAUNCH_GRID_X 4 > +#define VIRGL_LAUNCH_GRID_Y 5 > +#define VIRGL_LAUNCH_GRID_Z 6 > +#define VIRGL_LAUNCH_INDIRECT_HANDLE 7 > +#define VIRGL_LAUNCH_INDIRECT_OFFSET 8 > + > #endif > diff --git a/src/gallium/drivers/virgl/virgl_screen.c > b/src/gallium/drivers/virgl/virgl_screen.c > index 01e8eaec720..be21a35bf08 100644 > --- a/src/gallium/drivers/virgl/virgl_screen.c > +++ b/src/gallium/drivers/virgl/virgl_screen.c > @@ -139,7 +139,7 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap > param) > case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: > return 0; > case PIPE_CAP_COMPUTE: > - return 0; > + return vscreen->caps.caps.v2.capability_bits & > VIRGL_CAP_COMPUTE_SHADER; > case PIPE_CAP_USER_VERTEX_BUFFERS: > return 0; > case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: > @@ -327,6 +327,10 @@ virgl_get_shader_param(struct pipe_screen *screen, > !vscreen->caps.caps.v1.bset.has_tessellation_shaders) > return 0; > > + if (shader == PIPE_SHADER_COMPUTE && > + !(vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_COMPUTE_SHADER)) > + return 0; > + > switch(shader) > { > case PIPE_SHADER_FRAGMENT: > @@ -334,6 +338,7 @@ virgl_get_shader_param(struct pipe_screen *screen, > case PIPE_SHADER_GEOMETRY: > case PIPE_SHADER_TESS_CTRL: > case PIPE_SHADER_TESS_EVAL: > + case PIPE_SHADER_COMPUTE: > switch (param) { > case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: > case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: > @@ -372,15 +377,17 @@ virgl_get_shader_param(struct pipe_screen *screen, > case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: > return 4096 * sizeof(float[4]); > case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: > - if (shader == PIPE_SHADER_FRAGMENT) > + if (shader == PIPE_SHADER_FRAGMENT || shader == PIPE_SHADER_COMPUTE) > return vscreen->caps.caps.v2.max_shader_buffer_frag_compute; > else > return vscreen->caps.caps.v2.max_shader_buffer_other_stages; > case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: > - if (shader == PIPE_SHADER_FRAGMENT) > + if (shader == PIPE_SHADER_FRAGMENT || shader == PIPE_SHADER_COMPUTE) > return vscreen->caps.caps.v2.max_shader_image_frag_compute; > else > return vscreen->caps.caps.v2.max_shader_image_other_stages; > + case PIPE_SHADER_CAP_SUPPORTED_IRS: > + return (1 << PIPE_SHADER_IR_TGSI); > case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: > case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: > case PIPE_SHADER_CAP_INT64_ATOMICS: > @@ -425,6 +432,51 @@ virgl_get_paramf(struct pipe_screen *screen, enum > pipe_capf param) > return 0.0; > } > > +static int > +virgl_get_compute_param(struct pipe_screen *screen, > + enum pipe_shader_ir ir_type, > + enum pipe_compute_cap param, > + void *ret) > +{ > + struct virgl_screen *vscreen = virgl_screen(screen); > + if (!(vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_COMPUTE_SHADER)) > + return 0; > + switch (param) { > + case PIPE_COMPUTE_CAP_MAX_GRID_SIZE: > + if (ret) { > + uint64_t *grid_size = ret; > + grid_size[0] = vscreen->caps.caps.v2.max_compute_grid_size[0]; > + grid_size[1] = vscreen->caps.caps.v2.max_compute_grid_size[1]; > + grid_size[2] = vscreen->caps.caps.v2.max_compute_grid_size[2]; > + } > + return 3 * sizeof(uint64_t) ; > + case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE: > + if (ret) { > + uint64_t *block_size = ret; > + block_size[0] = vscreen->caps.caps.v2.max_compute_block_size[0]; > + block_size[1] = vscreen->caps.caps.v2.max_compute_block_size[1]; > + block_size[2] = vscreen->caps.caps.v2.max_compute_block_size[2]; > + } > + return 3 * sizeof(uint64_t); > + case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK: > + if (ret) { > + uint64_t *max_threads_per_block = ret; > + *max_threads_per_block = > vscreen->caps.caps.v2.max_compute_work_group_invocations; > + } > + return sizeof(uint64_t); > + case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE: > + if (ret) { > + uint64_t *max_local_size = ret; > + /* Value reported by the closed source driver. */ > + *max_local_size = > vscreen->caps.caps.v2.max_compute_shared_memory_size; > + } > + return sizeof(uint64_t); > + default: > + break; > + } > + return 0; > +} > + > static boolean > virgl_is_vertex_format_supported(struct pipe_screen *screen, > enum pipe_format format) > @@ -661,6 +713,7 @@ virgl_create_screen(struct virgl_winsys *vws) > screen->base.get_vendor = virgl_get_vendor; > screen->base.get_param = virgl_get_param; > screen->base.get_shader_param = virgl_get_shader_param; > + screen->base.get_compute_param = virgl_get_compute_param; > screen->base.get_paramf = virgl_get_paramf; > screen->base.is_format_supported = virgl_is_format_supported; > screen->base.destroy = virgl_destroy_screen; > diff --git a/src/gallium/drivers/virgl/virgl_winsys.h > b/src/gallium/drivers/virgl/virgl_winsys.h > index 315ca55f954..0e6cb7953f6 100644 > --- a/src/gallium/drivers/virgl/virgl_winsys.h > +++ b/src/gallium/drivers/virgl/virgl_winsys.h > @@ -138,5 +138,7 @@ static inline void virgl_ws_fill_new_caps_defaults(struct > virgl_drm_caps *caps) > caps->caps.v2.capability_bits = 0; > caps->caps.v2.max_vertex_attrib_stride = 0; > caps->caps.v2.max_image_samples = 0; > + caps->caps.v2.max_compute_work_group_invocations = 0; > + caps->caps.v2.max_compute_shared_memory_size = 0; > } > #endif > -- > 2.14.3 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev