[Mesa-dev] [PATCH 13/18] gallium/u_simple_shaders: generate POSITION from VERTEXID if not present

Marek Olšák maraeo at gmail.com
Thu Aug 17 18:31:34 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/auxiliary/util/u_blitter.c        |  3 +-
 src/gallium/auxiliary/util/u_simple_shaders.c | 54 +++++++++++++++++++++++++--
 src/gallium/auxiliary/util/u_simple_shaders.h |  3 +-
 src/mesa/state_tracker/st_cb_clear.c          |  2 +-
 4 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 7a3eb63..54d3009 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -358,21 +358,22 @@ static void bind_vs_passthrough(struct blitter_context_priv *ctx)
    }
 
    pipe->bind_vs_state(pipe, ctx->vs);
 }
 
 static void bind_vs_layered(struct blitter_context_priv *ctx)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
    if (!ctx->vs_layered) {
-      ctx->vs_layered = util_make_layered_clear_vertex_shader(pipe);
+      ctx->vs_layered =
+         util_make_layered_clear_vertex_shader(pipe, true);
    }
 
    pipe->bind_vs_state(pipe, ctx->vs_layered);
 }
 
 static void bind_fs_empty(struct blitter_context_priv *ctx)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
    if (!ctx->fs_empty) {
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 9679545..763c634 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -72,65 +72,111 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
 void *
 util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
                                     uint num_attribs,
                                     const uint *semantic_names,
                                     const uint *semantic_indexes,
                                     bool window_space, bool layered,
 				    const struct pipe_stream_output_info *so)
 {
    struct ureg_program *ureg;
    uint i;
+   bool has_position = false;
 
    ureg = ureg_create( PIPE_SHADER_VERTEX );
    if (!ureg)
       return NULL;
 
    if (window_space)
       ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
 
    for (i = 0; i < num_attribs; i++) {
       struct ureg_src src;
       struct ureg_dst dst;
 
       src = ureg_DECL_vs_input( ureg, i );
       
       dst = ureg_DECL_output( ureg,
                               semantic_names[i],
                               semantic_indexes[i]);
       
       ureg_MOV( ureg, dst, src );
+
+      if (semantic_names[i] == TGSI_SEMANTIC_POSITION)
+         has_position = true;
    }
 
    if (layered) {
       struct ureg_src instance_id =
          ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0);
       struct ureg_dst layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0);
 
       ureg_MOV(ureg, ureg_writemask(layer, TGSI_WRITEMASK_X),
                ureg_scalar(instance_id, TGSI_SWIZZLE_X));
    }
 
+   /* If there is no position to pass from inputs, generate it from VertexID.
+    */
+   if (!has_position) {
+      struct ureg_src vertex_id =
+         ureg_DECL_system_value(ureg, TGSI_SEMANTIC_VERTEXID, 0);
+      struct ureg_dst temp = ureg_DECL_temporary(ureg);
+      struct ureg_dst pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+
+      vertex_id = ureg_scalar(vertex_id, TGSI_SWIZZLE_X);
+
+      /* We want:
+       *    VertexID posX posY
+       *     0        -1   -1
+       *     1         1   -1
+       *     2         1    1
+       *     3        -1    1
+       *
+       * posX = (VertexID >> 1) ^ (VertexID & 1) ? 1 : -1;
+       * posY = VertexID >> 1 ? 1 : -1;
+       * posZ = 0;
+       * posW = 1;
+       */
+      ureg_USHR(ureg, ureg_writemask(temp, TGSI_WRITEMASK_Y),
+                vertex_id, ureg_imm1u(ureg, 1));
+      ureg_AND(ureg, ureg_writemask(temp, TGSI_WRITEMASK_X),
+               vertex_id, ureg_imm1u(ureg, 1));
+      ureg_XOR(ureg, ureg_writemask(temp, TGSI_WRITEMASK_X),
+               ureg_scalar(ureg_src(temp), TGSI_SWIZZLE_X),
+               ureg_scalar(ureg_src(temp), TGSI_SWIZZLE_Y));
+
+      ureg_UCMP(ureg, ureg_writemask(pos, TGSI_WRITEMASK_XY),
+                ureg_swizzle(ureg_src(temp),
+                             TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,
+                             TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y),
+                ureg_imm1f(ureg, 1), ureg_imm1f(ureg, -1));
+      ureg_MOV(ureg, ureg_writemask(pos, TGSI_WRITEMASK_ZW),
+               ureg_imm4f(ureg, 0, 0, 0, 1));
+   }
+
    ureg_END( ureg );
 
    return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
 }
 
 
-void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
+void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe,
+                                            bool has_position_input)
 {
    const unsigned semantic_names[] = {TGSI_SEMANTIC_POSITION,
                                       TGSI_SEMANTIC_GENERIC};
    const unsigned semantic_indices[] = {0, 0};
+   unsigned offset = has_position_input ? 0 : 1;
 
-   return util_make_vertex_passthrough_shader_with_so(pipe, 2, semantic_names,
-                                                      semantic_indices, false,
-                                                      true, NULL);
+   return util_make_vertex_passthrough_shader_with_so(pipe, 2 - offset,
+                                                      semantic_names + offset,
+                                                      semantic_indices + offset,
+                                                      false, true, NULL);
 }
 
 /**
  * Takes position and color, and outputs position, color, and instance id.
  */
 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
 {
    static const char text[] =
          "VERT\n"
          "DCL IN[0]\n"
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index a281f57..bb2ad66 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -53,21 +53,22 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
 
 extern void *
 util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
                                     uint num_attribs,
                                     const uint *semantic_names,
                                     const uint *semantic_indexes,
                                     bool window_space, bool layered,
                                     const struct pipe_stream_output_info *so);
 
 extern void *
-util_make_layered_clear_vertex_shader(struct pipe_context *pipe);
+util_make_layered_clear_vertex_shader(struct pipe_context *pipe,
+                                      bool has_position_input);
 
 extern void *
 util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe);
 
 extern void *
 util_make_layered_clear_geometry_shader(struct pipe_context *pipe);
 
 extern void *
 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
                                         unsigned tex_target,
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index cda9c71..5afc876 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -148,21 +148,21 @@ set_vertex_shader_layered(struct st_context *st)
    if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID)) {
       assert(!"Got layered clear, but VS instancing is unsupported");
       set_vertex_shader(st);
       return;
    }
 
    if (!st->clear.vs_layered) {
       bool vs_layer =
          pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);
       if (vs_layer) {
-         st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe);
+         st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe, true);
       } else {
          st->clear.vs_layered = util_make_layered_clear_helper_vertex_shader(pipe);
          st->clear.gs_layered = util_make_layered_clear_geometry_shader(pipe);
       }
    }
 
    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
    cso_set_geometry_shader_handle(st->cso_context, st->clear.gs_layered);
 }
 
-- 
2.7.4



More information about the mesa-dev mailing list