From 7b6f2704eb7333689531cc1572648a31319cb5ac Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 8 Jun 2018 14:38:14 +1000 Subject: [PATCH] virgl: add ARB_tessellation_shader support. (v2) This should add all the pieces to enable tess shaders on virgl. v2: fixup transform to handle tess and strip out precise. set default for max patch varyings to work around issue when tess gets enabled from v1 caps but v2 caps aren't in place. (Elie) Reviewed-by: Elie Tournier --- src/gallium/auxiliary/tgsi/tgsi_transform.c | 4 -- src/gallium/drivers/virgl/virgl_context.c | 69 +++++++++++++++++++++ src/gallium/drivers/virgl/virgl_encode.c | 21 ++++++- src/gallium/drivers/virgl/virgl_encode.h | 4 ++ src/gallium/drivers/virgl/virgl_protocol.h | 5 ++ src/gallium/drivers/virgl/virgl_screen.c | 10 ++- src/gallium/drivers/virgl/virgl_winsys.h | 2 +- 7 files changed, 107 insertions(+), 8 deletions(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.c b/src/gallium/auxiliary/tgsi/tgsi_transform.c index cd076c9e79e..4b2b10f50ad 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_transform.c +++ b/src/gallium/auxiliary/tgsi/tgsi_transform.c @@ -140,10 +140,6 @@ tgsi_transform_shader(const struct tgsi_token *tokens_in, return -1; } procType = parse.FullHeader.Processor.Processor; - assert(procType == PIPE_SHADER_FRAGMENT || - procType == PIPE_SHADER_VERTEX || - procType == PIPE_SHADER_GEOMETRY); - /** ** Setup output shader diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index 8d701bb8f40..e6f8dc85256 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -492,6 +492,18 @@ static void *virgl_create_vs_state(struct pipe_context *ctx, return virgl_shader_encoder(ctx, shader, PIPE_SHADER_VERTEX); } +static void *virgl_create_tcs_state(struct pipe_context *ctx, + const struct pipe_shader_state *shader) +{ + return virgl_shader_encoder(ctx, shader, PIPE_SHADER_TESS_CTRL); +} + +static void *virgl_create_tes_state(struct pipe_context *ctx, + const struct pipe_shader_state *shader) +{ + return virgl_shader_encoder(ctx, shader, PIPE_SHADER_TESS_EVAL); +} + static void *virgl_create_gs_state(struct pipe_context *ctx, const struct pipe_shader_state *shader) { @@ -534,6 +546,26 @@ virgl_delete_vs_state(struct pipe_context *ctx, virgl_encode_delete_object(vctx, handle, VIRGL_OBJECT_SHADER); } +static void +virgl_delete_tcs_state(struct pipe_context *ctx, + void *tcs) +{ + uint32_t handle = (unsigned long)tcs; + struct virgl_context *vctx = virgl_context(ctx); + + virgl_encode_delete_object(vctx, handle, VIRGL_OBJECT_SHADER); +} + +static void +virgl_delete_tes_state(struct pipe_context *ctx, + void *tes) +{ + uint32_t handle = (unsigned long)tes; + struct virgl_context *vctx = virgl_context(ctx); + + virgl_encode_delete_object(vctx, handle, VIRGL_OBJECT_SHADER); +} + static void virgl_bind_vs_state(struct pipe_context *ctx, void *vss) { @@ -543,6 +575,24 @@ static void virgl_bind_vs_state(struct pipe_context *ctx, virgl_encode_bind_shader(vctx, handle, PIPE_SHADER_VERTEX); } +static void virgl_bind_tcs_state(struct pipe_context *ctx, + void *vss) +{ + uint32_t handle = (unsigned long)vss; + struct virgl_context *vctx = virgl_context(ctx); + + virgl_encode_bind_shader(vctx, handle, PIPE_SHADER_TESS_CTRL); +} + +static void virgl_bind_tes_state(struct pipe_context *ctx, + void *vss) +{ + uint32_t handle = (unsigned long)vss; + struct virgl_context *vctx = virgl_context(ctx); + + virgl_encode_bind_shader(vctx, handle, PIPE_SHADER_TESS_EVAL); +} + static void virgl_bind_gs_state(struct pipe_context *ctx, void *vss) { @@ -801,6 +851,18 @@ static void virgl_set_clip_state(struct pipe_context *ctx, virgl_encoder_set_clip_state(vctx, clip); } +static void virgl_set_tess_state(struct pipe_context *ctx, + const float default_outer_level[4], + const float default_inner_level[2]) +{ + struct virgl_context *vctx = virgl_context(ctx); + struct virgl_screen *rs = virgl_screen(ctx->screen); + + if (!rs->caps.caps.v1.bset.has_tessellation_shaders) + return; + virgl_encode_set_tess_state(vctx, default_outer_level, default_inner_level); +} + static void virgl_resource_copy_region(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dst_level, @@ -893,15 +955,22 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen, vctx->base.set_vertex_buffers = virgl_set_vertex_buffers; vctx->base.set_constant_buffer = virgl_set_constant_buffer; + vctx->base.set_tess_state = virgl_set_tess_state; vctx->base.create_vs_state = virgl_create_vs_state; + vctx->base.create_tcs_state = virgl_create_tcs_state; + vctx->base.create_tes_state = virgl_create_tes_state; vctx->base.create_gs_state = virgl_create_gs_state; vctx->base.create_fs_state = virgl_create_fs_state; vctx->base.bind_vs_state = virgl_bind_vs_state; + vctx->base.bind_tcs_state = virgl_bind_tcs_state; + vctx->base.bind_tes_state = virgl_bind_tes_state; vctx->base.bind_gs_state = virgl_bind_gs_state; vctx->base.bind_fs_state = virgl_bind_fs_state; vctx->base.delete_vs_state = virgl_delete_vs_state; + vctx->base.delete_tcs_state = virgl_delete_tcs_state; + vctx->base.delete_tes_state = virgl_delete_tes_state; vctx->base.delete_gs_state = virgl_delete_gs_state; vctx->base.delete_fs_state = virgl_delete_fs_state; diff --git a/src/gallium/drivers/virgl/virgl_encode.c b/src/gallium/drivers/virgl/virgl_encode.c index f3cbd1ca4b0..ad018bd1964 100644 --- a/src/gallium/drivers/virgl/virgl_encode.c +++ b/src/gallium/drivers/virgl/virgl_encode.c @@ -419,6 +419,8 @@ int virgl_encoder_draw_vbo(struct virgl_context *ctx, const struct pipe_draw_info *info) { uint32_t length = VIRGL_DRAW_VBO_SIZE; + if (info->mode == PIPE_PRIM_PATCHES) + length = VIRGL_DRAW_VBO_SIZE_TESS; if (info->indirect) length = VIRGL_DRAW_VBO_SIZE_INDIRECT; virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_DRAW_VBO, 0, length)); @@ -437,9 +439,11 @@ int virgl_encoder_draw_vbo(struct virgl_context *ctx, virgl_encoder_write_dword(ctx->cbuf, info->count_from_stream_output->buffer_size); else virgl_encoder_write_dword(ctx->cbuf, 0); + if (length >= VIRGL_DRAW_VBO_SIZE_TESS) { + virgl_encoder_write_dword(ctx->cbuf, info->vertices_per_patch); /* vertices per patch */ + virgl_encoder_write_dword(ctx->cbuf, info->drawid); /* drawid */ + } if (length == VIRGL_DRAW_VBO_SIZE_INDIRECT) { - virgl_encoder_write_dword(ctx->cbuf, 0); /* vertices per patch */ - virgl_encoder_write_dword(ctx->cbuf, 0); /* drawid */ virgl_encoder_write_res(ctx, virgl_resource(info->indirect->buffer)); virgl_encoder_write_dword(ctx->cbuf, info->indirect->offset); virgl_encoder_write_dword(ctx->cbuf, 0); /* indirect stride */ @@ -891,3 +895,16 @@ int virgl_encode_bind_shader(struct virgl_context *ctx, virgl_encoder_write_dword(ctx->cbuf, type); return 0; } + +int virgl_encode_set_tess_state(struct virgl_context *ctx, + const float outer[4], + const float inner[2]) +{ + int i; + virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_SET_TESS_STATE, 0, 6)); + for (i = 0; i < 4; i++) + virgl_encoder_write_dword(ctx->cbuf, fui(outer[i])); + for (i = 0; i < 2; i++) + virgl_encoder_write_dword(ctx->cbuf, fui(inner[i])); + return 0; +} diff --git a/src/gallium/drivers/virgl/virgl_encode.h b/src/gallium/drivers/virgl/virgl_encode.h index 02c032d673e..837075ea483 100644 --- a/src/gallium/drivers/virgl/virgl_encode.h +++ b/src/gallium/drivers/virgl/virgl_encode.h @@ -251,4 +251,8 @@ int virgl_encoder_destroy_sub_ctx(struct virgl_context *ctx, uint32_t sub_ctx_id int virgl_encode_bind_shader(struct virgl_context *ctx, uint32_t handle, uint32_t type); + +int virgl_encode_set_tess_state(struct virgl_context *ctx, + const float outer[4], + const float inner[2]); #endif diff --git a/src/gallium/drivers/virgl/virgl_protocol.h b/src/gallium/drivers/virgl/virgl_protocol.h index 5dc2874d1dd..bd5a8b40434 100644 --- a/src/gallium/drivers/virgl/virgl_protocol.h +++ b/src/gallium/drivers/virgl/virgl_protocol.h @@ -83,6 +83,8 @@ enum virgl_context_cmd { VIRGL_CCMD_CREATE_SUB_CTX, VIRGL_CCMD_DESTROY_SUB_CTX, VIRGL_CCMD_BIND_SHADER, + + VIRGL_CCMD_SET_TESS_STATE, }; /* @@ -481,4 +483,7 @@ enum virgl_context_cmd { #define VIRGL_BIND_SHADER_HANDLE 1 #define VIRGL_BIND_SHADER_TYPE 2 +/* tess state */ +#define VIRGL_TESS_STATE_SIZE 6 + #endif diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c index 2ba9708ebac..f21526a60bd 100644 --- a/src/gallium/drivers/virgl/virgl_screen.c +++ b/src/gallium/drivers/virgl/virgl_screen.c @@ -215,6 +215,8 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param) return vscreen->caps.caps.v2.shader_buffer_offset_alignment; case PIPE_CAP_DOUBLES: return vscreen->caps.caps.v1.bset.has_fp64; + case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: + return vscreen->caps.caps.v2.max_shader_patch_varyings; case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_FAKE_SW_MSAA: @@ -229,7 +231,6 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: - case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: case PIPE_CAP_TEXTURE_FLOAT_LINEAR: case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: case PIPE_CAP_DEPTH_BOUNDS_TEST: @@ -316,11 +317,18 @@ virgl_get_shader_param(struct pipe_screen *screen, enum pipe_shader_cap param) { struct virgl_screen *vscreen = virgl_screen(screen); + + if ((shader == PIPE_SHADER_TESS_CTRL || shader == PIPE_SHADER_TESS_EVAL) && + !vscreen->caps.caps.v1.bset.has_tessellation_shaders) + return 0; + switch(shader) { case PIPE_SHADER_FRAGMENT: case PIPE_SHADER_VERTEX: case PIPE_SHADER_GEOMETRY: + case PIPE_SHADER_TESS_CTRL: + case PIPE_SHADER_TESS_EVAL: switch (param) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: diff --git a/src/gallium/drivers/virgl/virgl_winsys.h b/src/gallium/drivers/virgl/virgl_winsys.h index 9ebb31a1e41..99ab4d38405 100644 --- a/src/gallium/drivers/virgl/virgl_winsys.h +++ b/src/gallium/drivers/virgl/virgl_winsys.h @@ -127,7 +127,7 @@ static inline void virgl_ws_fill_new_caps_defaults(struct virgl_drm_caps *caps) caps->caps.v2.max_geom_total_output_components = 1024; caps->caps.v2.max_vertex_outputs = 32; caps->caps.v2.max_vertex_attribs = 16; - caps->caps.v2.max_shader_patch_varyings = 0; + caps->caps.v2.max_shader_patch_varyings = 30; caps->caps.v2.min_texel_offset = -8; caps->caps.v2.max_texel_offset = 7; caps->caps.v2.min_texture_gather_offset = -8; -- 2.30.2