diff options
author | Adam Jackson <ajax@redhat.com> | 2021-02-24 19:20:20 -0500 |
---|---|---|
committer | Marge Bot <eric+marge@anholt.net> | 2021-02-26 19:05:34 +0000 |
commit | 5afb3b7f25db8238e8545bffbe82ed80309fe3d7 (patch) | |
tree | 0175ee6a4b9731020c565f3b714c011ee5283b38 | |
parent | 0c55a98330cc1e3b58177c47700defa5f720224e (diff) |
softpipe: Implement GL_EXT_depth_bounds_test
This is a little bit contorted because the Z storage for the tile is
either float or int depending on the Z format, so we have to be careful
about types when comparing.
Reviewed-by: Eric Anholt <eric@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9287>
-rw-r--r-- | src/gallium/drivers/softpipe/ci/softpipe-quick.txt | 1 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_quad_depth_test.c | 111 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_screen.c | 1 |
3 files changed, 103 insertions, 10 deletions
diff --git a/src/gallium/drivers/softpipe/ci/softpipe-quick.txt b/src/gallium/drivers/softpipe/ci/softpipe-quick.txt index 1fc063cff13..cf94d7e9226 100644 --- a/src/gallium/drivers/softpipe/ci/softpipe-quick.txt +++ b/src/gallium/drivers/softpipe/ci/softpipe-quick.txt @@ -1860,7 +1860,6 @@ spec/egl_nok_swap_region/basic: skip spec/egl_nok_texture_from_pixmap/basic: skip spec/ext_demote_to_helper_invocation/execution/demote: skip spec/ext_demote_to_helper_invocation/execution/demote_with_derivatives: skip -spec/ext_depth_bounds_test/depth_bounds: skip spec/ext_direct_state_access/indexed-state-queries 12/getdoublei_vext: skip spec/ext_direct_state_access/indexed-state-queries 12/getfloati_vext: skip spec/ext_direct_state_access/indexed-state-queries 12/getpointeri_vext: skip diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index 2fb2c5b5ec0..17caf75dde8 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -747,6 +747,76 @@ alpha_test_quads(struct quad_stage *qs, } +/** + * EXT_depth_bounds_test has some careful language about precision: + * + * At what precision is the depth bounds test carried out? + * + * RESOLUTION: For the purposes of the test, the bounds are converted + * to fixed-point as though they were to be written to the depth buffer, + * and the comparison uses those quantized bounds. + * + * We choose the obvious interpretation that Z32F needs no such conversion. + */ +static unsigned +depth_bounds_test_quads(struct quad_stage *qs, + struct quad_header *quads[], + unsigned nr, + struct depth_data *data) +{ + struct pipe_depth_stencil_alpha_state *dsa = qs->softpipe->depth_stencil; + unsigned i = 0, pass_nr = 0; + enum pipe_format format = util_format_get_depth_only(data->format); + double min = dsa->depth_bounds_min; + double max = dsa->depth_bounds_max; + + for (i = 0; i < nr; i++) { + unsigned j = 0, passMask = 0; + + get_depth_stencil_values(data, quads[i]); + + if (format == PIPE_FORMAT_Z32_FLOAT) { + for (j = 0; j < TGSI_QUAD_SIZE; j++) { + double z = uif(data->bzzzz[j]); + + if (z >= min && z <= max) + passMask |= (1 << j); + } + } else { + unsigned imin, imax; + + if (format == PIPE_FORMAT_Z16_UNORM) { + imin = ((unsigned) (min * 65535.0)) & 0xffff; + imax = ((unsigned) (max * 65535.0)) & 0xffff; + } else if (format == PIPE_FORMAT_Z32_UNORM) { + imin = (unsigned) (min * 4294967295.0); + imax = (unsigned) (max * 4294967295.0); + } else if (format == PIPE_FORMAT_Z24X8_UNORM || + format == PIPE_FORMAT_X8Z24_UNORM) { + imin = ((unsigned) (min * 16777215.0)) & 0xffffff; + imax = ((unsigned) (max * 16777215.0)) & 0xffffff; + } else { + unreachable("Unknown depth buffer format"); + } + + for (j = 0; j < TGSI_QUAD_SIZE; j++) { + unsigned iz = data->bzzzz[j]; + + if (iz >= imin && iz <= imax) + passMask |= (1 << j); + } + } + + quads[i]->inout.mask &= passMask; + + if (quads[i]->inout.mask) + quads[pass_nr++] = quads[i]; + } + + return pass_nr; +} + + static unsigned mask_count[16] = { 0, /* 0x0 */ @@ -781,18 +851,15 @@ depth_test_quads_fallback(struct quad_stage *qs, const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info; boolean interp_depth = !fsInfo->writes_z || qs->softpipe->early_depth; boolean shader_stencil_ref = fsInfo->writes_stencil; + boolean have_zs = !!qs->softpipe->framebuffer.zsbuf; struct depth_data data; unsigned vp_idx = quads[0]->input.viewport_index; data.use_shader_stencil_refs = FALSE; - if (qs->softpipe->depth_stencil->alpha_enabled) { - nr = alpha_test_quads(qs, quads, nr); - } - - if (qs->softpipe->framebuffer.zsbuf && - (qs->softpipe->depth_stencil->depth_enabled || - qs->softpipe->depth_stencil->stencil[0].enabled)) { + if (have_zs && (qs->softpipe->depth_stencil->depth_enabled || + qs->softpipe->depth_stencil->stencil[0].enabled || + qs->softpipe->depth_stencil->depth_bounds_test)) { float near_val, far_val; data.ps = qs->softpipe->framebuffer.zsbuf; @@ -806,7 +873,29 @@ depth_test_quads_fallback(struct quad_stage *qs, far_val = near_val + (qs->softpipe->viewports[vp_idx].scale[2] * 2.0); data.minval = MIN2(near_val, far_val); data.maxval = MAX2(near_val, far_val); + } + + /* EXT_depth_bounds_test says: + * + * Where should the depth bounds test take place in the OpenGL fragment + * processing pipeline? + * + * RESOLUTION: After scissor test, before alpha test. In practice, + * this is a logical placement of the test. An implementation is + * free to perform the test in a manner that is consistent with the + * specified ordering. + */ + + if (have_zs && qs->softpipe->depth_stencil->depth_bounds_test) { + nr = depth_bounds_test_quads(qs, quads, nr, &data); + } + if (qs->softpipe->depth_stencil->alpha_enabled) { + nr = alpha_test_quads(qs, quads, nr); + } + + if (have_zs && (qs->softpipe->depth_stencil->depth_enabled || + qs->softpipe->depth_stencil->stencil[0].enabled)) { for (i = 0; i < nr; i++) { get_depth_stencil_values(&data, quads[i]); @@ -915,6 +1004,8 @@ choose_depth_test(struct quad_stage *qs, boolean clipped = !qs->softpipe->rasterizer->depth_clip_near; + boolean depth_bounds = qs->softpipe->depth_stencil->depth_bounds_test; + if(!qs->softpipe->framebuffer.zsbuf) depth = depthwrite = stencil = FALSE; @@ -926,7 +1017,8 @@ choose_depth_test(struct quad_stage *qs, !depth && !occlusion && !clipped && - !stencil) { + !stencil && + !depth_bounds) { qs->run = depth_noop; } else if (!alpha && @@ -935,7 +1027,8 @@ choose_depth_test(struct quad_stage *qs, depthwrite && !occlusion && !clipped && - !stencil) + !stencil && + !depth_bounds) { if (qs->softpipe->framebuffer.zsbuf->format == PIPE_FORMAT_Z16_UNORM) { switch (depthfunc) { diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 68185c87f47..65b01dd8a9d 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -146,6 +146,7 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; case PIPE_CAP_DEPTH_CLIP_DISABLE: + case PIPE_CAP_DEPTH_BOUNDS_TEST: return 1; case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: return PIPE_MAX_SO_BUFFERS; |