/**
- * 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,
else
assert(0);
- assert(type.width <= length);
- type.length = length / type.width;
+ type.length = length;
return type;
}
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;
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
}
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 ==
/* 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");
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), "");
/* 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);
!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);
}
}
!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) &&
!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);
}
}
!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) &&