diff options
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_interp.c | 26 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_interp.h | 2 | ||||
-rw-r--r-- | 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; |