From 0849621891041498c7438080338ccea562440a9a Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Sat, 20 Aug 2016 04:03:11 +0200 Subject: llvmpipe: fix issues with depth clamp We only did depth clamp when the value was written from the fs. This is very wrong both for d3d10 and GL, and only passed the corresponding piglit test due to pure luck (it no longer does with the enhanced test). Also, interpolation clamped values to 1.0 always, which can legitimately happen if depth clip is disabled, so fix that as well (untested). There is one unresolved issue left, d3d10 always does depth clamping, whereas GL does not (but does [0,1] clamp instead for fs depth outputs) - this information isn't in any gallium state object, leave it as-is for now (though it looks like llvmpipe misses the [0,1] clamp as well). This (with the previous patch) fixes piglit depth-clamp-range test. Reviewed-by: Jose Fonseca --- src/gallium/drivers/llvmpipe/lp_bld_interp.c | 26 +++++- src/gallium/drivers/llvmpipe/lp_bld_interp.h | 2 + src/gallium/drivers/llvmpipe/lp_state_fs.c | 115 ++++++++++++++++----------- 3 files changed, 94 insertions(+), 49 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c index 8e4f029fc81..79325683c61 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c @@ -338,10 +338,18 @@ attribs_update_simple(struct lp_build_interp_soa_context *bld, break; } - if ((attrib == 0) && (chan == 2)){ + if ((attrib == 0) && (chan == 2) && !bld->depth_clamp){ /* FIXME: Depth values can exceed 1.0, due to the fact that * setup interpolation coefficients refer to (0,0) which causes - * precision loss. So we must clamp to 1.0 here to avoid artifacts + * precision loss. So we must clamp to 1.0 here to avoid artifacts. + * Note though values outside [0,1] are perfectly valid with + * depth clip disabled. + * XXX: If depth clip is disabled but we force depth clamp + * we may get values larger than 1.0 in the fs (but not in + * depth test). Not sure if that's an issue... + * Also, on a similar note, it is not obvious if the depth values + * appearing in fs (with depth clip disabled) should be clamped + * to [0,1], clamped to near/far or not be clamped at all... */ a = lp_build_min(coeff_bld, a, coeff_bld->one); } @@ -633,10 +641,18 @@ attribs_update(struct lp_build_interp_soa_context *bld, } #endif - if (attrib == 0 && chan == 2) { + if (attrib == 0 && chan == 2 && !bld->depth_clamp) { /* FIXME: Depth values can exceed 1.0, due to the fact that * setup interpolation coefficients refer to (0,0) which causes - * precision loss. So we must clamp to 1.0 here to avoid artifacts + * precision loss. So we must clamp to 1.0 here to avoid artifacts. + * Note though values outside [0,1] are perfectly valid with + * depth clip disabled.. + * XXX: If depth clip is disabled but we force depth clamp + * we may get values larger than 1.0 in the fs (but not in + * depth test). Not sure if that's an issue... + * Also, on a similar note, it is not obvious if the depth values + * appearing in fs (with depth clip disabled) should be clamped + * to [0,1], clamped to near/far or not be clamped at all... */ a = lp_build_min(coeff_bld, a, coeff_bld->one); } @@ -677,6 +693,7 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, unsigned num_inputs, const struct lp_shader_input *inputs, boolean pixel_center_integer, + boolean depth_clamp, LLVMBuilderRef builder, struct lp_type type, LLVMValueRef a0_ptr, @@ -738,6 +755,7 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, } else { bld->pos_offset = 0.5; } + bld->depth_clamp = depth_clamp; pos_init(bld, x0, y0); diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h index 9029d2a4180..1b9ef5e878c 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.h @@ -85,6 +85,7 @@ struct lp_build_interp_soa_context unsigned mask[1 + PIPE_MAX_SHADER_INPUTS]; /**< TGSI_WRITE_MASK_x */ enum lp_interp interp[1 + PIPE_MAX_SHADER_INPUTS]; boolean simple_interp; + boolean depth_clamp; double pos_offset; @@ -116,6 +117,7 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, unsigned num_inputs, const struct lp_shader_input *inputs, boolean pixel_center_integer, + boolean depth_clamp, LLVMBuilderRef builder, struct lp_type type, LLVMValueRef a0_ptr, diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index b1102028643..3428eed4e7c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -238,6 +238,54 @@ lp_llvm_viewport(LLVMValueRef context_ptr, } +static LLVMValueRef +lp_build_depth_clamp(struct gallivm_state *gallivm, + LLVMBuilderRef builder, + struct lp_type type, + LLVMValueRef context_ptr, + LLVMValueRef thread_data_ptr, + LLVMValueRef z) +{ + LLVMValueRef viewport, min_depth, max_depth; + LLVMValueRef viewport_index; + struct lp_build_context f32_bld; + + assert(type.floating); + lp_build_context_init(&f32_bld, gallivm, type); + + /* + * Assumes clamping of the viewport index will occur in setup/gs. Value + * is passed through the rasterization stage via lp_rast_shader_inputs. + * + * See: draw_clamp_viewport_idx and lp_clamp_viewport_idx for clamping + * semantics. + */ + viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm, + thread_data_ptr); + + /* + * Load the min and max depth from the lp_jit_context.viewports + * array of lp_jit_viewport structures. + */ + viewport = lp_llvm_viewport(context_ptr, gallivm, viewport_index); + + /* viewports[viewport_index].min_depth */ + min_depth = LLVMBuildExtractElement(builder, viewport, + lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MIN_DEPTH), ""); + min_depth = lp_build_broadcast_scalar(&f32_bld, min_depth); + + /* viewports[viewport_index].max_depth */ + max_depth = LLVMBuildExtractElement(builder, viewport, + lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MAX_DEPTH), ""); + max_depth = lp_build_broadcast_scalar(&f32_bld, max_depth); + + /* + * Clamp to the min and max depth values for the given viewport. + */ + return lp_build_clamp(&f32_bld, z, min_depth, max_depth); +} + + /** * Generate the fragment shader, depth/stencil test, and alpha tests. */ @@ -383,6 +431,13 @@ generate_fs_loop(struct gallivm_state *gallivm, z = interp->pos[2]; if (depth_mode & EARLY_DEPTH_TEST) { + /* + * Clamp according to ARB_depth_clamp semantics. + */ + if (key->depth_clamp) { + z = lp_build_depth_clamp(gallivm, builder, type, context_ptr, + thread_data_ptr, z); + } lp_build_depth_stencil_load_swizzled(gallivm, type, zs_format_desc, key->resource_1d, depth_ptr, depth_stride, @@ -471,51 +526,13 @@ generate_fs_loop(struct gallivm_state *gallivm, 0); if (pos0 != -1 && outputs[pos0][2]) { z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z"); - - /* - * Clamp according to ARB_depth_clamp semantics. - */ - if (key->depth_clamp) { - LLVMValueRef viewport, min_depth, max_depth; - LLVMValueRef viewport_index; - struct lp_build_context f32_bld; - - assert(type.floating); - lp_build_context_init(&f32_bld, gallivm, type); - - /* - * Assumes clamping of the viewport index will occur in setup/gs. Value - * is passed through the rasterization stage via lp_rast_shader_inputs. - * - * See: draw_clamp_viewport_idx and lp_clamp_viewport_idx for clamping - * semantics. - */ - viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm, - thread_data_ptr); - - /* - * Load the min and max depth from the lp_jit_context.viewports - * array of lp_jit_viewport structures. - */ - viewport = lp_llvm_viewport(context_ptr, gallivm, viewport_index); - - /* viewports[viewport_index].min_depth */ - min_depth = LLVMBuildExtractElement(builder, viewport, - lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MIN_DEPTH), - ""); - min_depth = lp_build_broadcast_scalar(&f32_bld, min_depth); - - /* viewports[viewport_index].max_depth */ - max_depth = LLVMBuildExtractElement(builder, viewport, - lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MAX_DEPTH), - ""); - max_depth = lp_build_broadcast_scalar(&f32_bld, max_depth); - - /* - * Clamp to the min and max depth values for the given viewport. - */ - z = lp_build_clamp(&f32_bld, z, min_depth, max_depth); - } + } + /* + * Clamp according to ARB_depth_clamp semantics. + */ + if (key->depth_clamp) { + z = lp_build_depth_clamp(gallivm, builder, type, context_ptr, + thread_data_ptr, z); } if (s_out != -1 && outputs[s_out][1]) { @@ -2344,6 +2361,7 @@ generate_fragment(struct llvmpipe_context *lp, shader->info.base.num_inputs, inputs, pixel_center_integer, + key->depth_clamp, builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, x, y); @@ -2949,6 +2967,13 @@ make_variant_key(struct llvmpipe_context *lp, * depth_clip == 0 implies depth clamping is enabled. * * When clip_halfz is enabled, then always clamp the depth values. + * + * XXX: This is incorrect for GL, but correct for d3d10 (depth + * clamp is always active in d3d10, regardless if depth clip is + * enabled or not). + * (GL has an always-on [0,1] clamp on fs depth output instead + * to ensure the depth values stay in range. Doesn't look like + * we do that, though...) */ if (lp->rasterizer->clip_halfz) { key->depth_clamp = 1; -- cgit v1.2.3