From e84a1ab3c400f819408a7ebe01c2325cd59d94d3 Mon Sep 17 00:00:00 2001 From: Matthew McClure Date: Tue, 10 Dec 2013 13:10:03 -0800 Subject: [PATCH] llvmpipe: add plumbing for ARB_depth_clamp MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit With this patch llvmpipe will adhere to the ARB_depth_clamp enabled state when clamping the fragment's zw value. To support this, the variant key now includes the depth_clamp state. key->depth_clamp is derived from pipe_rasterizer_state's (depth_clip == 0), thus depth clamp is only enabled when depth clip is disabled. Reviewed-by: Roland Scheidegger Reviewed-by: José Fonseca --- src/gallium/drivers/llvmpipe/lp_setup.c | 11 ++- src/gallium/drivers/llvmpipe/lp_state_fs.c | 83 +++++++++++++--------- src/gallium/drivers/llvmpipe/lp_state_fs.h | 1 + src/gallium/include/pipe/p_state.h | 2 + 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 31aaf963fe9..49962af7bb2 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -656,6 +656,7 @@ lp_setup_set_viewports(struct lp_setup_context *setup, unsigned num_viewports, const struct pipe_viewport_state *viewports) { + struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); unsigned i; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -670,8 +671,14 @@ lp_setup_set_viewports(struct lp_setup_context *setup, float min_depth; float max_depth; - min_depth = viewports[i].translate[2]; - max_depth = viewports[i].translate[2] + viewports[i].scale[2]; + if (lp->rasterizer->clip_halfz == 0) { + float half_depth = viewports[i].scale[2]; + min_depth = viewports[i].translate[2] - half_depth; + max_depth = min_depth + half_depth * 2.0f; + } else { + min_depth = viewports[i].translate[2]; + max_depth = min_depth + viewports[i].scale[2]; + } if (setup->viewports[i].min_depth != min_depth || setup->viewports[i].max_depth != max_depth) { diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 93c24f6ba38..2118c1ab489 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -445,47 +445,52 @@ generate_fs_loop(struct gallivm_state *gallivm, 0); if (pos0 != -1 && outputs[pos0][2]) { - 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); + z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z"); /* - * 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. + * Clamp according to ARB_depth_clamp semantics. */ - viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm, - thread_data_ptr); + if (key->depth_clamp) { + LLVMValueRef viewport, min_depth, max_depth; + LLVMValueRef viewport_index; + struct lp_build_context f32_bld; - /* - * 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); + assert(type.floating); + lp_build_context_init(&f32_bld, gallivm, type); - /* 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); + /* + * 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); - /* 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); + /* + * 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); - z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z"); + /* 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); - /* - * Clamp to the min and max depth values for the given viewport. - */ - z = lp_build_clamp(&f32_bld, z, min_depth, max_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); + } } lp_build_depth_stencil_load_swizzled(gallivm, type, @@ -2860,6 +2865,18 @@ make_variant_key(struct llvmpipe_context *lp, } } + /* + * Propagate the depth clamp setting from the rasterizer state. + * depth_clip == 0 implies depth clamping is enabled. + * + * When clip_halfz is enabled, then always clamp the depth values. + */ + if (lp->rasterizer->clip_halfz) { + key->depth_clamp = 1; + } else { + key->depth_clamp = (lp->rasterizer->depth_clip == 0) ? 1 : 0; + } + /* alpha test only applies if render buffer 0 is non-integer (or does not exist) */ if (!lp->framebuffer.nr_cbufs || !util_format_is_pure_integer(lp->framebuffer.cbufs[0]->format)) { diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index aac45266017..2ddd8518834 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -76,6 +76,7 @@ struct lp_fragment_shader_variant_key unsigned flatshade:1; unsigned occlusion_count:1; unsigned resource_1d:1; + unsigned depth_clamp:1; enum pipe_format zsbuf_format; enum pipe_format cbuf_format[PIPE_MAX_COLOR_BUFS]; diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 29e8cc9b05f..1b5f88e3e1d 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -130,6 +130,8 @@ struct pipe_rasterizer_state /** * When true clip space in the z axis goes from [0..1] (D3D). When false * [-1, 1] (GL). + * + * NOTE: D3D will always use depth clamping. */ unsigned clip_halfz:1; -- 2.30.2