Mesa (master): gallium: first steps to treat edgeflags as regular vertex element

Roland Scheidegger sroland at kemper.freedesktop.org
Tue Dec 22 12:48:48 PST 2009


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

Author: Keith Whitwell <keithw at vmware.com>
Date:   Wed Dec  9 19:03:10 2009 +0100

gallium: first steps to treat edgeflags as regular vertex element

The idea here is to eliminate the set_edgeflags() call in pipe_context
by treating edgeflags as a regular vertex element.

Edgeflags provoke special treatment in hardware, which means we need to
label them in some way, in this case we'll be passing them through the
vertex shader and labelling the vertex shader output with a new TGSI
semantic (TGSI_SEMANTIC_EDGEFLAG).

---

 src/gallium/auxiliary/draw/draw_context.c          |    7 --
 src/gallium/auxiliary/draw/draw_context.h          |    3 -
 src/gallium/auxiliary/draw/draw_private.h          |    2 -
 src/gallium/auxiliary/draw/draw_pt.c               |    4 +-
 src/gallium/auxiliary/draw/draw_pt.h               |    5 --
 src/gallium/auxiliary/draw/draw_pt_fetch.c         |   32 ++++------
 .../auxiliary/draw/draw_pt_fetch_shade_pipeline.c  |    3 +-
 src/gallium/auxiliary/draw/draw_pt_post_vs.c       |   53 ++++++++++++++--
 src/gallium/include/pipe/p_context.h               |    8 ---
 src/gallium/include/pipe/p_shader_tokens.h         |    3 +-
 src/mesa/state_tracker/st_atom_shader.c            |   11 +++-
 src/mesa/state_tracker/st_draw.c                   |   64 --------------------
 src/mesa/state_tracker/st_mesa_to_tgsi.c           |   13 +---
 src/mesa/state_tracker/st_program.c                |   32 ++++++++++-
 src/mesa/state_tracker/st_program.h                |    2 +-
 15 files changed, 111 insertions(+), 131 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index a4f1fcd..cc5f7f0 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -366,13 +366,6 @@ void draw_set_render( struct draw_context *draw,
    draw->render = render;
 }
 
-void draw_set_edgeflags( struct draw_context *draw,
-                         const unsigned *edgeflag )
-{
-   draw->pt.user.edgeflag = edgeflag;
-}
-
-
 
 
 /**
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index d529e4e..465b8f1 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -143,9 +143,6 @@ void draw_set_mapped_constant_buffer(struct draw_context *draw,
                                      const void *buffer,
                                      unsigned size );
 
-void draw_set_edgeflags( struct draw_context *draw,
-                         const unsigned *edgeflag );
-
 
 /***********************************************************************
  * draw_prim.c 
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 41fcb16..0750e6e 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -142,8 +142,6 @@ struct draw_context
 
       /* user-space vertex data, buffers */
       struct {
-         const unsigned *edgeflag;
-
          /** vertex element/index buffer (ex: glDrawElements) */
          const void *elts;
          /** bytes per index (0, 1, 2 or 4) */
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 4865a2d..139ae1f 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -318,8 +318,10 @@ draw_arrays(struct draw_context *draw, unsigned prim,
 boolean draw_pt_get_edgeflag( struct draw_context *draw,
                               unsigned idx )
 {
-   if (draw->pt.user.edgeflag)
+   if (draw->pt.user.edgeflag) {
+      float *ef = draw->pt.verted_buffer[idx]
       return (draw->pt.user.edgeflag[idx/32] & (1 << (idx%32))) != 0;
+   }
    else
       return 1;
 }
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 7a17a9f..b5c8c82 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -149,11 +149,6 @@ struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw );
 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
 
 
-/* More helpers:
- */
-boolean draw_pt_get_edgeflag( struct draw_context *draw,
-                              unsigned idx );
-
 
 /*******************************************************************************
  * HW vertex emit:
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index 65c3a34..cb609f8 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -120,7 +120,12 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       fetch->translate = translate_cache_find(fetch->cache, &key);
 
       {
-         static struct vertex_header vh = { 0, 1, 0, UNDEFINED_VERTEX_ID, { .0f, .0f, .0f, .0f } };
+         static struct vertex_header vh = { 0,
+                                            1,
+                                            0,
+                                            UNDEFINED_VERTEX_ID,
+                                            { .0f, .0f, .0f, .0f } };
+
 	 fetch->translate->set_buffer(fetch->translate,
 				      draw->pt.nr_vertex_buffers,
 				      &vh,
@@ -128,9 +133,6 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       }
    }
 
-   fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
-                             draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
-                            draw->pt.user.edgeflag);
 }
 
 
@@ -158,16 +160,10 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
 			count,
 			verts );
 
-   /* Edgeflags are hard to fit into a translate program, populate
-    * them separately if required.  In the setup above they are
-    * defaulted to one, so only need this if there is reason to change
-    * that default:
+   /* Extract edgeflag values from vertex data into the header.
     */
    if (fetch->need_edgeflags) {
-      for (i = 0; i < count; i++) {
-         struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
-         vh->edgeflag = draw_pt_get_edgeflag( draw, elts[i] );
-      }
+      extract_edge_flags( fetch, count );
    }
 }
 
@@ -194,16 +190,12 @@ void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
                    count,
                    verts );
 
-   /* Edgeflags are hard to fit into a translate program, populate
-    * them separately if required.  In the setup above they are
-    * defaulted to one, so only need this if there is reason to change
-    * that default:
+   /* Extract edgeflag values from vertex data into the header.  XXX:
+    * this should be done after the vertex shader is run.
+    * Bypass-vs-and-clip interaction with pipeline???
     */
    if (fetch->need_edgeflags) {
-      for (i = 0; i < count; i++) {
-         struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
-         vh->edgeflag = draw_pt_get_edgeflag( draw, start + i );
-      }
+      extract_edge_flags( fetch, count );
    }
 }
 
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index df6c265..d414368 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -86,7 +86,8 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
 			    (boolean)draw->bypass_clipping,
 			    (boolean)(draw->identity_viewport ||
                                       draw->rasterizer->bypass_vs_clip_and_viewport),
-			    (boolean)draw->rasterizer->gl_rasterization_rules );
+			    (boolean)draw->rasterizer->gl_rasterization_rules,
+                            need_edgeflags );
 			    
 
    if (!(opt & PT_PIPELINE)) {
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
index 6c1cb48..0745b16 100644
--- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -147,6 +147,34 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
 
 
 
+/* As above plus edgeflags
+ */
+static boolean 
+post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
+                                      struct vertex_header *vertices,
+                                      unsigned count,
+                                      unsigned stride )
+{
+   if (!post_vs_cliptest_viewport_gl( pvs, vertices, count, stride))
+      return FALSE;
+
+   /* If present, copy edgeflag VS output into vertex header.
+    * Otherwise, leave header as is.
+    */
+   if (pvs->draw->vs.edgeflag_output) {
+      struct vertex_header *out = vertices;
+      int ef = pvs->draw->vs.edgeflag_output;
+
+      for (j = 0; j < count; j++) {
+         const float *edgeflag = out->data[ef];
+         out->edgeflag = (edgeflag[0] != 1.0f);
+      }
+   }
+}
+
+
+
+
 /* If bypass_clipping is set, skip cliptest and rhw divide.
  */
 static boolean post_vs_viewport( struct pt_post_vs *pvs,
@@ -203,15 +231,26 @@ void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
 			      boolean bypass_viewport,
 			      boolean opengl )
 {
-   if (bypass_clipping) {
-      if (bypass_viewport)
-	 pvs->run = post_vs_none;
-      else
-	 pvs->run = post_vs_viewport;
+   if (!need_edgeflags) {
+      if (bypass_clipping) {
+         if (bypass_viewport)
+            pvs->run = post_vs_none;
+         else
+            pvs->run = post_vs_viewport;
+      }
+      else {
+         /* if (opengl) */
+         pvs->run = post_vs_cliptest_viewport_gl;
+      }
    }
    else {
-      /* if (opengl) */
-      pvs->run = post_vs_cliptest_viewport_gl;
+      /* If we need to copy edgeflags to the vertex header, it should
+       * mean we're running the primitive pipeline.  Hence the bypass
+       * flags should be false.
+       */
+      assert(!bypass_clipping);
+      assert(!bypass_viewport);
+      pvs->run = post_vs_cliptest_viewport_gl_edgeflag;
    }
 }
 
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index f896001..11bcdc0 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -57,14 +57,6 @@ struct pipe_context {
 
    void (*destroy)( struct pipe_context * );
 
-   
-   /* Possible interface for setting edgeflags.  These aren't really
-    * vertex elements, so don't fit there.
-    */
-   void (*set_edgeflags)( struct pipe_context *,
-                          const unsigned *bitfield );
-
-
    /**
     * VBO drawing (return false on fallbacks (temporary??))
     */
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 588ca5e..c051d4d 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -127,7 +127,8 @@ struct tgsi_declaration_range
 #define TGSI_SEMANTIC_GENERIC  5
 #define TGSI_SEMANTIC_NORMAL   6
 #define TGSI_SEMANTIC_FACE     7
-#define TGSI_SEMANTIC_COUNT    8 /**< number of semantic values */
+#define TGSI_SEMANTIC_EDGEFLAG 8
+#define TGSI_SEMANTIC_COUNT    9 /**< number of semantic values */
 
 struct tgsi_declaration_semantic
 {
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 09baff8..e209634 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -106,7 +106,16 @@ find_translated_vp(struct st_context *st,
    /* Nothing in our key yet.  This will change:
     */
    memset(&key, 0, sizeof key);
-   key.dummy = 0;
+
+   /* When this is true, we will add an extra input to the vertex
+    * shader translation (for edgeflags), an extra output with
+    * edgeflag semantics, and extend the vertex shader to pass through
+    * the input to the output.  We'll need to use similar logic to set
+    * up the extra vertex_element input for edgeflags.
+    */
+   key.passthrough_edgeflags = (ctx->Polygon.FrontMode != GL_FILL ||
+                                ctx->Polygon.BackMode != GL_FILL);
+      
 
    /* Do we need to throw away old translations after a change in the
     * GL program string?
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index e13ae57..773a3f1 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -217,59 +217,7 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
 }
 
 
-/*
- * If edge flags are needed, setup an bitvector of flags and call
- * pipe->set_edgeflags().
- * XXX memleak: need to free the returned pointer at some point
- */
-static void *
-setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
-                const struct gl_client_array *array)
-{
-   struct pipe_context *pipe = ctx->st->pipe;
-
-   if ((primMode == GL_TRIANGLES ||
-        primMode == GL_QUADS ||
-        primMode == GL_POLYGON) &&
-       (ctx->Polygon.FrontMode != GL_FILL ||
-        ctx->Polygon.BackMode != GL_FILL)) {
-      /* need edge flags */
-      GLint i;
-      unsigned *vec;
-      struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
-      ubyte *map;
-
-      if (!stobj || stobj->Base.Name == 0) {
-         /* edge flags are not in a VBO */
-         return NULL;
-      }
-
-      vec = (unsigned *) _mesa_calloc(sizeof(unsigned) * ((count + 31) / 32));
-      if (!vec)
-         return NULL;
-
-      map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
-      map = ADD_POINTERS(map, array->Ptr);
 
-      for (i = 0; i < count; i++) {
-         if (*((float *) map))
-            vec[i/32] |= 1 << (i % 32);
-
-         map += array->StrideB;
-      }
-
-      pipe_buffer_unmap(pipe->screen, stobj->buffer);
-
-      pipe->set_edgeflags(pipe, vec);
-
-      return vec;
-   }
-   else {
-      /* edge flags not needed */
-      pipe->set_edgeflags(pipe, NULL);
-      return NULL;
-   }
-}
 
 
 /**
@@ -671,10 +619,6 @@ st_draw_vbo(GLcontext *ctx,
           * through to driver & draw module.  These interfaces still
           * need a bit of work...
           */
-         setup_edgeflags(ctx, prims[i].mode,
-                         prims[i].start + indexOffset, prims[i].count,
-                         arrays[VERT_ATTRIB_EDGEFLAG]);
-
          pipe->draw_range_elements(pipe, indexBuf, indexSize,
                                    min_index,
                                    max_index,
@@ -683,10 +627,6 @@ st_draw_vbo(GLcontext *ctx,
       }
       else {
          for (i = 0; i < nr_prims; i++) {
-            setup_edgeflags(ctx, prims[i].mode,
-                            prims[i].start + indexOffset, prims[i].count,
-                            arrays[VERT_ATTRIB_EDGEFLAG]);
-            
             pipe->draw_elements(pipe, indexBuf, indexSize,
                                 prims[i].mode,
                                 prims[i].start + indexOffset, prims[i].count);
@@ -699,10 +639,6 @@ st_draw_vbo(GLcontext *ctx,
       /* non-indexed */
       GLuint i;
       for (i = 0; i < nr_prims; i++) {
-         setup_edgeflags(ctx, prims[i].mode,
-                         prims[i].start, prims[i].count,
-                         arrays[VERT_ATTRIB_EDGEFLAG]);
-
          pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
       }
    }
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index 1611d53..9fd670c 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -741,6 +741,7 @@ emit_face_var( struct st_translate *t,
 const struct tgsi_token *
 st_translate_mesa_program(
    GLcontext *ctx,
+   struct ureg_program *ureg;
    uint procType,
    const struct gl_program *program,
    GLuint numInputs,
@@ -754,7 +755,6 @@ st_translate_mesa_program(
    const ubyte outputSemanticIndex[] )
 {
    struct st_translate translate, *t;
-   struct ureg_program *ureg;
    const struct tgsi_token *tokens = NULL;
    unsigned i;
 
@@ -764,11 +764,7 @@ st_translate_mesa_program(
    t->procType = procType;
    t->inputMapping = inputMapping;
    t->outputMapping = outputMapping;
-   t->ureg = ureg_create( procType );
-   if (t->ureg == NULL)
-      return NULL;
-
-   ureg = t->ureg;
+   t->ureg = ureg;
 
    /*_mesa_print_program(program);*/
 
@@ -899,8 +895,7 @@ st_translate_mesa_program(
                         t->insn[t->labels[i].branch_target] );
    }
 
-   tokens = ureg_get_tokens( ureg, NULL );
-   ureg_destroy( ureg );
+   return PIPE_OK;
 
 out:
    FREE(t->insn);
@@ -919,7 +914,7 @@ out:
       debug_assert(0);
    }
 
-   return tokens;
+   return PIPE_ERROR_OUT_OF_MEMORY;
 }
 
 
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 5c81a03..876d925 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -192,10 +192,16 @@ st_translate_vertex_program(struct st_context *st,
 {
    struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient);
    struct pipe_context *pipe = st->pipe;
+   struct ureg_program *ureg;
 
-   vpv->state.tokens = 
+   ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+   if (ureg == NULL)
+      return NULL;
+
+   error = 
       st_translate_mesa_program(st->ctx,
                                 TGSI_PROCESSOR_VERTEX,
+                                ureg,
                                 &stvp->Base.Base,
                                 /* inputs */
                                 stvp->num_inputs,
@@ -209,6 +215,20 @@ st_translate_vertex_program(struct st_context *st,
                                 stvp->output_semantic_name,
                                 stvp->output_semantic_index );
 
+   if (ret)
+      goto fail;
+
+   /* Edgeflags will be the last input:
+    */
+   if (key.passthrough_edgeflags) {
+      ureg_MOV( ureg,
+                ureg_DECL_output( ureg, TGSI_SEMANTIC_EDGEFLAG, 0 ),
+                ureg_DECL_next_vs_input(ureg));
+   }
+
+   tokens = ureg_get_tokens( ureg, NULL );
+   ureg_destroy( ureg );
+
    vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
 
    if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
@@ -222,6 +242,10 @@ st_translate_vertex_program(struct st_context *st,
    }
 
    return vpv;
+
+fail:
+   ureg_destroy( ureg );
+   return NULL;
 }
 
 
@@ -243,6 +267,7 @@ st_translate_fragment_program(struct st_context *st,
    GLuint interpMode[16];  /* XXX size? */
    GLuint attr;
    const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+   struct ureg_program *ureg;
    GLuint vslot = 0;
 
    uint fs_num_inputs = 0;
@@ -377,6 +402,11 @@ st_translate_fragment_program(struct st_context *st,
    if (!inputMapping)
       inputMapping = defaultInputMapping;
 
+   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+   if (ureg == NULL)
+      return NULL;
+
+
    stfp->state.tokens = 
       st_translate_mesa_program(st->ctx,
                                 TGSI_PROCESSOR_FRAGMENT,
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 88aadbd..9139278 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -73,7 +73,7 @@ struct st_fragment_program
 
 struct st_vp_varient_key
 {
-   char dummy;                  /* currently unused */
+   boolean passthrough_edgeflags;
 };
 
 



More information about the mesa-commit mailing list