draw/softpipe: add clip vertex support. (v2)
authorDave Airlie <airlied@redhat.com>
Wed, 4 Jan 2012 11:52:30 +0000 (11:52 +0000)
committerDave Airlie <airlied@redhat.com>
Wed, 11 Jan 2012 07:13:35 +0000 (07:13 +0000)
softpipe always clipped using the position vector, however for unclipped
vertices it stored the position in window coordinates, however when position
and clipping are separated, we need to store the clip-space position and
the clip-space vertex clip, so we can interpolate both separately.

This means we have to take the clip space position and store it to use later.

This allows softpipe to pass all the clip-vertex piglit tests.

v2: fix llvm draw regression, the structure being passed into llvm needed
updating, remove some hardcoded ints that should have been enums while there.

Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/auxiliary/draw/draw_cliptest_tmp.h
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_pipe_clip.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt_fetch.c
src/gallium/auxiliary/draw/draw_vs.c
src/gallium/auxiliary/draw/draw_vs.h

index 9e6827cc452bcbdd0ed162c1969168bfca52a5db..7dba49b28706d4a35acb8e6d15de35e07fafc0a3 100644 (file)
@@ -35,11 +35,13 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
    const float *trans = pvs->draw->viewport.translate;
    /* const */ float (*plane)[4] = pvs->draw->plane;
    const unsigned pos = draw_current_shader_position_output(pvs->draw);
+   const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
    const unsigned ef = pvs->draw->vs.edgeflag_output;
    const unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
    const unsigned flags = (FLAGS);
    unsigned need_pipeline = 0;
    unsigned j;
+   unsigned i;
 
    for (j = 0; j < info->count; j++) {
       float *position = out->data[pos];
@@ -49,10 +51,15 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
 
       if (flags & (DO_CLIP_XY | DO_CLIP_XY_GUARD_BAND |
                    DO_CLIP_FULL_Z | DO_CLIP_HALF_Z | DO_CLIP_USER)) {
-         out->clip[0] = position[0];
-         out->clip[1] = position[1];
-         out->clip[2] = position[2];
-         out->clip[3] = position[3];
+         float *clipvertex = position;
+
+         if ((flags & DO_CLIP_USER) && cv != pos)
+            clipvertex = out->data[cv];
+
+         for (i = 0; i < 4; i++) {
+            out->clip[i] = clipvertex[i];
+            out->pre_clip_pos[i] = position[i];
+         }
 
          /* Do the hardwired planes first:
           */
@@ -88,7 +95,7 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
                ucp_mask &= ~(1 << plane_idx);
                plane_idx += 6;
 
-               if (dot4(position, plane[plane_idx]) < 0) {
+               if (dot4(clipvertex, plane[plane_idx]) < 0) {
                   mask |= 1 << plane_idx;
                }
             }
index 10a20f761784fd468686b59d580b7f22cbaff151..6d7075e545246ac661a81d2b779232b28cb546a4 100644 (file)
@@ -691,6 +691,16 @@ draw_current_shader_position_output(const struct draw_context *draw)
 }
 
 
+/**
+ * Return the index of the shader output which will contain the
+ * vertex position.
+ */
+uint
+draw_current_shader_clipvertex_output(const struct draw_context *draw)
+{
+   return draw->vs.clipvertex_output;
+}
+
 /**
  * Return a pointer/handle for a driver/CSO rasterizer object which
  * disabled culling, stippling, unfilled tris, etc.
index cf97e82a63c8e774846b6999bc07366cb1cea6f4..50c7e254debbff424234789ce85480aabbae73b8 100644 (file)
@@ -268,15 +268,16 @@ static LLVMTypeRef
 create_jit_vertex_header(struct gallivm_state *gallivm, int data_elems)
 {
    LLVMTargetDataRef target = gallivm->target;
-   LLVMTypeRef elem_types[3];
+   LLVMTypeRef elem_types[4];
    LLVMTypeRef vertex_header;
    char struct_name[24];
 
    util_snprintf(struct_name, 23, "vertex_header%d", data_elems);
 
-   elem_types[0]  = LLVMIntTypeInContext(gallivm->context, 32);
-   elem_types[1]  = LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
-   elem_types[2]  = LLVMArrayType(elem_types[1], data_elems);
+   elem_types[DRAW_JIT_VERTEX_VERTEX_ID]  = LLVMIntTypeInContext(gallivm->context, 32);
+   elem_types[DRAW_JIT_VERTEX_CLIP]  = LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
+   elem_types[DRAW_JIT_VERTEX_PRE_CLIP_POS]  = LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
+   elem_types[DRAW_JIT_VERTEX_DATA]  = LLVMArrayType(elem_types[1], data_elems);
 
 #if HAVE_LLVM >= 0x0300
    vertex_header = LLVMStructCreateNamed(gallivm->context, struct_name);
@@ -307,6 +308,9 @@ create_jit_vertex_header(struct gallivm_state *gallivm, int data_elems)
    LP_CHECK_MEMBER_OFFSET(struct vertex_header, clip,
                           target, vertex_header,
                           DRAW_JIT_VERTEX_CLIP);
+   LP_CHECK_MEMBER_OFFSET(struct vertex_header, pre_clip_pos,
+                          target, vertex_header,
+                          DRAW_JIT_VERTEX_PRE_CLIP_POS);
    LP_CHECK_MEMBER_OFFSET(struct vertex_header, data,
                           target, vertex_header,
                           DRAW_JIT_VERTEX_DATA);
index edd1a08e3db03832a5c1e1eb93563e45d9544e5c..31fc2db05bd3a328681c37cdc2118cabafe0a0d6 100644 (file)
@@ -80,6 +80,7 @@ enum {
 enum {
    DRAW_JIT_VERTEX_VERTEX_ID = 0,
    DRAW_JIT_VERTEX_CLIP,
+   DRAW_JIT_VERTEX_PRE_CLIP_POS,
    DRAW_JIT_VERTEX_DATA
 };
 
@@ -123,13 +124,16 @@ struct draw_jit_context
    lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_TEXTURES, "textures")
 
 #define draw_jit_header_id(_gallivm, _ptr)              \
-   lp_build_struct_get_ptr(_gallivm, _ptr, 0, "id")
+   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_VERTEX_ID, "id")
 
 #define draw_jit_header_clip(_gallivm, _ptr) \
-   lp_build_struct_get_ptr(_gallivm, _ptr, 1, "clip")
+   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_CLIP, "clip")
+
+#define draw_jit_header_pre_clip_pos(_gallivm, _ptr) \
+   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_PRE_CLIP_POS, "pre_clip_pos")
 
 #define draw_jit_header_data(_gallivm, _ptr)            \
-   lp_build_struct_get_ptr(_gallivm, _ptr, 2, "data")
+   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_DATA, "data")
 
 
 #define draw_jit_vbuffer_stride(_gallivm, _ptr)         \
index e1eabe22288a24aaf0709313cf112c8aa7154dbb..fbc8f6751298fabad8a6bca6b9b1b9f0592bf3b6 100644 (file)
@@ -118,6 +118,7 @@ static void interp( const struct clip_stage *clip,
 {
    const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw);
    const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
+   const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
    unsigned j;
 
    /* Vertex header.
@@ -130,12 +131,14 @@ static void interp( const struct clip_stage *clip,
    /* Interpolate the clip-space coords.
     */
    interp_attr(dst->clip, t, in->clip, out->clip);
+   /* interpolate the clip-space position */
+   interp_attr(dst->pre_clip_pos, t, in->pre_clip_pos, out->pre_clip_pos);
 
    /* Do the projective divide and viewport transformation to get
     * new window coordinates:
     */
    {
-      const float *pos = dst->clip;
+      const float *pos = dst->pre_clip_pos;
       const float *scale = clip->stage.draw->viewport.scale;
       const float *trans = clip->stage.draw->viewport.translate;
       const float oow = 1.0f / pos[3];
@@ -149,8 +152,8 @@ static void interp( const struct clip_stage *clip,
    /* Other attributes
     */
    for (j = 0; j < nr_attrs; j++) {
-      if (j != pos_attr)
-         interp_attr(dst->data[j], t, in->data[j], out->data[j]);
+      if (j != pos_attr && j != clip_attr)
+        interp_attr(dst->data[j], t, in->data[j], out->data[j]);
    }
 }
 
index 91112eb96b440dfd4fdd82c17e09bd94d4d27edd..aa9b602a353125dd34ac88823a60a50e4ffeae54 100644 (file)
@@ -76,6 +76,7 @@ struct vertex_header {
    unsigned vertex_id:16;
 
    float clip[4];
+   float pre_clip_pos[4];
 
    /* This will probably become float (*data)[4] soon:
     */
@@ -230,6 +231,7 @@ struct draw_context
       uint num_vs_outputs;  /**< convenience, from vertex_shader */
       uint position_output;
       uint edgeflag_output;
+      uint clipvertex_output;
 
       /** TGSI program interpreter runtime state */
       struct tgsi_exec_machine *machine;
@@ -378,7 +380,7 @@ void draw_gs_destroy( struct draw_context *draw );
  */
 uint draw_current_shader_outputs(const struct draw_context *draw);
 uint draw_current_shader_position_output(const struct draw_context *draw);
-
+uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
 int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
                                    uint semantic_name, uint semantic_index);
 void draw_remove_extra_vertex_attribs(struct draw_context *draw);
index b0032e5ad0e94ff7302e7c7befc7566160c777fa..a6cc1834e6c426bbf43e3bf91b691316f3a3aef7 100644 (file)
@@ -74,9 +74,9 @@ draw_pt_fetch_prepare(struct pt_fetch *fetch,
    /* Leave the clipmask/edgeflags/pad/vertex_id untouched
     */
    dst_offset += 1 * sizeof(float);
-   /* Just leave the clip[] array untouched.
+   /* Just leave the clip[] and pre_clip_pos[] array untouched.
     */
-   dst_offset += 4 * sizeof(float);
+   dst_offset += 8 * sizeof(float);
 
    if (instance_id_index != ~0) {
       num_extra_inputs++;
index bc1c90b0f3a1e6315fd0a2cdaf5e5a3acae35b0d..150653c669ac049446a31c8fca49ccf7ede6c02a 100644 (file)
@@ -120,6 +120,7 @@ draw_create_vertex_shader(struct draw_context *draw,
    if (vs)
    {
       uint i;
+      bool found_clipvertex = FALSE;
       for (i = 0; i < vs->info.num_outputs; i++) {
          if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
              vs->info.output_semantic_index[i] == 0)
@@ -127,7 +128,14 @@ draw_create_vertex_shader(struct draw_context *draw,
          else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_EDGEFLAG &&
              vs->info.output_semantic_index[i] == 0)
             vs->edgeflag_output = i;
+         else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPVERTEX &&
+                  vs->info.output_semantic_index[i] == 0) {
+            found_clipvertex = TRUE;
+            vs->clipvertex_output = i;
+         }
       }
+      if (!found_clipvertex)
+         vs->clipvertex_output = vs->position_output;
    }
 
    assert(vs);
@@ -147,6 +155,7 @@ draw_bind_vertex_shader(struct draw_context *draw,
       draw->vs.num_vs_outputs = dvs->info.num_outputs;
       draw->vs.position_output = dvs->position_output;
       draw->vs.edgeflag_output = dvs->edgeflag_output;
+      draw->vs.clipvertex_output = dvs->clipvertex_output;
       dvs->prepare( dvs, draw );
    }
    else {
index 49229f8164b675d78eea29072dad7d3c08503994..a3b90faa24b505b06cab6bd5f7758790328b1075 100644 (file)
@@ -111,6 +111,7 @@ struct draw_vertex_shader {
    struct tgsi_shader_info info;
    unsigned position_output;
    unsigned edgeflag_output;
+   unsigned clipvertex_output;
 
    /* Extracted from shader:
     */