Mesa (main): d3d12: Support clip halfz
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Jul 22 00:17:40 UTC 2022
Module: Mesa
Branch: main
Commit: fccd6e275c3278a5abe814e9a0e535ffca436243
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=fccd6e275c3278a5abe814e9a0e535ffca436243
Author: Jesse Natalie <jenatali at microsoft.com>
Date: Mon Feb 7 09:49:33 2022 -0800
d3d12: Support clip halfz
Reviewed-by: Giancarlo Devich <gdevich at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17567>
---
docs/features.txt | 2 +-
src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt | 7 ++-----
src/gallium/drivers/d3d12/d3d12_compiler.cpp | 10 +++++++---
src/gallium/drivers/d3d12/d3d12_compiler.h | 1 +
src/gallium/drivers/d3d12/d3d12_context.cpp | 18 +++++++++++++++++-
src/gallium/drivers/d3d12/d3d12_nir_passes.c | 14 ++++++++++----
src/gallium/drivers/d3d12/d3d12_nir_passes.h | 2 +-
src/gallium/drivers/d3d12/d3d12_screen.cpp | 1 +
8 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/docs/features.txt b/docs/features.txt
index 47ba684337e..56b8adacdf2 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -213,7 +213,7 @@ GL 4.4, GLSL 4.40 -- all DONE: i965/gen8+, nvc0, r600, radeonsi, llvmpipe, zink
GL 4.5, GLSL 4.50 -- all DONE: nvc0, r600, radeonsi, llvmpipe, zink
GL_ARB_ES3_1_compatibility DONE (i965/hsw+, softpipe, virgl)
- GL_ARB_clip_control DONE (freedreno, i965, nv50, softpipe, virgl, lima)
+ GL_ARB_clip_control DONE (freedreno, i965, nv50, softpipe, virgl, lima, d3d12)
GL_ARB_conditional_render_inverted DONE (freedreno, i965, nv50, softpipe, virgl, panfrost, d3d12)
GL_ARB_cull_distance DONE (freedreno/a6xx, i965, nv50, softpipe, virgl)
GL_ARB_derivative_control DONE (i965, nv50, softpipe, virgl)
diff --git a/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt b/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt
index c6dbead427b..61c1d393f9f 100644
--- a/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt
+++ b/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt
@@ -319,9 +319,6 @@ spec/arb_clear_texture/arb_clear_texture-sized-formats: skip
spec/arb_clear_texture/arb_clear_texture-srgb: skip
spec/arb_clear_texture/arb_clear_texture-stencil: skip
spec/arb_clear_texture/arb_clear_texture-texview: skip
-spec/arb_clip_control/arb_clip_control-clip-control: skip
-spec/arb_clip_control/arb_clip_control-depth-precision: skip
-spec/arb_clip_control/arb_clip_control-viewport: skip
spec/arb_compute_shader/compute-and-render-bug-109630: fail
spec/arb_copy_image/arb_copy_image-api_errors: skip
spec/arb_copy_image/arb_copy_image-format-swizzle: skip
@@ -3515,10 +3512,10 @@ wgl/wgl-sanity: skip
summary:
name: results
---- --------
- pass: 17870
+ pass: 17873
fail: 2035
crash: 12
- skip: 1448
+ skip: 1445
timeout: 0
warn: 10
incomplete: 0
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
index b88255b1368..d6f9620bedc 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
@@ -123,8 +123,9 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
if (key->last_vertex_processing_stage) {
if (key->invert_depth)
- NIR_PASS_V(nir, d3d12_nir_invert_depth, key->invert_depth);
- NIR_PASS_V(nir, nir_lower_clip_halfz);
+ NIR_PASS_V(nir, d3d12_nir_invert_depth, key->invert_depth, key->halfz);
+ if (!key->halfz)
+ NIR_PASS_V(nir, nir_lower_clip_halfz);
NIR_PASS_V(nir, d3d12_lower_yflip);
}
NIR_PASS_V(nir, nir_lower_packed_ubo_loads);
@@ -790,7 +791,8 @@ d3d12_compare_shader_keys(const d3d12_shader_key *expect, const d3d12_shader_key
expect->n_images * sizeof(struct d3d12_image_format_conversion_info)))
return false;
- if (expect->invert_depth != have->invert_depth)
+ if (expect->invert_depth != have->invert_depth ||
+ expect->halfz != have->halfz)
return false;
if (expect->stage == PIPE_SHADER_VERTEX) {
@@ -930,6 +932,8 @@ d3d12_fill_shader_key(struct d3d12_selection_context *sel_ctx,
(!next || next->stage == PIPE_SHADER_FRAGMENT))) {
key->last_vertex_processing_stage = 1;
key->invert_depth = sel_ctx->ctx->reverse_depth_range;
+ key->halfz = sel_ctx->ctx->gfx_pipeline_state.rast ?
+ sel_ctx->ctx->gfx_pipeline_state.rast->base.clip_halfz : false;
if (sel_ctx->ctx->pstipple.enabled &&
sel_ctx->ctx->gfx_pipeline_state.rast->base.poly_stipple_enable)
key->next_varying_inputs |= VARYING_BIT_POS;
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.h b/src/gallium/drivers/d3d12/d3d12_compiler.h
index aed79f95c1e..20298e2353f 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.h
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.h
@@ -92,6 +92,7 @@ struct d3d12_shader_key {
uint64_t prev_varying_outputs;
unsigned last_vertex_processing_stage : 1;
unsigned invert_depth : 16;
+ unsigned halfz : 1;
unsigned samples_int_textures : 1;
unsigned input_clip_size : 4;
unsigned tex_saturate_s : PIPE_MAX_SAMPLERS;
diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context.cpp
index 1b84a68d23f..fa4ab2dffca 100644
--- a/src/gallium/drivers/d3d12/d3d12_context.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_context.cpp
@@ -1313,9 +1313,25 @@ d3d12_set_viewport_states(struct pipe_context *pctx,
ctx->viewports[start_slot + i].TopLeftX = state[i].translate[0] - state[i].scale[0];
ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2;
- float near_depth = state[i].translate[2] - state[i].scale[2];
+ float near_depth = state[i].translate[2];
float far_depth = state[i].translate[2] + state[i].scale[2];
+ /* When the rasterizer is configured for "full" depth clipping ([-1, 1])
+ * the viewport that we get is set to cover the positive half of clip space.
+ * E.g. a [0, 1] viewport from the GL API will come to the driver as [0.5, 1].
+ * Since we halve clipping space from [-1, 1] to [0, 1], we need to double the
+ * viewport, treating translate as the center instead of the near plane. When
+ * the rasterizer is configured for "half" depth clipping ([0, 1]), the viewport
+ * covers the entire clip range, so no fixup is needed.
+ *
+ * Note: If halfz mode changes, both the rasterizer and viewport are dirtied,
+ * and on the next draw we will get the rasterizer state first, and viewport
+ * second, because ST_NEW_RASTERIZER comes before ST_NEW_VIEWPORT.
+ */
+ if (ctx->gfx_pipeline_state.rast && !ctx->gfx_pipeline_state.rast->base.clip_halfz) {
+ near_depth -= state[i].scale[2];
+ }
+
bool reverse_depth_range = near_depth > far_depth;
if (reverse_depth_range) {
float tmp = near_depth;
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.c b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
index 9dddadaf9ee..3859abf955d 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.c
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
@@ -391,6 +391,7 @@ d3d12_lower_load_patch_vertices_in(struct nir_shader *nir)
struct invert_depth_state
{
unsigned viewport_mask;
+ bool clip_halfz;
nir_ssa_def *viewport_index;
nir_instr *store_pos_instr;
};
@@ -415,10 +416,14 @@ invert_depth_impl(nir_builder *b, struct invert_depth_state *state)
if (state->viewport_index) {
nir_push_if(b, nir_test_mask(b, nir_ishl(b, nir_imm_int(b, 1), state->viewport_index), state->viewport_mask));
}
+ nir_ssa_def *old_depth = nir_channel(b, pos, 2);
+ nir_ssa_def *new_depth = nir_fneg(b, old_depth);
+ if (state->clip_halfz)
+ new_depth = nir_fadd_imm(b, new_depth, 1.0);
nir_ssa_def *def = nir_vec4(b,
nir_channel(b, pos, 0),
nir_channel(b, pos, 1),
- nir_fneg(b, nir_channel(b, pos, 2)),
+ new_depth,
nir_channel(b, pos, 3));
if (state->viewport_index) {
nir_pop_if(b, NULL);
@@ -453,19 +458,20 @@ invert_depth_instr(nir_builder *b, struct nir_instr *instr, struct invert_depth_
}
/* In OpenGL the windows space depth value z_w is evaluated according to "s * z_d + b"
- * with "s + (far - near) / 2" (depth clip:minus_one_to_one) [OpenGL 3.3, 2.13.1].
+ * with "s = (far - near) / 2" (depth clip:minus_one_to_one) [OpenGL 3.3, 2.13.1].
* When we switch the far and near value to satisfy DirectX requirements we have
* to compensate by inverting "z_d' = -z_d" with this lowering pass.
+ * When depth clip is set zero_to_one, we compensate with "z_d' = 1.0f - z_d" instead.
*/
void
-d3d12_nir_invert_depth(nir_shader *shader, unsigned viewport_mask)
+d3d12_nir_invert_depth(nir_shader *shader, unsigned viewport_mask, bool clip_halfz)
{
if (shader->info.stage != MESA_SHADER_VERTEX &&
shader->info.stage != MESA_SHADER_TESS_EVAL &&
shader->info.stage != MESA_SHADER_GEOMETRY)
return;
- struct invert_depth_state state = { viewport_mask };
+ struct invert_depth_state state = { viewport_mask, clip_halfz };
nir_foreach_function(function, shader) {
if (function->impl) {
nir_builder b;
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.h b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
index 818b12abf31..62034f0b85f 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.h
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
@@ -88,7 +88,7 @@ bool
d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask);
void
-d3d12_nir_invert_depth(nir_shader *s, unsigned viewport_mask);
+d3d12_nir_invert_depth(nir_shader *s, unsigned viewport_mask, bool clip_halfz);
bool
nir_lower_packed_ubo_loads(struct nir_shader *nir);
diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp
index 88f8209709a..11dc0c35b2d 100644
--- a/src/gallium/drivers/d3d12/d3d12_screen.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp
@@ -329,6 +329,7 @@ d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_MEMOBJ:
case PIPE_CAP_FENCE_SIGNAL:
case PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT:
+ case PIPE_CAP_CLIP_HALFZ:
return 1;
case PIPE_CAP_MAX_VERTEX_STREAMS:
More information about the mesa-commit
mailing list