Mesa (master): svga: add VS code to set attribute W component to 1

Brian Paul brianp at kemper.freedesktop.org
Thu Apr 17 18:36:19 UTC 2014


Module: Mesa
Branch: master
Commit: 851645a3e7f06348d60180ec122b9ad0dc3cf432
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=851645a3e7f06348d60180ec122b9ad0dc3cf432

Author: Brian Paul <brianp at vmware.com>
Date:   Thu Apr 17 09:00:29 2014 -0700

svga: add VS code to set attribute W component to 1

There's a few 3-component vertex attribute formats that have no
equivalent SVGA3D_DECLTYPE_x format.  Previously, we had to use
the swtnl code to handle them.  This patch lets us use hwtnl for
more vertex attribute types by fetching 3-component attributes as
4-component attributes and explicitly setting the W component to 1.

This lets us handle PIPE_FORMAT_R16G16B16_SNORM/UNORM and
PIPE_FORMAT_R8G8B8_UNORM vertex attribs without using the swtnl path.

Fixes piglit normal3b3s GL_SHORT test.

Reviewed-by: Charmaine Lee <charmainel at vmware.com>

---

 src/gallium/drivers/svga/svga_context.h     |    1 +
 src/gallium/drivers/svga/svga_pipe_vertex.c |   30 ++++++-
 src/gallium/drivers/svga/svga_state_vs.c    |    1 +
 src/gallium/drivers/svga/svga_tgsi.h        |    1 +
 src/gallium/drivers/svga/svga_tgsi_insn.c   |  113 ++++++++++++++++-----------
 5 files changed, 100 insertions(+), 46 deletions(-)

diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index 5564277..4ff0ed7 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -202,6 +202,7 @@ struct svga_velems_state {
    struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
    SVGA3dDeclType decl_type[PIPE_MAX_ATTRIBS]; /**< vertex attrib formats */
    unsigned adjust_attrib_range; /* bitmask of attrs needing range adjustment */
+   unsigned adjust_attrib_w_1;   /* bitmask of attrs needing w = 1 */
 };
 
 /* Use to calculate differences between state emitted to hardware and
diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c
index d679ad3..f951c0d 100644
--- a/src/gallium/drivers/svga/svga_pipe_vertex.c
+++ b/src/gallium/drivers/svga/svga_pipe_vertex.c
@@ -94,9 +94,14 @@ translate_vertex_format(enum pipe_format format)
    case PIPE_FORMAT_R16G16_FLOAT:         return SVGA3D_DECLTYPE_FLOAT16_2;
    case PIPE_FORMAT_R16G16B16A16_FLOAT:   return SVGA3D_DECLTYPE_FLOAT16_4;
 
-   /* See attrib_needs_adjustment() below */
+   /* See attrib_needs_adjustment() and attrib_needs_w_to_1() below */
    case PIPE_FORMAT_R8G8B8_SNORM:         return SVGA3D_DECLTYPE_UBYTE4N;
 
+   /* See attrib_needs_w_to_1() below */
+   case PIPE_FORMAT_R16G16B16_SNORM:      return SVGA3D_DECLTYPE_SHORT4N;
+   case PIPE_FORMAT_R16G16B16_UNORM:      return SVGA3D_DECLTYPE_USHORT4N;
+   case PIPE_FORMAT_R8G8B8_UNORM:         return SVGA3D_DECLTYPE_UBYTE4N;
+
    default:
       /* There are many formats without hardware support.  This case
        * will be hit regularly, meaning we'll need swvfetch.
@@ -123,6 +128,25 @@ attrib_needs_range_adjustment(enum pipe_format format)
 }
 
 
+/**
+ * Does the given vertex attrib format need to have the W component set
+ * to one in the VS?
+ */
+static boolean
+attrib_needs_w_to_1(enum pipe_format format)
+{
+   switch (format) {
+   case PIPE_FORMAT_R8G8B8_SNORM:
+   case PIPE_FORMAT_R8G8B8_UNORM:
+   case PIPE_FORMAT_R16G16B16_SNORM:
+   case PIPE_FORMAT_R16G16B16_UNORM:
+      return TRUE;
+   default:
+      return FALSE;
+   }
+}
+
+
 static void *
 svga_create_vertex_elements_state(struct pipe_context *pipe,
                                   unsigned count,
@@ -138,6 +162,7 @@ svga_create_vertex_elements_state(struct pipe_context *pipe,
       memcpy(velems->velem, attribs, sizeof(*attribs) * count);
 
       velems->adjust_attrib_range = 0x0;
+      velems->adjust_attrib_w_1 = 0x0;
 
       /* Translate Gallium vertex format to SVGA3dDeclType */
       for (i = 0; i < count; i++) {
@@ -147,6 +172,9 @@ svga_create_vertex_elements_state(struct pipe_context *pipe,
          if (attrib_needs_range_adjustment(f)) {
             velems->adjust_attrib_range |= (1 << i);
          }
+         if (attrib_needs_w_to_1(f)) {
+            velems->adjust_attrib_w_1 |= (1 << i);
+         }
       }
    }
    return velems;
diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c
index 2ea2549..64dd7c9 100644
--- a/src/gallium/drivers/svga/svga_state_vs.c
+++ b/src/gallium/drivers/svga/svga_state_vs.c
@@ -162,6 +162,7 @@ make_vs_key(struct svga_context *svga, struct svga_vs_compile_key *key)
 
    /* SVGA_NEW_VELEMENT */
    key->adjust_attrib_range = svga->curr.velems->adjust_attrib_range;
+   key->adjust_attrib_w_1 = svga->curr.velems->adjust_attrib_w_1;
 }
 
 
diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h
index cb40560..e7a2a13 100644
--- a/src/gallium/drivers/svga/svga_tgsi.h
+++ b/src/gallium/drivers/svga/svga_tgsi.h
@@ -50,6 +50,7 @@ struct svga_vs_compile_key
    unsigned need_prescale:1;
    unsigned allow_psiz:1;
    unsigned adjust_attrib_range:16;
+   unsigned adjust_attrib_w_1:16;
 };
 
 struct svga_fs_compile_key
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index e798b17..a44ef3a 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -3532,57 +3532,78 @@ emit_inverted_texcoords(struct svga_shader_emitter *emit)
 static boolean
 emit_adjusted_vertex_attribs(struct svga_shader_emitter *emit)
 {
-   unsigned adjust_attrib_range = emit->key.vkey.adjust_attrib_range;
-
-   while (adjust_attrib_range) {
-      /* The vertex input/attribute is supposed to be a signed value in
-       * the range [-1,1] but we actually fetched/converted it to the
-       * range [0,1].  This most likely happens when the app specifies a
-       * signed byte attribute but we interpreted it as unsigned bytes.
-       * See also svga_translate_vertex_format().
-       *
-       * Here, we emit some extra instructions to adjust
-       * the attribute values from [0,1] to [-1,1].
-       *
-       * The adjustment we implement is:
-       *   new_attrib = attrib * 2.0;
-       *   if (attrib >= 0.5)
-       *      new_attrib = new_attrib - 2.0;
-       * This isn't exactly right (it's off by a bit or so) but close enough.
-       */
-      const unsigned index = u_bit_scan(&adjust_attrib_range);
+   unsigned adjust_mask = (emit->key.vkey.adjust_attrib_range |
+                           emit->key.vkey.adjust_attrib_w_1);
+ 
+   while (adjust_mask) {
+      /* Adjust vertex attrib range and/or set W component = 1 */
+      const unsigned index = u_bit_scan(&adjust_mask);
       struct src_register tmp;
 
-      SVGA3dShaderDestToken pred_reg = dst_register(SVGA3DREG_PREDICATE, 0);
-
       /* allocate a temp reg */
       tmp = src_register(SVGA3DREG_TEMP, emit->nr_hw_temp);
       emit->nr_hw_temp++;
 
-      /* tmp = attrib * 2.0 */
-      if (!submit_op2(emit,
-                      inst_token(SVGA3DOP_MUL),
-                      dst(tmp),
-                      emit->input_map[index],
-                      get_two_immediate(emit)))
-         return FALSE;
+      if (emit->key.vkey.adjust_attrib_range & (1 << index)) {
+         /* The vertex input/attribute is supposed to be a signed value in
+          * the range [-1,1] but we actually fetched/converted it to the
+          * range [0,1].  This most likely happens when the app specifies a
+          * signed byte attribute but we interpreted it as unsigned bytes.
+          * See also svga_translate_vertex_format().
+          *
+          * Here, we emit some extra instructions to adjust
+          * the attribute values from [0,1] to [-1,1].
+          *
+          * The adjustment we implement is:
+          *   new_attrib = attrib * 2.0;
+          *   if (attrib >= 0.5)
+          *      new_attrib = new_attrib - 2.0;
+          * This isn't exactly right (it's off by a bit or so) but close enough.
+          */
+         SVGA3dShaderDestToken pred_reg = dst_register(SVGA3DREG_PREDICATE, 0);
+
+         /* tmp = attrib * 2.0 */
+         if (!submit_op2(emit,
+                         inst_token(SVGA3DOP_MUL),
+                         dst(tmp),
+                         emit->input_map[index],
+                         get_two_immediate(emit)))
+            return FALSE;
 
-      /* pred = (attrib >= 0.5) */
-      if (!submit_op2(emit,
-                      inst_token_setp(SVGA3DOPCOMP_GE),
-                      pred_reg,
-                      emit->input_map[index],  /* vert attrib */
-                      get_half_immediate(emit)))  /* 0.5 */
-         return FALSE;
+         /* pred = (attrib >= 0.5) */
+         if (!submit_op2(emit,
+                         inst_token_setp(SVGA3DOPCOMP_GE),
+                         pred_reg,
+                         emit->input_map[index],  /* vert attrib */
+                         get_half_immediate(emit)))  /* 0.5 */
+            return FALSE;
 
-      /* sub(pred) tmp, tmp, 2.0 */
-      if (!submit_op3(emit,
-                      inst_token_predicated(SVGA3DOP_SUB),
-                      dst(tmp),
-                      src(pred_reg),
-                      tmp,
-                      get_two_immediate(emit)))
-         return FALSE;
+         /* sub(pred) tmp, tmp, 2.0 */
+         if (!submit_op3(emit,
+                         inst_token_predicated(SVGA3DOP_SUB),
+                         dst(tmp),
+                         src(pred_reg),
+                         tmp,
+                         get_two_immediate(emit)))
+            return FALSE;
+      }
+      else {
+         /* just copy the vertex input attrib to the temp register */
+         if (!submit_op1(emit,
+                         inst_token(SVGA3DOP_MOV),
+                         dst(tmp),
+                         emit->input_map[index]))
+            return FALSE;
+      }
+
+      if (emit->key.vkey.adjust_attrib_w_1 & (1 << index)) {
+         /* move 1 into W position of tmp */
+         if (!submit_op1(emit,
+                         inst_token(SVGA3DOP_MOV),
+                         writemask(dst(tmp), TGSI_WRITEMASK_W),
+                         get_one_immediate(emit)))
+            return FALSE;
+      }
 
       /* Reassign the input_map entry to the new tmp register */
       emit->input_map[index] = tmp;
@@ -3640,7 +3661,8 @@ needs_to_create_common_immediate(const struct svga_shader_emitter *emit)
    else if (emit->unit == PIPE_SHADER_VERTEX) {
       if (emit->info.opcode_count[TGSI_OPCODE_CMP] >= 1)
          return TRUE;
-      if (emit->key.vkey.adjust_attrib_range)
+      if (emit->key.vkey.adjust_attrib_range ||
+          emit->key.vkey.adjust_attrib_w_1)
          return TRUE;
    }
 
@@ -3803,7 +3825,8 @@ svga_shader_emit_helpers(struct svga_shader_emitter *emit)
    }
    else {
       assert(emit->unit == PIPE_SHADER_VERTEX);
-      if (emit->key.vkey.adjust_attrib_range) {
+      if (emit->key.vkey.adjust_attrib_range ||
+          emit->key.vkey.adjust_attrib_w_1) {
          if (!emit_adjusted_vertex_attribs(emit))
             return FALSE;
       }




More information about the mesa-commit mailing list