d3d12: Support clip halfz

Reviewed-by: Giancarlo Devich <gdevich@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17567>
This commit is contained in:
Jesse Natalie 2022-02-07 09:49:33 -08:00 committed by Marge Bot
parent 948c03bf58
commit fccd6e275c
8 changed files with 40 additions and 15 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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