lp: Implement gallium depth_bounds_test capability
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Support for this capability in llvmpipe expose
support for GL_EXT_depth_bounds_test, as well as supporting
the `depthBounds` device feature in lavapipe.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36487>
This commit is contained in:
Lucas Fryzek 2025-07-29 14:13:04 -04:00 committed by Marge Bot
parent 36b0fdb7b7
commit b75b0ce7b2
11 changed files with 113 additions and 5 deletions

View file

@ -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, "");

View file

@ -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,

View file

@ -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);

View file

@ -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")

View file

@ -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;

View file

@ -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,

View file

@ -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]);

View file

@ -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) {

View file

@ -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)

View file

@ -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)) {

View file

@ -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