From: Dave Airlie Date: Fri, 15 Jun 2018 01:20:53 +0000 (+1000) Subject: virgl: add initial ARB_compute_shader support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f8a8ea6a2da89bb6f7d97f286a0cf1202fb95d8e;p=mesa.git virgl: add initial ARB_compute_shader support This hooks up compute shader creation and launch grid support. Reviewed-by: Gurchetan Singh --- 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 1947c6e4880..a2fa2a4dd26 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: @@ -328,6 +328,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: @@ -335,6 +339,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: @@ -373,15 +378,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: @@ -426,6 +433,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) @@ -666,6 +718,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