summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/llvmpipe
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-12-06 01:28:25 -0500
committerZack Rusin <[email protected]>2013-12-10 16:39:48 -0500
commit155139059ba588da1161eaa692515cacdead9f4e (patch)
treef64daec33014ca5ea6ccf8d93a58ae064dda28eb /src/gallium/drivers/llvmpipe
parent1e71493afa263791b2ff10afd2fbc36a7effa73f (diff)
llvmpipe: fix blending with half-float formats
The fact that we flush denorms to zero breaks our half-float conversion and blending. This patches enables denorms for blending. It's a little tricky due to the llvm bug that makes it incorrectly reorder the mxcsr intrinsics: http://llvm.org/bugs/show_bug.cgi?id=6393 Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: José Fonseca <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]> Signed-off-by: Zack Rusin <[email protected]>
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 74c7360bfbb..93c24f6ba38 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -1554,6 +1554,28 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
const boolean is_1d = variant->key.resource_1d;
unsigned num_fullblock_fs = is_1d ? 2 * num_fs : num_fs;
+ LLVMValueRef fpstate = 0;
+
+ /* Get type from output format */
+ lp_blend_type_from_format_desc(out_format_desc, &row_type);
+ lp_mem_type_from_format_desc(out_format_desc, &dst_type);
+
+ /*
+ * Technically this code should go into lp_build_smallfloat_to_float
+ * and lp_build_float_to_smallfloat but due to the
+ * http://llvm.org/bugs/show_bug.cgi?id=6393
+ * llvm reorders the mxcsr intrinsics in a way that breaks the code.
+ * So the ordering is important here and there shouldn't be any
+ * llvm ir instrunctions in this function before
+ * this, otherwise half-float format conversions won't work
+ * (again due to llvm bug #6393).
+ */
+ if (dst_type.floating && dst_type.width != 32) {
+ /* We need to make sure that denorms are ok for half float
+ conversions */
+ fpstate = lp_build_fpstate_get(gallivm);
+ lp_build_fpstate_set_denorms_zero(gallivm, FALSE);
+ }
mask_type = lp_int32_vec4_type();
mask_type.length = fs_type.length;
@@ -1587,11 +1609,6 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
undef_src_val = lp_build_undef(gallivm, fs_type);
#endif
-
- /* Get type from output format */
- lp_blend_type_from_format_desc(out_format_desc, &row_type);
- lp_mem_type_from_format_desc(out_format_desc, &dst_type);
-
row_type.length = fs_type.length;
vector_width = dst_type.floating ? lp_native_vector_width : lp_integer_vector_width;
@@ -2051,6 +2068,10 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
dst, dst_type, dst_count, dst_alignment);
}
+ if (dst_type.floating && dst_type.width != 32) {
+ lp_build_fpstate_set(gallivm, fpstate);
+ }
+
if (do_branch) {
lp_build_mask_end(&mask_ctx);
}