gallium: first steps to treat edgeflags as regular vertex element
authorKeith Whitwell <keithw@vmware.com>
Wed, 9 Dec 2009 18:03:10 +0000 (19:03 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Wed, 9 Dec 2009 18:03:10 +0000 (19:03 +0100)
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).

15 files changed:
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_context.h
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt.h
src/gallium/auxiliary/draw/draw_pt_fetch.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_post_vs.c
src/gallium/include/pipe/p_context.h
src/gallium/include/pipe/p_shader_tokens.h
src/mesa/state_tracker/st_atom_shader.c
src/mesa/state_tracker/st_draw.c
src/mesa/state_tracker/st_mesa_to_tgsi.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index a4f1fcddc1a0cd6f9de25be4bd0c21c791f5da4e..cc5f7f01059f53b19f381725b5541bc695c008c5 100644 (file)
@@ -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;
-}
-
-
 
 
 /**
index d529e4e9a27f7e3f35c7eb24b0732f6fff1cc722..465b8f10c6c3562d5816beb4d4bf3660444c7a09 100644 (file)
@@ -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 
index 41fcb16a0a5a1df71c3de27bbafaec358fd5b61c..0750e6e3797aa5e2f4329e0563c5ea48b778e891 100644 (file)
@@ -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) */
index 4865a2d85421cc28f74fc753629bce7db1503d8c..139ae1fe552e65b8e02da73fe47fe2ce7904e402 100644 (file)
@@ -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;
 }
index 7a17a9fb6b2818013966b6b13c7a78be0849a6a8..b5c8c82f4a6c1eae12db13228c6a28aef7ae51fc 100644 (file)
@@ -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:
index 65c3a34c3474a664fbac65042117800174eda9db..cb609f8c41ebf5c00cb52f296ac262779fab4bc7 100644 (file)
@@ -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 );
    }
 }
 
index df6c265b7ec9026a95cd6383b1d70adb242efcbb..d41436858ad2eb4c28a5888be60b155c82126386 100644 (file)
@@ -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)) {
index 6c1cb48e8b82202da1638d2a7a9cdf9cbd40c247..0745b168de21820b9146f63ca85645bebf4804ef 100644 (file)
@@ -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;
    }
 }
 
index f896001eb12091d3d7035eb908731e42ca4258ab..11bcdc0a24c2ae69992eb129e774eda7ae7774e3 100644 (file)
@@ -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??))
     */
index 588ca5e026d482c784ee9c7e14890d0b96dfc761..c051d4dae8449f05ad13fe49a4135226c70ee25d 100644 (file)
@@ -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
 {
index 09baff875bc1e7f9d58877935a89a52091be18ce..e209634c9048b57aec9044221d444a56540683eb 100644 (file)
@@ -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?
index e13ae57a0ec409b2cbdd5d98e4830e0abd29883f..773a3f17cdd0f564ff9a40f710df47e5204487ab 100644 (file)
@@ -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);
       }
    }
index 1611d53e2fe644fc981217aa2b129868152074e1..9fd670cac230bf45fd7f70a344be6ee20808940e 100644 (file)
@@ -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;
 }
 
 
index 5c81a033f9ce71101c1c39b02169d3876894d19b..876d92539e900ab1c8a56be7fef2d43d43770e29 100644 (file)
@@ -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,
index 88aadbd75102a5e01a1591695a946045819829e3..91392785e5566e2bd456ed4299179a8003cca051 100644 (file)
@@ -73,7 +73,7 @@ struct st_fragment_program
 
 struct st_vp_varient_key
 {
-   char dummy;                  /* currently unused */
+   boolean passthrough_edgeflags;
 };