[Mesa-dev] [PATCH] llvmpipe: Support Z16_UNORM as depth-stencil format.

jfonseca at vmware.com jfonseca at vmware.com
Mon Jan 28 11:10:22 PST 2013


From: José Fonseca <jfonseca at vmware.com>

Simply by adjusting the vector element width after/before
reading/writing the depth-stencil values.

Ran several GL_DEPTH_COMPONENT16 piglit tests without regressions.
---
 src/gallium/drivers/llvmpipe/lp_bld_depth.c |   46 ++++++++++++++++++++-------
 src/gallium/drivers/llvmpipe/lp_bld_depth.h |    3 +-
 src/gallium/drivers/llvmpipe/lp_screen.c    |    8 ++---
 src/gallium/drivers/llvmpipe/lp_state_fs.c  |    8 ++---
 4 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
index 5c3715a..1c899b3 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
index e01fc46..33cb0dd 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index 872967c..de80c6f 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -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;
    }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 09f37e0..00f3b69 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -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) &&
-- 
1.7.9.5



More information about the mesa-dev mailing list