From 0ca384fb39f6d98af2de5654c46394743147d228 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Mon, 28 Jan 2013 19:10:22 +0000 Subject: [PATCH] llvmpipe: Support Z16_UNORM as depth-stencil format. 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 Reviewed-by: Roland Scheidegger --- 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 5c3715aa8fb..1c899b31cc9 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 e01fc46ec16..33cb0dd4a9e 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 872967caeef..de80c6fdc6b 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 09f37e0cead..00f3b6990e3 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) && -- 2.30.2