llvmpipe: Support Z16_UNORM as depth-stencil format.
authorJosé Fonseca <jfonseca@vmware.com>
Mon, 28 Jan 2013 19:10:22 +0000 (19:10 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 29 Jan 2013 07:06:36 +0000 (07:06 +0000)
Simply by adjusting the vector element width after/before
reading/writing the depth-stencil values.

Ran several GL_DEPTH_COMPONENT16 piglit tests without regressions.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/drivers/llvmpipe/lp_bld_depth.c
src/gallium/drivers/llvmpipe/lp_bld_depth.h
src/gallium/drivers/llvmpipe/lp_screen.c
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 5c3715aa8fbe968b26d77797128498913c45095c..1c899b31cc9c825383b150523a3a065f37e4813e 100644 (file)
@@ -299,7 +299,7 @@ lp_build_stencil_op(struct lp_build_context *bld,
 
 
 /**
- * Return a type appropriate for depth/stencil testing.
+ * Return a type that matches the depth/stencil format.
  */
 struct lp_type
 lp_depth_type(const struct util_format_description *format_desc,
@@ -336,8 +336,7 @@ lp_depth_type(const struct util_format_description *format_desc,
    else
       assert(0);
 
-   assert(type.width <= length);
-   type.length = length / type.width;
+   type.length = length;
 
    return type;
 }
@@ -546,6 +545,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
                             boolean do_branch)
 {
    LLVMBuilderRef builder = gallivm->builder;
+   struct lp_type zs_type;
    struct lp_type z_type;
    struct lp_build_context z_bld;
    struct lp_build_context s_bld;
@@ -573,11 +573,14 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
       assert(z_src_type.norm);
    }
 
-   /* Pick the depth type. */
-   z_type = lp_depth_type(format_desc, z_src_type.width*z_src_type.length);
+   /* Pick the type matching the depth-stencil format. */
+   zs_type = lp_depth_type(format_desc, z_src_type.length);
 
-   /* FIXME: Cope with a depth test type with a different bit width. */
-   assert(z_type.width == z_src_type.width);
+   /* Pick the intermediate type for depth operations. */
+   z_type = zs_type;
+   /* FIXME: Cope with a depth test type with higher bit width. */
+   assert(zs_type.width <= z_src_type.width);
+   z_type.width = z_src_type.width;
    assert(z_type.length == z_src_type.length);
 
    /* FIXME: for non-float depth/stencil might generate better code
@@ -606,7 +609,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
       }
 
       assert(z_swizzle < 4);
-      assert(format_desc->block.bits == z_type.width);
+      assert(format_desc->block.bits <= z_type.width);
       if (z_type.floating) {
          assert(z_swizzle == 0);
          assert(format_desc->channel[z_swizzle].type ==
@@ -633,8 +636,12 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
    /* Load current z/stencil value from z/stencil buffer */
    zs_dst_ptr = LLVMBuildBitCast(builder,
                                  zs_dst_ptr,
-                                 LLVMPointerType(z_bld.vec_type, 0), "");
+                                 LLVMPointerType(lp_build_vec_type(gallivm, zs_type), 0), "");
    zs_dst = LLVMBuildLoad(builder, zs_dst_ptr, "");
+   if (format_desc->block.bits < z_type.width) {
+      /* Extend destination ZS values (e.g., when reading from Z16_UNORM) */
+      zs_dst = LLVMBuildZExt(builder, zs_dst, z_bld.vec_type, "");
+   }
 
    lp_build_name(zs_dst, "zs_dst");
 
@@ -850,11 +857,23 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
 
 
 void
-lp_build_depth_write(LLVMBuilderRef builder,
+lp_build_depth_write(struct gallivm_state *gallivm,
+                     struct lp_type z_src_type,
                      const struct util_format_description *format_desc,
                      LLVMValueRef zs_dst_ptr,
                      LLVMValueRef zs_value)
 {
+   LLVMBuilderRef builder = gallivm->builder;
+
+   if (format_desc->block.bits < z_src_type.width) {
+      /* Truncate income ZS values (e.g., when writing to Z16_UNORM) */
+      LLVMTypeRef zs_type = LLVMIntTypeInContext(gallivm->context, format_desc->block.bits);
+      if (z_src_type.length > 1) {
+         zs_type = LLVMVectorType(zs_type, z_src_type.length);
+      }
+      zs_value = LLVMBuildTrunc(builder, zs_value, zs_type, "");
+   }
+
    zs_dst_ptr = LLVMBuildBitCast(builder, zs_dst_ptr,
                                  LLVMPointerType(LLVMTypeOf(zs_value), 0), "");
 
@@ -877,13 +896,18 @@ lp_build_deferred_depth_write(struct gallivm_state *gallivm,
 
    /* XXX: pointlessly redo type logic:
     */
-   z_type = lp_depth_type(format_desc, z_src_type.width*z_src_type.length);
+   z_type = lp_depth_type(format_desc, z_src_type.length);
    lp_build_context_init(&z_bld, gallivm, z_type);
 
    zs_dst_ptr = LLVMBuildBitCast(builder, zs_dst_ptr,
                                  LLVMPointerType(z_bld.vec_type, 0), "");
 
    z_dst = LLVMBuildLoad(builder, zs_dst_ptr, "zsbufval");
+
+   if (z_type.width < z_src_type.width) {
+      zs_value = LLVMBuildTrunc(builder, zs_value, z_bld.vec_type, "");
+   }
+
    z_dst = lp_build_select(&z_bld, lp_build_mask_value(mask), zs_value, z_dst);
 
    LLVMBuildStore(builder, z_dst, zs_dst_ptr);
index e01fc46ec1693b4d591ba0a2c89574e73045342d..33cb0dd4a9e3e20cd55213ae01c34ebe4aa182b0 100644 (file)
@@ -69,7 +69,8 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm,
                             boolean do_branch);
 
 void
-lp_build_depth_write(LLVMBuilderRef builder,
+lp_build_depth_write(struct gallivm_state *gallivm,
+                     struct lp_type z_src_type,
                      const struct util_format_description *format_desc,
                      LLVMValueRef zs_dst_ptr,
                      LLVMValueRef zs_value);
index 872967caeef65a75e8920eaea817ea86f8bd8210..de80c6fdc6b4fab5e0eac5169826056181c46b69 100644 (file)
@@ -302,10 +302,6 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
    if (!format_desc)
       return FALSE;
 
-   /* Z16 support is missing, which breaks the blit */
-   if (format == PIPE_FORMAT_Z16_UNORM)
-      return FALSE;
-
    assert(target == PIPE_BUFFER ||
           target == PIPE_TEXTURE_1D ||
           target == PIPE_TEXTURE_1D_ARRAY ||
@@ -360,8 +356,8 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
       if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
          return FALSE;
 
-      /* FIXME: Temporary restriction. See lp_state_fs.c. */
-      if (format_desc->block.bits != 32)
+      /* FIXME: Temporary restriction. See lp_bld_depth.c. */
+      if (format_desc->block.bits > 32)
          return FALSE;
    }
 
index 09f37e0ceaddb63d9f8be6d57a29764475724375..00f3b6990e3fd0c67299200935c560beac47d117 100644 (file)
@@ -335,7 +335,7 @@ generate_fs(struct gallivm_state *gallivm,
                                   !simple_shader);
 
       if (depth_mode & EARLY_DEPTH_WRITE) {
-         lp_build_depth_write(builder, zs_format_desc, depth_ptr, zs_value);
+         lp_build_depth_write(gallivm, type, zs_format_desc, depth_ptr, zs_value);
       }
    }
 
@@ -392,7 +392,7 @@ generate_fs(struct gallivm_state *gallivm,
                                   !simple_shader);
       /* Late Z write */
       if (depth_mode & LATE_DEPTH_WRITE) {
-         lp_build_depth_write(builder, zs_format_desc, depth_ptr, zs_value);
+         lp_build_depth_write(gallivm, type, zs_format_desc, depth_ptr, zs_value);
       }
    }
    else if ((depth_mode & EARLY_DEPTH_TEST) &&
@@ -574,7 +574,7 @@ generate_fs_loop(struct gallivm_state *gallivm,
                                   !simple_shader);
 
       if (depth_mode & EARLY_DEPTH_WRITE) {
-         lp_build_depth_write(builder, zs_format_desc, depth_ptr_i, zs_value);
+         lp_build_depth_write(gallivm, type, zs_format_desc, depth_ptr_i, zs_value);
       }
    }
 
@@ -631,7 +631,7 @@ generate_fs_loop(struct gallivm_state *gallivm,
                                   !simple_shader);
       /* Late Z write */
       if (depth_mode & LATE_DEPTH_WRITE) {
-         lp_build_depth_write(builder, zs_format_desc, depth_ptr_i, zs_value);
+         lp_build_depth_write(gallivm, type, zs_format_desc, depth_ptr_i, zs_value);
       }
    }
    else if ((depth_mode & EARLY_DEPTH_TEST) &&