diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c index a437a71d234..e27d1818105 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c @@ -827,6 +827,8 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, LLVMValueRef z_fb, LLVMValueRef s_fb, LLVMValueRef face, + LLVMValueRef min_depth_bounds, + LLVMValueRef max_depth_bounds, LLVMValueRef *z_value, LLVMValueRef *s_value, bool do_branch, @@ -841,7 +843,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, LLVMValueRef z_dst = NULL; LLVMValueRef stencil_vals = NULL; LLVMValueRef z_bitmask = NULL, stencil_shift = NULL; - LLVMValueRef z_pass = NULL, s_pass_mask = NULL; + LLVMValueRef z_pass = NULL, s_pass_mask = NULL, b_pass_mask = NULL; LLVMValueRef current_mask = mask ? lp_build_mask_value(mask) : *cov_mask; LLVMValueRef front_facing = NULL; bool have_z, have_s; @@ -883,7 +885,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, assert(z_swizzle != PIPE_SWIZZLE_NONE || s_swizzle != PIPE_SWIZZLE_NONE); - assert(depth->enabled || stencil[0].enabled); + assert(depth->enabled || depth->depth_bounds_test || stencil[0].enabled); assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); assert(format_desc->block.width == 1); @@ -1026,6 +1028,40 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, } } + if (depth->depth_bounds_test) { + if (!z_type.floating) { + struct lp_type f_type = lp_type_float_vec(32, 32 * z_type.length); + struct lp_build_context f_bld; + + lp_build_context_init(&f_bld, gallivm, f_type); + + min_depth_bounds = lp_build_max(&f_bld, + lp_build_const_vec(gallivm, f_type, 0.0f), + min_depth_bounds); + max_depth_bounds = lp_build_min(&f_bld, + lp_build_const_vec(gallivm, f_type, 1.0f), + max_depth_bounds); + + min_depth_bounds = + lp_build_clamped_float_to_unsigned_norm(gallivm, f_type, z_width, + min_depth_bounds); + max_depth_bounds = + lp_build_clamped_float_to_unsigned_norm(gallivm, f_type, z_width, + max_depth_bounds); + } + + LLVMValueRef above_min = lp_build_cmp(&z_bld, PIPE_FUNC_GEQUAL, + z_dst, min_depth_bounds); + LLVMValueRef below_max = lp_build_cmp(&z_bld, PIPE_FUNC_LEQUAL, + z_dst, max_depth_bounds); + + b_pass_mask = + LLVMBuildAnd(builder, above_min, below_max, ""); + + /* Mask off any writes that failed the depth bounds test */ + current_mask = b_pass_mask; + } + if (depth->enabled) { /* * Convert fragment Z to the desired type, aligning the LSB to the right. @@ -1112,7 +1148,7 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, stencil_refs, stencil_vals, z_pass_mask, front_facing); } - } else { + } else if (stencil[0].enabled) { /* No depth test: apply Z-pass operator to stencil buffer values which * passed the stencil test. */ @@ -1146,6 +1182,9 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, } if (mask) { + if (b_pass_mask) + lp_build_mask_update(mask, b_pass_mask); + if (s_pass_mask) lp_build_mask_update(mask, s_pass_mask); @@ -1153,6 +1192,9 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, lp_build_mask_update(mask, z_pass); } else { LLVMValueRef tmp_mask = *cov_mask; + if (b_pass_mask) + tmp_mask = LLVMBuildAnd(builder, tmp_mask, b_pass_mask, ""); + if (s_pass_mask) tmp_mask = LLVMBuildAnd(builder, tmp_mask, s_pass_mask, ""); diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h index a38dbd07d0e..9a66ad9f589 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h @@ -66,6 +66,8 @@ lp_build_depth_stencil_test(struct gallivm_state *gallivm, LLVMValueRef z_fb, LLVMValueRef s_fb, LLVMValueRef face, + LLVMValueRef min_depth_bounds, + LLVMValueRef max_depth_bounds, LLVMValueRef *z_value, LLVMValueRef *s_value, bool do_branch, diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index b29cf1a6603..7c50305372c 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -78,6 +78,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) LLVMTypeRef elem_types[LP_JIT_CTX_COUNT]; LLVMTypeRef context_type; + elem_types[LP_JIT_CTX_MIN_DEPTH_BOUNDS] = + elem_types[LP_JIT_CTX_MAX_DEPTH_BOUNDS] = elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc); elem_types[LP_JIT_CTX_SAMPLE_MASK] = elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = @@ -107,6 +109,12 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, viewports, gallivm->target, context_type, LP_JIT_CTX_VIEWPORTS); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, min_depth_bounds, + gallivm->target, context_type, + LP_JIT_CTX_MIN_DEPTH_BOUNDS); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, max_depth_bounds, + gallivm->target, context_type, + LP_JIT_CTX_MAX_DEPTH_BOUNDS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, sample_mask, gallivm->target, context_type, LP_JIT_CTX_SAMPLE_MASK); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 87cd01cdb8b..2bb26e8293a 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -85,6 +85,8 @@ struct lp_jit_context struct lp_jit_viewport *viewports; + float min_depth_bounds, max_depth_bounds; + uint32_t sample_mask; }; @@ -100,6 +102,8 @@ enum { LP_JIT_CTX_U8_BLEND_COLOR, LP_JIT_CTX_F_BLEND_COLOR, LP_JIT_CTX_VIEWPORTS, + LP_JIT_CTX_MIN_DEPTH_BOUNDS, + LP_JIT_CTX_MAX_DEPTH_BOUNDS, LP_JIT_CTX_SAMPLE_MASK, LP_JIT_CTX_COUNT }; @@ -122,6 +126,12 @@ enum { #define lp_jit_context_viewports(_gallivm, _type, _ptr) \ lp_build_struct_get2(_gallivm, _type, _ptr, LP_JIT_CTX_VIEWPORTS, "viewports") +#define lp_jit_context_min_depth_bounds(_gallivm, _type, _ptr) \ + lp_build_struct_get2(_gallivm, _type, _ptr, LP_JIT_CTX_MIN_DEPTH_BOUNDS, "min_depth_bounds") + +#define lp_jit_context_max_depth_bounds(_gallivm, _type, _ptr) \ + lp_build_struct_get2(_gallivm, _type, _ptr, LP_JIT_CTX_MAX_DEPTH_BOUNDS, "max_depth_bounds") + #define lp_jit_context_sample_mask(_gallivm, _type, _ptr) \ lp_build_struct_get_ptr2(_gallivm, _type, _ptr, LP_JIT_CTX_SAMPLE_MASK, "sample_mask") diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 14a19f9cc77..f00c57e0728 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -370,6 +370,7 @@ llvmpipe_init_screen_caps(struct pipe_screen *screen) caps->texture_multisample = true; caps->sample_shading = true; caps->gl_spirv = true; + caps->depth_bounds_test = true; caps->post_depth_coverage = true; caps->shader_clock = true; caps->packed_uniforms = true; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 4b7aebc7ba7..1962e60ef78 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -756,6 +756,21 @@ lp_setup_set_alpha_ref_value(struct lp_setup_context *setup, } } +void +lp_setup_set_depth_bounds_test_value(struct lp_setup_context *setup, + float min_depth_bounds, + float max_depth_bounds) +{ + LP_DBG(DEBUG_SETUP, "%s %f %f\n", + __func__, min_depth_bounds, max_depth_bounds); + + if (setup->fs.current.jit_context.min_depth_bounds != min_depth_bounds || + setup->fs.current.jit_context.max_depth_bounds != max_depth_bounds) { + setup->fs.current.jit_context.min_depth_bounds = min_depth_bounds; + setup->fs.current.jit_context.max_depth_bounds = max_depth_bounds; + setup->dirty |= LP_SETUP_NEW_FS; + } +} void lp_setup_set_stencil_ref_values(struct lp_setup_context *setup, diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 648d50a53ab..8c29fd1b64a 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -96,6 +96,11 @@ void lp_setup_set_alpha_ref_value(struct lp_setup_context *setup, float alpha_ref_value); +void +lp_setup_set_depth_bounds_test_value(struct lp_setup_context *setup, + float min_depth_bounds, + float max_depth_bounds); + void lp_setup_set_stencil_ref_values(struct lp_setup_context *setup, const uint8_t refs[2]); diff --git a/src/gallium/drivers/llvmpipe/lp_state_blend.c b/src/gallium/drivers/llvmpipe/lp_state_blend.c index 8a4f530a5f6..3e8a7425fb9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_state_blend.c @@ -118,6 +118,10 @@ llvmpipe_create_depth_stencil_state(struct pipe_context *pipe, state->depth_writemask = 0; state->stencil[0].enabled = 0; state->stencil[1].enabled = 0; + + state->depth_bounds_test = 0; + state->depth_bounds_min = 0.0; + state->depth_bounds_max = 1.0; } if (LP_PERF & PERF_NO_ALPHATEST) { diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index a1f5133ffe0..87d03e2625a 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -345,6 +345,9 @@ llvmpipe_update_derived(struct llvmpipe_context *llvmpipe) llvmpipe->depth_stencil->alpha_ref_value); lp_setup_set_stencil_ref_values(llvmpipe->setup, llvmpipe->stencil_ref.ref_value); + lp_setup_set_depth_bounds_test_value(llvmpipe->setup, + llvmpipe->depth_stencil->depth_bounds_min, + llvmpipe->depth_stencil->depth_bounds_max); } if (llvmpipe->dirty & LP_NEW_FS_CONSTANTS) diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 889cd7c7ab0..8abd784cdaa 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -710,6 +710,7 @@ generate_fs_loop(struct gallivm_state *gallivm, LLVMValueRef z_fb, s_fb; LLVMValueRef zs_samples = lp_build_const_int32(gallivm, key->zsbuf_nr_samples); LLVMValueRef z_out = NULL, s_out = NULL; + LLVMValueRef min_depth_bounds = NULL, max_depth_bounds = NULL; struct lp_build_for_loop_state loop_state, sample_loop_state = {0}; struct lp_build_mask_context mask; struct nir_shader *nir = shader->base.ir.nir; @@ -733,6 +734,7 @@ generate_fs_loop(struct gallivm_state *gallivm, unsigned depth_mode; const struct util_format_description *zs_format_desc = NULL; if (key->depth.enabled || + key->depth.depth_bounds_test || key->stencil[0].enabled) { zs_format_desc = util_format_description(key->zsbuf_format); @@ -930,6 +932,14 @@ generate_fs_loop(struct gallivm_state *gallivm, depth_ptr, &sample_offset, 1, ""); } + if (key->depth.depth_bounds_test) { + min_depth_bounds = lp_jit_context_min_depth_bounds(gallivm, context_type, context_ptr); + min_depth_bounds = lp_build_broadcast(gallivm, vec_type, min_depth_bounds); + + max_depth_bounds = lp_jit_context_max_depth_bounds(gallivm, context_type, context_ptr); + max_depth_bounds = lp_build_broadcast(gallivm, vec_type, max_depth_bounds); + } + if (depth_mode & EARLY_DEPTH_TEST) { z = lp_build_depth_clamp(gallivm, builder, key->depth_clamp, key->restrict_depth_values, type, @@ -950,6 +960,7 @@ generate_fs_loop(struct gallivm_state *gallivm, stencil_refs, z, z_fb, s_fb, facing, + min_depth_bounds, max_depth_bounds, &z_value, &s_value, !key->multisample, key->restrict_depth_values); @@ -1376,6 +1387,7 @@ generate_fs_loop(struct gallivm_state *gallivm, stencil_refs, z, z_fb, s_fb, facing, + min_depth_bounds, max_depth_bounds, &z_value, &s_value, false, key->restrict_depth_values); @@ -3566,7 +3578,8 @@ generate_fragment(struct llvmpipe_context *lp, bool do_branch = ((key->depth.enabled || key->stencil[0].enabled - || key->alpha.enabled) + || key->alpha.enabled + || key->depth.depth_bounds_test) && !nir->info.fs.uses_discard); color_ptr = LLVMBuildLoad2(builder, int8p_type, @@ -3876,6 +3889,7 @@ generate_variant(struct llvmpipe_context *lp, !key->multisample && !key->blend.alpha_to_coverage && !key->depth.enabled && + !key->depth.depth_bounds_test && !nir->info.fs.uses_discard && !(nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) && !nir->info.fs.uses_fbfetch_output; @@ -3946,6 +3960,7 @@ generate_variant(struct llvmpipe_context *lp, const bool linear_pipeline = !key->stencil[0].enabled && !key->depth.enabled && + !key->depth.depth_bounds_test && !nir->info.fs.uses_discard && !key->blend.logicop_enable && (key->cbuf_format[0] == PIPE_FORMAT_B8G8R8A8_UNORM || @@ -4479,12 +4494,14 @@ make_variant_key(struct llvmpipe_context *lp, const struct util_format_description *zsbuf_desc = util_format_description(zsbuf_format); - if (lp->depth_stencil->depth_enabled && + if ((lp->depth_stencil->depth_enabled || + lp->depth_stencil->depth_bounds_test) && util_format_has_depth(zsbuf_desc)) { key->zsbuf_format = zsbuf_format; key->depth.enabled = lp->depth_stencil->depth_enabled; key->depth.writemask = lp->depth_stencil->depth_writemask; key->depth.func = lp->depth_stencil->depth_func; + key->depth.depth_bounds_test = lp->depth_stencil->depth_bounds_test; } if (lp->depth_stencil->stencil[0].enabled && util_format_has_stencil(zsbuf_desc)) { diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index 74998dfffca..ae48e5bf3a4 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -63,6 +63,7 @@ struct lp_depth_state unsigned enabled:1; /**< depth test enabled? */ unsigned writemask:1; /**< allow depth buffer writes? */ unsigned func:3; /**< depth test func (PIPE_FUNC_x) */ + unsigned depth_bounds_test:1; }; struct lp_fragment_shader_variant_key