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:
@@ -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 4.5, GLSL 4.50 -- all DONE: nvc0, r600, radeonsi, llvmpipe, zink
|
||||||
|
|
||||||
GL_ARB_ES3_1_compatibility DONE (i965/hsw+, softpipe, virgl)
|
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_conditional_render_inverted DONE (freedreno, i965, nv50, softpipe, virgl, panfrost, d3d12)
|
||||||
GL_ARB_cull_distance DONE (freedreno/a6xx, i965, nv50, softpipe, virgl)
|
GL_ARB_cull_distance DONE (freedreno/a6xx, i965, nv50, softpipe, virgl)
|
||||||
GL_ARB_derivative_control DONE (i965, nv50, softpipe, virgl)
|
GL_ARB_derivative_control DONE (i965, nv50, softpipe, virgl)
|
||||||
|
@@ -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-srgb: skip
|
||||||
spec/arb_clear_texture/arb_clear_texture-stencil: skip
|
spec/arb_clear_texture/arb_clear_texture-stencil: skip
|
||||||
spec/arb_clear_texture/arb_clear_texture-texview: 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_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-api_errors: skip
|
||||||
spec/arb_copy_image/arb_copy_image-format-swizzle: skip
|
spec/arb_copy_image/arb_copy_image-format-swizzle: skip
|
||||||
@@ -3515,10 +3512,10 @@ wgl/wgl-sanity: skip
|
|||||||
summary:
|
summary:
|
||||||
name: results
|
name: results
|
||||||
---- --------
|
---- --------
|
||||||
pass: 17870
|
pass: 17873
|
||||||
fail: 2035
|
fail: 2035
|
||||||
crash: 12
|
crash: 12
|
||||||
skip: 1448
|
skip: 1445
|
||||||
timeout: 0
|
timeout: 0
|
||||||
warn: 10
|
warn: 10
|
||||||
incomplete: 0
|
incomplete: 0
|
||||||
|
@@ -123,7 +123,8 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
|
|||||||
|
|
||||||
if (key->last_vertex_processing_stage) {
|
if (key->last_vertex_processing_stage) {
|
||||||
if (key->invert_depth)
|
if (key->invert_depth)
|
||||||
NIR_PASS_V(nir, d3d12_nir_invert_depth, key->invert_depth);
|
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, nir_lower_clip_halfz);
|
||||||
NIR_PASS_V(nir, d3d12_lower_yflip);
|
NIR_PASS_V(nir, d3d12_lower_yflip);
|
||||||
}
|
}
|
||||||
@@ -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)))
|
expect->n_images * sizeof(struct d3d12_image_format_conversion_info)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (expect->invert_depth != have->invert_depth)
|
if (expect->invert_depth != have->invert_depth ||
|
||||||
|
expect->halfz != have->halfz)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (expect->stage == PIPE_SHADER_VERTEX) {
|
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))) {
|
(!next || next->stage == PIPE_SHADER_FRAGMENT))) {
|
||||||
key->last_vertex_processing_stage = 1;
|
key->last_vertex_processing_stage = 1;
|
||||||
key->invert_depth = sel_ctx->ctx->reverse_depth_range;
|
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 &&
|
if (sel_ctx->ctx->pstipple.enabled &&
|
||||||
sel_ctx->ctx->gfx_pipeline_state.rast->base.poly_stipple_enable)
|
sel_ctx->ctx->gfx_pipeline_state.rast->base.poly_stipple_enable)
|
||||||
key->next_varying_inputs |= VARYING_BIT_POS;
|
key->next_varying_inputs |= VARYING_BIT_POS;
|
||||||
|
@@ -92,6 +92,7 @@ struct d3d12_shader_key {
|
|||||||
uint64_t prev_varying_outputs;
|
uint64_t prev_varying_outputs;
|
||||||
unsigned last_vertex_processing_stage : 1;
|
unsigned last_vertex_processing_stage : 1;
|
||||||
unsigned invert_depth : 16;
|
unsigned invert_depth : 16;
|
||||||
|
unsigned halfz : 1;
|
||||||
unsigned samples_int_textures : 1;
|
unsigned samples_int_textures : 1;
|
||||||
unsigned input_clip_size : 4;
|
unsigned input_clip_size : 4;
|
||||||
unsigned tex_saturate_s : PIPE_MAX_SAMPLERS;
|
unsigned tex_saturate_s : PIPE_MAX_SAMPLERS;
|
||||||
|
@@ -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].TopLeftX = state[i].translate[0] - state[i].scale[0];
|
||||||
ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2;
|
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];
|
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;
|
bool reverse_depth_range = near_depth > far_depth;
|
||||||
if (reverse_depth_range) {
|
if (reverse_depth_range) {
|
||||||
float tmp = near_depth;
|
float tmp = near_depth;
|
||||||
|
@@ -391,6 +391,7 @@ d3d12_lower_load_patch_vertices_in(struct nir_shader *nir)
|
|||||||
struct invert_depth_state
|
struct invert_depth_state
|
||||||
{
|
{
|
||||||
unsigned viewport_mask;
|
unsigned viewport_mask;
|
||||||
|
bool clip_halfz;
|
||||||
nir_ssa_def *viewport_index;
|
nir_ssa_def *viewport_index;
|
||||||
nir_instr *store_pos_instr;
|
nir_instr *store_pos_instr;
|
||||||
};
|
};
|
||||||
@@ -415,10 +416,14 @@ invert_depth_impl(nir_builder *b, struct invert_depth_state *state)
|
|||||||
if (state->viewport_index) {
|
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_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_ssa_def *def = nir_vec4(b,
|
||||||
nir_channel(b, pos, 0),
|
nir_channel(b, pos, 0),
|
||||||
nir_channel(b, pos, 1),
|
nir_channel(b, pos, 1),
|
||||||
nir_fneg(b, nir_channel(b, pos, 2)),
|
new_depth,
|
||||||
nir_channel(b, pos, 3));
|
nir_channel(b, pos, 3));
|
||||||
if (state->viewport_index) {
|
if (state->viewport_index) {
|
||||||
nir_pop_if(b, NULL);
|
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"
|
/* 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
|
* 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.
|
* 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
|
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 &&
|
if (shader->info.stage != MESA_SHADER_VERTEX &&
|
||||||
shader->info.stage != MESA_SHADER_TESS_EVAL &&
|
shader->info.stage != MESA_SHADER_TESS_EVAL &&
|
||||||
shader->info.stage != MESA_SHADER_GEOMETRY)
|
shader->info.stage != MESA_SHADER_GEOMETRY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct invert_depth_state state = { viewport_mask };
|
struct invert_depth_state state = { viewport_mask, clip_halfz };
|
||||||
nir_foreach_function(function, shader) {
|
nir_foreach_function(function, shader) {
|
||||||
if (function->impl) {
|
if (function->impl) {
|
||||||
nir_builder b;
|
nir_builder b;
|
||||||
|
@@ -88,7 +88,7 @@ bool
|
|||||||
d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask);
|
d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask);
|
||||||
|
|
||||||
void
|
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
|
bool
|
||||||
nir_lower_packed_ubo_loads(struct nir_shader *nir);
|
nir_lower_packed_ubo_loads(struct nir_shader *nir);
|
||||||
|
@@ -329,6 +329,7 @@ d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
|
|||||||
case PIPE_CAP_MEMOBJ:
|
case PIPE_CAP_MEMOBJ:
|
||||||
case PIPE_CAP_FENCE_SIGNAL:
|
case PIPE_CAP_FENCE_SIGNAL:
|
||||||
case PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT:
|
case PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT:
|
||||||
|
case PIPE_CAP_CLIP_HALFZ:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case PIPE_CAP_MAX_VERTEX_STREAMS:
|
case PIPE_CAP_MAX_VERTEX_STREAMS:
|
||||||
|
Reference in New Issue
Block a user