intel/fs: Drop the gl_program from fs_visitor
[mesa.git] / src / gallium / drivers / llvmpipe / lp_bld_depth.c
index 2376ca73c51e148a8f1d4007bd5303e8223b8d60..d5d5c5a786e95bc5cc0add9272e8f629356a0444 100644 (file)
@@ -349,8 +349,6 @@ get_z_shift_and_mask(const struct util_format_description *format_desc,
 {
    unsigned total_bits;
    unsigned z_swizzle;
-   unsigned chan;
-   unsigned padding_left, padding_right;
 
    assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
    assert(format_desc->block.width == 1);
@@ -361,29 +359,19 @@ get_z_shift_and_mask(const struct util_format_description *format_desc,
 
    z_swizzle = format_desc->swizzle[0];
 
-   if (z_swizzle == UTIL_FORMAT_SWIZZLE_NONE)
+   if (z_swizzle == PIPE_SWIZZLE_NONE)
       return FALSE;
 
    *width = format_desc->channel[z_swizzle].size;
+   /* & 31 is for the same reason as the 32-bit limit above */
+   *shift = format_desc->channel[z_swizzle].shift & 31;
 
-   padding_right = 0;
-   for (chan = 0; chan < z_swizzle; ++chan)
-      padding_right += format_desc->channel[chan].size;
-
-   padding_left =
-      total_bits - (padding_right + *width);
-
-   if (padding_left || padding_right) {
-      unsigned long long mask_left = (1ULL << (total_bits - padding_left)) - 1;
-      unsigned long long mask_right = (1ULL << (padding_right)) - 1;
-      *mask = mask_left ^ mask_right;
-   }
-   else {
+   if (*width == total_bits) {
       *mask = 0xffffffff;
+   } else {
+      *mask = ((1 << *width) - 1) << *shift;
    }
 
-   *shift = padding_right;
-
    return TRUE;
 }
 
@@ -398,25 +386,23 @@ get_s_shift_and_mask(const struct util_format_description *format_desc,
                      unsigned *shift, unsigned *mask)
 {
    unsigned s_swizzle;
-   unsigned chan, sz;
+   unsigned sz;
 
    s_swizzle = format_desc->swizzle[1];
 
-   if (s_swizzle == UTIL_FORMAT_SWIZZLE_NONE)
+   if (s_swizzle == PIPE_SWIZZLE_NONE)
       return FALSE;
 
    /* just special case 64bit d/s format */
    if (format_desc->block.bits > 32) {
+      /* XXX big-endian? */
       assert(format_desc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT);
       *shift = 0;
       *mask = 0xff;
       return TRUE;
    }
 
-   *shift = 0;
-   for (chan = 0; chan < s_swizzle; chan++)
-      *shift += format_desc->channel[chan].size;
-
+   *shift = format_desc->channel[s_swizzle].shift;
    sz = format_desc->channel[s_swizzle].size;
    *mask = (1U << sz) - 1U;
 
@@ -429,6 +415,7 @@ get_s_shift_and_mask(const struct util_format_description *format_desc,
  * Test the depth mask. Add the number of channel which has none zero mask
  * into the occlusion counter. e.g. maskvalue is {-1, -1, -1, -1}.
  * The counter will add 4.
+ * TODO: could get that out of the fs loop.
  *
  * \param type holds element type of the mask vector.
  * \param maskvalue is the depth test mask.
@@ -457,6 +444,7 @@ lp_build_occlusion_count(struct gallivm_state *gallivm,
                                       LLVMInt32TypeInContext(context), bits);
       count = lp_build_intrinsic_unary(builder, popcntintr,
                                        LLVMInt32TypeInContext(context), bits);
+      count = LLVMBuildZExt(builder, count, LLVMIntTypeInContext(context, 64), "");
    }
    else if(util_cpu_caps.has_avx && type.length == 8) {
       const char *movmskintr = "llvm.x86.avx.movmsk.ps.256";
@@ -467,6 +455,7 @@ lp_build_occlusion_count(struct gallivm_state *gallivm,
                                       LLVMInt32TypeInContext(context), bits);
       count = lp_build_intrinsic_unary(builder, popcntintr,
                                        LLVMInt32TypeInContext(context), bits);
+      count = LLVMBuildZExt(builder, count, LLVMIntTypeInContext(context, 64), "");
    }
    else {
       unsigned i;
@@ -509,8 +498,11 @@ lp_build_occlusion_count(struct gallivm_state *gallivm,
        }
        count = lp_build_intrinsic_unary(builder, popcntintr, counttype, countd);
 
-       if (type.length > 4) {
-          count = LLVMBuildTrunc(builder, count, LLVMIntTypeInContext(context, 32), "");
+       if (type.length > 8) {
+          count = LLVMBuildTrunc(builder, count, LLVMIntTypeInContext(context, 64), "");
+       }
+       else if (type.length < 8) {
+          count = LLVMBuildZExt(builder, count, LLVMIntTypeInContext(context, 64), "");
        }
    }
    newcount = LLVMBuildLoad(builder, counter, "origcount");
@@ -525,6 +517,7 @@ lp_build_occlusion_count(struct gallivm_state *gallivm,
  *
  * \param type  the data type of the fragment depth/stencil values
  * \param format_desc  description of the depth/stencil surface
+ * \param is_1d  whether this resource has only one dimension
  * \param loop_counter  the current loop iteration
  * \param depth_ptr  pointer to the depth/stencil values of this 4x4 block
  * \param depth_stride  stride of the depth/stencil buffer
@@ -535,6 +528,7 @@ void
 lp_build_depth_stencil_load_swizzled(struct gallivm_state *gallivm,
                                      struct lp_type z_src_type,
                                      const struct util_format_description *format_desc,
+                                     boolean is_1d,
                                      LLVMValueRef depth_ptr,
                                      LLVMValueRef depth_stride,
                                      LLVMValueRef *z_fb,
@@ -592,9 +586,14 @@ lp_build_depth_stencil_load_swizzled(struct gallivm_state *gallivm,
    zs_dst_ptr = LLVMBuildGEP(builder, depth_ptr, &depth_offset1, 1, "");
    zs_dst_ptr = LLVMBuildBitCast(builder, zs_dst_ptr, load_ptr_type, "");
    zs_dst1 = LLVMBuildLoad(builder, zs_dst_ptr, "");
-   zs_dst_ptr = LLVMBuildGEP(builder, depth_ptr, &depth_offset2, 1, "");
-   zs_dst_ptr = LLVMBuildBitCast(builder, zs_dst_ptr, load_ptr_type, "");
-   zs_dst2 = LLVMBuildLoad(builder, zs_dst_ptr, "");
+   if (is_1d) {
+      zs_dst2 = lp_build_undef(gallivm, zs_load_type);
+   }
+   else {
+      zs_dst_ptr = LLVMBuildGEP(builder, depth_ptr, &depth_offset2, 1, "");
+      zs_dst_ptr = LLVMBuildBitCast(builder, zs_dst_ptr, load_ptr_type, "");
+      zs_dst2 = LLVMBuildLoad(builder, zs_dst_ptr, "");
+   }
 
    *z_fb = LLVMBuildShuffleVector(builder, zs_dst1, zs_dst2,
                                   LLVMConstVector(shuffles, zs_type.length), "");
@@ -648,6 +647,7 @@ lp_build_depth_stencil_load_swizzled(struct gallivm_state *gallivm,
  *
  * \param type  the data type of the fragment depth/stencil values
  * \param format_desc  description of the depth/stencil surface
+ * \param is_1d  whether this resource has only one dimension
  * \param mask  the alive/dead pixel mask for the quad (vector)
  * \param z_fb  z values read from fb (with padding)
  * \param s_fb  s values read from fb (with padding)
@@ -661,6 +661,7 @@ void
 lp_build_depth_stencil_write_swizzled(struct gallivm_state *gallivm,
                                       struct lp_type z_src_type,
                                       const struct util_format_description *format_desc,
+                                      boolean is_1d,
                                       struct lp_build_mask_context *mask,
                                       LLVMValueRef z_fb,
                                       LLVMValueRef s_fb,
@@ -680,15 +681,15 @@ lp_build_depth_stencil_write_swizzled(struct gallivm_state *gallivm,
    LLVMTypeRef load_ptr_type;
    unsigned depth_bytes = format_desc->block.bits / 8;
    struct lp_type zs_type = lp_depth_type(format_desc, z_src_type.length);
+   struct lp_type z_type = zs_type;
    struct lp_type zs_load_type = zs_type;
 
    zs_load_type.length = zs_load_type.length / 2;
    load_ptr_type = LLVMPointerType(lp_build_vec_type(gallivm, zs_load_type), 0);
 
-   if (zs_type.width > 32)
-      zs_type.width = 32;
+   z_type.width = z_src_type.width;
 
-   lp_build_context_init(&z_bld, gallivm, zs_type);
+   lp_build_context_init(&z_bld, gallivm, z_type);
 
    /*
     * This is far from ideal, at least for late depth write we should do this
@@ -742,7 +743,8 @@ lp_build_depth_stencil_write_swizzled(struct gallivm_state *gallivm,
 
    if (zs_type.width < z_src_type.width) {
       /* Truncate ZS values (e.g., when writing to Z16_UNORM) */
-      z_value = LLVMBuildTrunc(builder, z_value, z_bld.vec_type, "");
+      z_value = LLVMBuildTrunc(builder, z_value,
+                               lp_build_int_vec_type(gallivm, zs_type), "");
    }
 
    if (format_desc->block.bits <= 32) {
@@ -762,9 +764,9 @@ lp_build_depth_stencil_write_swizzled(struct gallivm_state *gallivm,
    }
    else {
       if (z_src_type.length == 4) {
-         zs_dst1 = lp_build_interleave2(gallivm, zs_type,
+         zs_dst1 = lp_build_interleave2(gallivm, z_type,
                                         z_value, s_value, 0);
-         zs_dst2 = lp_build_interleave2(gallivm, zs_type,
+         zs_dst2 = lp_build_interleave2(gallivm, z_type,
                                         z_value, s_value, 1);
       }
       else {
@@ -790,7 +792,9 @@ lp_build_depth_stencil_write_swizzled(struct gallivm_state *gallivm,
    }
 
    LLVMBuildStore(builder, zs_dst1, zs_dst_ptr1);
-   LLVMBuildStore(builder, zs_dst2, zs_dst_ptr2);
+   if (!is_1d) {
+      LLVMBuildStore(builder, zs_dst2, zs_dst_ptr2);
+   }
 }
 
 /**
@@ -833,7 +837,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
    LLVMValueRef stencil_vals = NULL;
    LLVMValueRef z_bitmask = NULL, stencil_shift = NULL;
    LLVMValueRef z_pass = NULL, s_pass_mask = NULL;
-   LLVMValueRef orig_mask = lp_build_mask_value(mask);
+   LLVMValueRef current_mask = lp_build_mask_value(mask);
    LLVMValueRef front_facing = NULL;
    boolean have_z, have_s;
 
@@ -869,8 +873,8 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
       const unsigned z_swizzle = format_desc->swizzle[0];
       const unsigned s_swizzle = format_desc->swizzle[1];
 
-      assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE ||
-             s_swizzle != UTIL_FORMAT_SWIZZLE_NONE);
+      assert(z_swizzle != PIPE_SWIZZLE_NONE ||
+             s_swizzle != PIPE_SWIZZLE_NONE);
 
       assert(depth->enabled || stencil[0].enabled);
 
@@ -959,21 +963,49 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
    if (stencil[0].enabled) {
 
       if (face) {
-         LLVMValueRef zero = lp_build_const_int32(gallivm, 0);
-
-         /* front_facing = face != 0 ? ~0 : 0 */
-         front_facing = LLVMBuildICmp(builder, LLVMIntNE, face, zero, "");
-         front_facing = LLVMBuildSExt(builder, front_facing,
-                                      LLVMIntTypeInContext(gallivm->context,
-                                             s_bld.type.length*s_bld.type.width),
-                                      "");
-         front_facing = LLVMBuildBitCast(builder, front_facing,
-                                         s_bld.int_vec_type, "");
-      }
+         if (0) {
+            /*
+             * XXX: the scalar expansion below produces atrocious code
+             * (basically producing a 64bit scalar value, then moving the 2
+             * 32bit pieces separately to simd, plus 4 shuffles, which is
+             * seriously lame). But the scalar-simd transitions are always
+             * tricky, so no big surprise there.
+             * This here would be way better, however llvm has some serious
+             * trouble later using it in the select, probably because it will
+             * recognize the expression as constant and move the simd value
+             * away (out of the loop) - and then it will suddenly try
+             * constructing i1 high-bit masks out of it later...
+             * (Try piglit stencil-twoside.)
+             * Note this is NOT due to using SExt/Trunc, it fails exactly the
+             * same even when using native compare/select.
+             * I cannot reproduce this problem when using stand-alone compiler
+             * though, suggesting some problem with optimization passes...
+             * (With stand-alone compilation, the construction of this mask
+             * value, no matter if the easy 3 instruction here or the complex
+             * 16+ one below, never gets separated from where it's used.)
+             * The scalar code still has the same problem, but the generated
+             * code looks a bit better at least for some reason, even if
+             * mostly by luck (the fundamental issue clearly is the same).
+             */
+            front_facing = lp_build_broadcast(gallivm, s_bld.vec_type, face);
+            /* front_facing = face != 0 ? ~0 : 0 */
+            front_facing = lp_build_compare(gallivm, s_bld.type,
+                                            PIPE_FUNC_NOTEQUAL,
+                                            front_facing, s_bld.zero);
+         } else {
+            LLVMValueRef zero = lp_build_const_int32(gallivm, 0);
 
-      /* convert scalar stencil refs into vectors */
-      stencil_refs[0] = lp_build_broadcast_scalar(&s_bld, stencil_refs[0]);
-      stencil_refs[1] = lp_build_broadcast_scalar(&s_bld, stencil_refs[1]);
+            /* front_facing = face != 0 ? ~0 : 0 */
+            front_facing = LLVMBuildICmp(builder, LLVMIntNE, face, zero, "");
+            front_facing = LLVMBuildSExt(builder, front_facing,
+                                         LLVMIntTypeInContext(gallivm->context,
+                                                s_bld.type.length*s_bld.type.width),
+                                         "");
+            front_facing = LLVMBuildBitCast(builder, front_facing,
+                                            s_bld.int_vec_type, "");
+
+         }
+      }
 
       s_pass_mask = lp_build_stencil_test(&s_bld, stencil,
                                           stencil_refs, stencil_vals,
@@ -981,7 +1013,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
 
       /* apply stencil-fail operator */
       {
-         LLVMValueRef s_fail_mask = lp_build_andnot(&s_bld, orig_mask, s_pass_mask);
+         LLVMValueRef s_fail_mask = lp_build_andnot(&s_bld, current_mask, s_pass_mask);
          stencil_vals = lp_build_stencil_op(&s_bld, stencil, S_FAIL_OP,
                                             stencil_refs, stencil_vals,
                                             s_fail_mask, front_facing);
@@ -1029,6 +1061,11 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
       /* compare src Z to dst Z, returning 'pass' mask */
       z_pass = lp_build_cmp(&z_bld, depth->func, z_src, z_dst);
 
+      /* mask off bits that failed stencil test */
+      if (s_pass_mask) {
+         current_mask = LLVMBuildAnd(builder, current_mask, s_pass_mask, "");
+      }
+
       if (!stencil[0].enabled) {
          /* We can potentially skip all remaining operations here, but only
           * if stencil is disabled because we still need to update the stencil
@@ -1038,25 +1075,19 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
 
          if (do_branch) {
             lp_build_mask_check(mask);
-            do_branch = FALSE;
          }
       }
 
       if (depth->writemask) {
-         LLVMValueRef zselectmask;
+         LLVMValueRef z_pass_mask;
 
          /* mask off bits that failed Z test */
-         zselectmask = LLVMBuildAnd(builder, orig_mask, z_pass, "");
-
-         /* mask off bits that failed stencil test */
-         if (s_pass_mask) {
-            zselectmask = LLVMBuildAnd(builder, zselectmask, s_pass_mask, "");
-         }
+         z_pass_mask = LLVMBuildAnd(builder, current_mask, z_pass, "");
 
          /* Mix the old and new Z buffer values.
           * z_dst[i] = zselectmask[i] ? z_src[i] : z_dst[i]
           */
-         z_dst = lp_build_select(&z_bld, zselectmask, z_src, z_dst);
+         z_dst = lp_build_select(&z_bld, z_pass_mask, z_src, z_dst);
       }
 
       if (stencil[0].enabled) {
@@ -1064,13 +1095,13 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
          LLVMValueRef z_fail_mask, z_pass_mask;
 
          /* apply Z-fail operator */
-         z_fail_mask = lp_build_andnot(&s_bld, orig_mask, z_pass);
+         z_fail_mask = lp_build_andnot(&s_bld, current_mask, z_pass);
          stencil_vals = lp_build_stencil_op(&s_bld, stencil, Z_FAIL_OP,
                                             stencil_refs, stencil_vals,
                                             z_fail_mask, front_facing);
 
          /* apply Z-pass operator */
-         z_pass_mask = LLVMBuildAnd(builder, orig_mask, z_pass, "");
+         z_pass_mask = LLVMBuildAnd(builder, current_mask, z_pass, "");
          stencil_vals = lp_build_stencil_op(&s_bld, stencil, Z_PASS_OP,
                                             stencil_refs, stencil_vals,
                                             z_pass_mask, front_facing);
@@ -1080,7 +1111,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
       /* No depth test: apply Z-pass operator to stencil buffer values which
        * passed the stencil test.
        */
-      s_pass_mask = LLVMBuildAnd(builder, orig_mask, s_pass_mask, "");
+      s_pass_mask = LLVMBuildAnd(builder, current_mask, s_pass_mask, "");
       stencil_vals = lp_build_stencil_op(&s_bld, stencil, Z_PASS_OP,
                                          stencil_refs, stencil_vals,
                                          s_pass_mask, front_facing);
@@ -1096,23 +1127,18 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
                                   stencil_shift, "");
 
    /* Finally, merge the z/stencil values */
-   if ((depth->enabled && depth->writemask) ||
-       (stencil[0].enabled && (stencil[0].writemask ||
-                               (stencil[1].enabled && stencil[1].writemask)))) {
-
-      if (format_desc->block.bits <= 32) {
-         if (have_z && have_s)
-            *z_value = LLVMBuildOr(builder, z_dst, stencil_vals, "");
-         else if (have_z)
-            *z_value = z_dst;
-         else
-            *z_value = stencil_vals;
-         *s_value = *z_value;
-      }
-      else {
+   if (format_desc->block.bits <= 32) {
+      if (have_z && have_s)
+         *z_value = LLVMBuildOr(builder, z_dst, stencil_vals, "");
+      else if (have_z)
          *z_value = z_dst;
-         *s_value = stencil_vals;
-      }
+      else
+         *z_value = stencil_vals;
+      *s_value = *z_value;
+   }
+   else {
+      *z_value = z_dst;
+      *s_value = stencil_vals;
    }
 
    if (s_pass_mask)
@@ -1120,9 +1146,5 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
 
    if (depth->enabled && stencil[0].enabled)
       lp_build_mask_update(mask, z_pass);
-
-   if (do_branch)
-      lp_build_mask_check(mask);
-
 }