From 687c4be9cf61df18e5318f918a32e24d0a2aca0e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 26 Aug 2016 17:26:43 +0200 Subject: [PATCH] gallium/radeon: set VPORT_ZMIN/MAX registers correctly MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Calculate depth ranges from viewport states and pipe_rasterizer_state::clip_halfz. The evergreend.h change is required to silence a warning. This fixes this recently updated piglit: arb_depth_clamp/depth-clamp-range Reviewed-by: Bas Nieuwenhuizen Reviewed-by: Nicolai Hähnle --- src/gallium/drivers/r600/evergreen_state.c | 1 + src/gallium/drivers/r600/evergreend.h | 4 +- src/gallium/drivers/r600/r600_hw_context.c | 1 + src/gallium/drivers/r600/r600_pipe.h | 1 + src/gallium/drivers/r600/r600_state.c | 1 + src/gallium/drivers/r600/r600_state_common.c | 2 +- src/gallium/drivers/radeon/r600_pipe_common.h | 5 +- src/gallium/drivers/radeon/r600_viewport.c | 73 +++++++++++++++++-- src/gallium/drivers/radeon/r600d_common.h | 2 + src/gallium/drivers/radeonsi/si_hw_context.c | 1 + src/gallium/drivers/radeonsi/si_state.c | 3 +- src/gallium/drivers/radeonsi/si_state.h | 1 + 12 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 11c8161672e..5ca5453a8d7 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -473,6 +473,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx, r600_init_command_buffer(&rs->buffer, 30); rs->scissor_enable = state->scissor; + rs->clip_halfz = state->clip_halfz; rs->flatshade = state->flatshade; rs->sprite_coord_enable = state->sprite_coord_enable; rs->two_side = state->light_twoside; diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index a81b6c5fc81..40ba7c15392 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -1863,8 +1863,8 @@ #define R_0283F8_SQ_VTX_SEMANTIC_30 0x000283F8 #define R_0283FC_SQ_VTX_SEMANTIC_31 0x000283FC #define R_0288F0_SQ_VTX_SEMANTIC_CLEAR 0x000288F0 -#define R_0282D0_PA_SC_VPORT_ZMIN_0 0x000282D0 -#define R_0282D4_PA_SC_VPORT_ZMAX_0 0x000282D4 +#define R_0282D0_PA_SC_VPORT_ZMIN_0 0x0282D0 +#define R_0282D4_PA_SC_VPORT_ZMAX_0 0x0282D4 #define R_028400_VGT_MAX_VTX_INDX 0x00028400 #define R_028404_VGT_MIN_VTX_INDX 0x00028404 #define R_028408_VGT_INDX_OFFSET 0x00028408 diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index 58ba09d1014..dc5ad7537b9 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -312,6 +312,7 @@ void r600_begin_new_cs(struct r600_context *ctx) ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; r600_mark_atom_dirty(ctx, &ctx->b.scissors.atom); ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; + ctx->b.viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; r600_mark_atom_dirty(ctx, &ctx->b.viewports.atom); if (ctx->b.chip_class <= EVERGREEN) { r600_mark_atom_dirty(ctx, &ctx->config_state.atom); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index e1b2aeddf01..4403aca687a 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -276,6 +276,7 @@ struct r600_rasterizer_state { bool offset_units_unscaled; bool scissor_enable; bool multisample_enable; + bool clip_halfz; }; struct r600_poly_offset_state { diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index fb2861a2359..c8768e0343a 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -472,6 +472,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx, r600_init_command_buffer(&rs->buffer, 30); rs->scissor_enable = state->scissor; + rs->clip_halfz = state->clip_halfz; rs->flatshade = state->flatshade; rs->sprite_coord_enable = state->sprite_coord_enable; rs->two_side = state->light_twoside; diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 6f8053a069d..bb994297c11 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -366,7 +366,7 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state) r600_mark_atom_dirty(rctx, &rctx->clip_misc_state.atom); } - r600_set_scissor_enable(&rctx->b, rs->scissor_enable); + r600_viewport_set_rast_deps(&rctx->b, rs->scissor_enable, rs->clip_halfz); /* Re-emit PA_SC_LINE_STIPPLE. */ rctx->last_primitive_type = -1; diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index d821eaa6318..aa40a54f43d 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -486,6 +486,7 @@ struct r600_scissors { struct r600_viewports { struct r600_atom atom; unsigned dirty_mask; + unsigned depth_range_dirty_mask; struct pipe_viewport_state states[R600_MAX_VIEWPORTS]; struct r600_signed_scissor as_scissor[R600_MAX_VIEWPORTS]; }; @@ -537,6 +538,7 @@ struct r600_common_context { struct r600_scissors scissors; struct r600_viewports viewports; bool scissor_enabled; + bool clip_halfz; bool vs_writes_viewport_index; bool vs_disables_clipping_viewport; @@ -793,7 +795,8 @@ void r600_init_context_texture_functions(struct r600_common_context *rctx); /* r600_viewport.c */ void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx, struct pipe_scissor_state *scissor); -void r600_set_scissor_enable(struct r600_common_context *rctx, bool enable); +void r600_viewport_set_rast_deps(struct r600_common_context *rctx, + bool scissor_enable, bool clip_halfz); void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx, struct tgsi_shader_info *info); void r600_init_viewport_functions(struct r600_common_context *rctx); diff --git a/src/gallium/drivers/radeon/r600_viewport.c b/src/gallium/drivers/radeon/r600_viewport.c index 2d6878391da..2de13820545 100644 --- a/src/gallium/drivers/radeon/r600_viewport.c +++ b/src/gallium/drivers/radeon/r600_viewport.c @@ -22,6 +22,7 @@ */ #include "r600_cs.h" +#include "util/u_viewport.h" #include "tgsi/tgsi_scan.h" #define GET_MAX_SCISSOR(rctx) (rctx->chip_class >= EVERGREEN ? 16384 : 8192) @@ -260,6 +261,7 @@ static void r600_set_viewport_states(struct pipe_context *ctx, const struct pipe_viewport_state *state) { struct r600_common_context *rctx = (struct r600_common_context *)ctx; + unsigned mask; int i; for (i = 0; i < num_viewports; i++) { @@ -270,8 +272,10 @@ static void r600_set_viewport_states(struct pipe_context *ctx, &rctx->viewports.as_scissor[index]); } - rctx->viewports.dirty_mask |= ((1 << num_viewports) - 1) << start_slot; - rctx->scissors.dirty_mask |= ((1 << num_viewports) - 1) << start_slot; + mask = ((1 << num_viewports) - 1) << start_slot; + rctx->viewports.dirty_mask |= mask; + rctx->viewports.depth_range_dirty_mask |= mask; + rctx->scissors.dirty_mask |= mask; rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true); rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true); } @@ -289,7 +293,7 @@ static void r600_emit_one_viewport(struct r600_common_context *rctx, radeon_emit(cs, fui(state->translate[2])); } -static void r600_emit_viewports(struct r600_common_context *rctx, struct r600_atom *atom) +static void r600_emit_viewports(struct r600_common_context *rctx) { struct radeon_winsys_cs *cs = rctx->gfx.cs; struct pipe_viewport_state *states = rctx->viewports.states; @@ -319,13 +323,64 @@ static void r600_emit_viewports(struct r600_common_context *rctx, struct r600_at rctx->viewports.dirty_mask = 0; } -void r600_set_scissor_enable(struct r600_common_context *rctx, bool enable) +static void r600_emit_depth_ranges(struct r600_common_context *rctx) { - if (rctx->scissor_enabled != enable) { - rctx->scissor_enabled = enable; + struct radeon_winsys_cs *cs = rctx->gfx.cs; + struct pipe_viewport_state *states = rctx->viewports.states; + unsigned mask = rctx->viewports.depth_range_dirty_mask; + float zmin, zmax; + + /* The simple case: Only 1 viewport is active. */ + if (!rctx->vs_writes_viewport_index) { + if (!(mask & 1)) + return; + + util_viewport_zmin_zmax(&states[0], rctx->clip_halfz, &zmin, &zmax); + + radeon_set_context_reg_seq(cs, R_0282D0_PA_SC_VPORT_ZMIN_0, 2); + radeon_emit(cs, fui(zmin)); + radeon_emit(cs, fui(zmax)); + rctx->viewports.depth_range_dirty_mask &= ~1; /* clear one bit */ + return; + } + + while (mask) { + int start, count, i; + + u_bit_scan_consecutive_range(&mask, &start, &count); + + radeon_set_context_reg_seq(cs, R_0282D0_PA_SC_VPORT_ZMIN_0 + + start * 4 * 2, count * 2); + for (i = start; i < start+count; i++) { + util_viewport_zmin_zmax(&states[i], rctx->clip_halfz, &zmin, &zmax); + radeon_emit(cs, fui(zmin)); + radeon_emit(cs, fui(zmax)); + } + } + rctx->viewports.depth_range_dirty_mask = 0; +} + +static void r600_emit_viewport_states(struct r600_common_context *rctx, + struct r600_atom *atom) +{ + r600_emit_viewports(rctx); + r600_emit_depth_ranges(rctx); +} + +/* Set viewport dependencies on pipe_rasterizer_state. */ +void r600_viewport_set_rast_deps(struct r600_common_context *rctx, + bool scissor_enable, bool clip_halfz) +{ + if (rctx->scissor_enabled != scissor_enable) { + rctx->scissor_enabled = scissor_enable; rctx->scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true); } + if (rctx->clip_halfz != clip_halfz) { + rctx->clip_halfz = clip_halfz; + rctx->viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; + rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true); + } } /** @@ -359,14 +414,16 @@ void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx, if (rctx->scissors.dirty_mask) rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true); - if (rctx->viewports.dirty_mask) + + if (rctx->viewports.dirty_mask || + rctx->viewports.depth_range_dirty_mask) rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true); } void r600_init_viewport_functions(struct r600_common_context *rctx) { rctx->scissors.atom.emit = r600_emit_scissors; - rctx->viewports.atom.emit = r600_emit_viewports; + rctx->viewports.atom.emit = r600_emit_viewport_states; rctx->scissors.atom.num_dw = (2 + 16 * 2) + 6; rctx->viewports.atom.num_dw = 2 + 16 * 6; diff --git a/src/gallium/drivers/radeon/r600d_common.h b/src/gallium/drivers/radeon/r600d_common.h index 6f534b3e5cd..3dbe43a8b56 100644 --- a/src/gallium/drivers/radeon/r600d_common.h +++ b/src/gallium/drivers/radeon/r600d_common.h @@ -246,5 +246,7 @@ #define S_028254_BR_Y(x) (((unsigned)(x) & 0x7FFF) << 16) #define G_028254_BR_Y(x) (((x) >> 16) & 0x7FFF) #define C_028254_BR_Y 0x8000FFFF +#define R_0282D0_PA_SC_VPORT_ZMIN_0 0x0282D0 +#define R_0282D4_PA_SC_VPORT_ZMAX_0 0x0282D4 #endif diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c index aeccb2d85f2..a03b3275d04 100644 --- a/src/gallium/drivers/radeonsi/si_hw_context.c +++ b/src/gallium/drivers/radeonsi/si_hw_context.c @@ -213,6 +213,7 @@ void si_begin_new_cs(struct si_context *ctx) ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; + ctx->b.viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; si_mark_atom_dirty(ctx, &ctx->b.scissors.atom); si_mark_atom_dirty(ctx, &ctx->b.viewports.atom); diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index f54b0bcc3a8..60ba3f6e8b3 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -733,6 +733,7 @@ static void *si_create_rs_state(struct pipe_context *ctx, } rs->scissor_enable = state->scissor; + rs->clip_halfz = state->clip_halfz; rs->two_side = state->light_twoside; rs->multisample_enable = state->multisample; rs->force_persample_interp = state->force_persample_interp; @@ -872,7 +873,7 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state) si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs.atom); } - r600_set_scissor_enable(&sctx->b, rs->scissor_enable); + r600_viewport_set_rast_deps(&sctx->b, rs->scissor_enable, rs->clip_halfz); si_pm4_bind_state(sctx, rasterizer, rs); si_update_poly_offset_state(sctx); diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h index f4f75758dbf..d0e519c4994 100644 --- a/src/gallium/drivers/radeonsi/si_state.h +++ b/src/gallium/drivers/radeonsi/si_state.h @@ -76,6 +76,7 @@ struct si_state_rasterizer { bool clamp_fragment_color; bool rasterizer_discard; bool scissor_enable; + bool clip_halfz; }; struct si_dsa_stencil_ref_part { -- 2.30.2