virgl: add ARB_tessellation_shader support. (v2)
authorDave Airlie <airlied@redhat.com>
Fri, 8 Jun 2018 04:38:14 +0000 (14:38 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 14 Jun 2018 00:36:31 +0000 (10:36 +1000)
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 <elie.tournier@collabora.com>
src/gallium/auxiliary/tgsi/tgsi_transform.c
src/gallium/drivers/virgl/virgl_context.c
src/gallium/drivers/virgl/virgl_encode.c
src/gallium/drivers/virgl/virgl_encode.h
src/gallium/drivers/virgl/virgl_protocol.h
src/gallium/drivers/virgl/virgl_screen.c
src/gallium/drivers/virgl/virgl_winsys.h

index cd076c9e79e8f09d84559ead1fe0d6cc28eff735..4b2b10f50ad25d8ca73df5579cc7b9b747fb9d1a 100644 (file)
@@ -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
index 8d701bb8f409755b8355a7b743a73f80309b66e3..e6f8dc852566848229f633572c32c9f72cd4b8bd 100644 (file)
@@ -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;
 
index f3cbd1ca4b0123c9e7ab0e7fe7b884b27402ca55..ad018bd1964d38b74a965f8257dfe16a3ccd4583 100644 (file)
@@ -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;
+}
index 02c032d673e671f8e27b70d7813a4e8b5917a663..837075ea483634f7a3195cd13da263307a28146c 100644 (file)
@@ -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
index 5dc2874d1dd51c190dd16027c5a95403b4ab2efc..bd5a8b40434f331dc15728306f79826df6b50469 100644 (file)
@@ -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
index 2ba9708ebac3b6f9af2e6ad46cefbd283a89993d..f21526a60bd2cc77555eada3bad7f15e135c9d02 100644 (file)
@@ -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:
index 9ebb31a1e41452b9060b22a158729bd20fff9427..99ab4d3840519221125b02953e44f402aa1ad353 100644 (file)
@@ -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;