mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 22:00:13 +01:00
panvk: hack to improve depth clipping with small viewport depth range
Fixes 'dEQP-VK.draw.renderpass.inverted_depth_ranges.nodepthclamp_deltazero'. This is an unfortunate fix, but it's not a situation that's likely to come up in practice. The proprietary driver does something similar. Signed-off-by: Benjamin Lee <benjamin.lee@collabora.com> Co-authored-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31879>
This commit is contained in:
parent
fd5c94b8c7
commit
7ca01506c9
1 changed files with 49 additions and 6 deletions
|
|
@ -212,11 +212,18 @@ prepare_fs_driver_set(struct panvk_cmd_buffer *cmdbuf)
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
/* This value has been selected to get
|
||||
* dEQP-VK.draw.renderpass.inverted_depth_ranges.nodepthclamp_deltazero passing.
|
||||
*/
|
||||
#define MIN_DEPTH_CLIP_RANGE 37.7E-06f
|
||||
|
||||
static void
|
||||
prepare_sysvals(struct panvk_cmd_buffer *cmdbuf)
|
||||
{
|
||||
struct panvk_graphics_sysvals *sysvals = &cmdbuf->state.gfx.sysvals;
|
||||
struct vk_color_blend_state *cb = &cmdbuf->vk.dynamic_graphics_state.cb;
|
||||
const struct vk_rasterization_state *rs =
|
||||
&cmdbuf->vk.dynamic_graphics_state.rs;
|
||||
|
||||
if (is_dirty(cmdbuf, CB_BLEND_CONSTANTS)) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(cb->blend_constants); i++)
|
||||
|
|
@ -225,7 +232,8 @@ prepare_sysvals(struct panvk_cmd_buffer *cmdbuf)
|
|||
cmdbuf->state.gfx.push_uniforms = 0;
|
||||
}
|
||||
|
||||
if (is_dirty(cmdbuf, VP_VIEWPORTS)) {
|
||||
if (is_dirty(cmdbuf, VP_VIEWPORTS) || is_dirty(cmdbuf, RS_CULL_MODE) ||
|
||||
is_dirty(cmdbuf, RS_DEPTH_CLAMP_ENABLE)) {
|
||||
VkViewport *viewport = &cmdbuf->vk.dynamic_graphics_state.vp.viewports[0];
|
||||
|
||||
/* Upload the viewport scale. Defined as (px/2, py/2, pz) at the start of
|
||||
|
|
@ -251,6 +259,38 @@ prepare_sysvals(struct panvk_cmd_buffer *cmdbuf)
|
|||
sysvals->viewport.offset.x = (0.5f * viewport->width) + viewport->x;
|
||||
sysvals->viewport.offset.y = (0.5f * viewport->height) + viewport->y;
|
||||
sysvals->viewport.offset.z = viewport->minDepth;
|
||||
|
||||
/* Doing the viewport transform in the vertex shader and then depth
|
||||
* clipping with the viewport depth range gets a similar result to
|
||||
* clipping in clip-space, but loses precision when the viewport depth
|
||||
* range is very small. When minDepth == maxDepth, this completely
|
||||
* flattens the clip-space depth and results in never clipping.
|
||||
*
|
||||
* To work around this, set a lower limit on depth range when clipping is
|
||||
* enabled. This results in slightly incorrect fragment depth values, and
|
||||
* doesn't help with the precision loss, but at least clipping isn't
|
||||
* completely broken.
|
||||
*/
|
||||
if (vk_rasterization_state_depth_clip_enable(rs) &&
|
||||
fabsf(sysvals->viewport.scale.z) < MIN_DEPTH_CLIP_RANGE) {
|
||||
float z_min = viewport->minDepth;
|
||||
float z_max = viewport->maxDepth;
|
||||
float z_sign = z_min <= z_max ? 1.0f : -1.0f;
|
||||
|
||||
sysvals->viewport.scale.z = z_sign * MIN_DEPTH_CLIP_RANGE;
|
||||
|
||||
/* Middle of the user range is
|
||||
* z_range_center = z_min + (z_max - z_min) * 0.5f,
|
||||
* and we want to set the offset to
|
||||
* z_offset = z_range_center - viewport.scale.z * 0.5f
|
||||
* which, when expanding, gives us
|
||||
* z_offset = (z_max + z_min - viewport.scale.z) * 0.5f
|
||||
*/
|
||||
float z_offset = (z_max + z_min - sysvals->viewport.scale.z) * 0.5f;
|
||||
/* Bump offset off-center if necessary, to not go out of range */
|
||||
sysvals->viewport.offset.z = CLAMP(z_offset, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
cmdbuf->state.gfx.push_uniforms = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -577,11 +617,14 @@ prepare_vp(struct panvk_cmd_buffer *cmdbuf)
|
|||
cs_move64_to(b, cs_sr_reg64(b, 42), scissor_box);
|
||||
}
|
||||
|
||||
if (is_dirty(cmdbuf, VP_VIEWPORTS)) {
|
||||
cs_move32_to(b, cs_sr_reg32(b, 44),
|
||||
fui(MIN2(viewport->minDepth, viewport->maxDepth)));
|
||||
cs_move32_to(b, cs_sr_reg32(b, 45),
|
||||
fui(MAX2(viewport->minDepth, viewport->maxDepth)));
|
||||
if (is_dirty(cmdbuf, VP_VIEWPORTS) || is_dirty(cmdbuf, RS_CULL_MODE) ||
|
||||
is_dirty(cmdbuf, RS_DEPTH_CLAMP_ENABLE)) {
|
||||
struct panvk_graphics_sysvals *sysvals = &cmdbuf->state.gfx.sysvals;
|
||||
|
||||
float z_min = sysvals->viewport.offset.z;
|
||||
float z_max = z_min + sysvals->viewport.scale.z;
|
||||
cs_move32_to(b, cs_sr_reg32(b, 44), fui(MIN2(z_min, z_max)));
|
||||
cs_move32_to(b, cs_sr_reg32(b, 45), fui(MAX2(z_min, z_max)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue