if (sctx->queued.named.viewport[0]) {
util_blitter_save_viewport(sctx->blitter, &sctx->queued.named.viewport[0]->viewport);
}
- if (sctx->queued.named.scissor[0]) {
- util_blitter_save_scissor(sctx->blitter, &sctx->queued.named.scissor[0]->scissor);
- }
+ util_blitter_save_scissor(sctx->blitter, &sctx->scissors.states[0]);
util_blitter_save_vertex_buffer_slot(sctx->blitter, sctx->vertex_buffer);
util_blitter_save_so_targets(sctx->blitter, sctx->b.streamout.num_targets,
(struct pipe_stream_output_target**)sctx->b.streamout.targets);
si_mark_atom_dirty(ctx, &ctx->b.streamout.enable_atom);
si_all_descriptors_begin_new_cs(ctx);
+ ctx->scissors.dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1;
+ si_mark_atom_dirty(ctx, &ctx->scissors.atom);
+
r600_postflush_resume_features(&ctx->b);
ctx->b.initial_gfx_cs_size = ctx->b.rings.gfx.cs->cdw;
return 8;
case PIPE_CAP_MAX_VIEWPORTS:
- return 16;
+ return SI_MAX_VIEWPORTS;
/* Timer queries, present when the clock frequency is non zero. */
case PIPE_CAP_QUERY_TIMESTAMP:
#define SI_IS_TRACE_POINT(x) (((x) & 0xcafe0000) == 0xcafe0000)
#define SI_GET_TRACE_POINT_ID(x) ((x) & 0xffff)
+#define SI_MAX_VIEWPORTS 16
+
struct si_compute;
struct si_screen {
unsigned export_16bpc;
};
+struct si_scissors {
+ struct r600_atom atom;
+ unsigned dirty_mask;
+ struct pipe_scissor_state states[SI_MAX_VIEWPORTS];
+};
+
#define SI_NUM_ATOMS(sctx) (sizeof((sctx)->atoms)/sizeof((sctx)->atoms.array[0]))
struct si_context {
struct r600_atom *msaa_config;
struct r600_atom *clip_regs;
struct r600_atom *shader_userdata;
+ struct r600_atom *scissors;
} s;
struct r600_atom *array[0];
} atoms;
struct r600_resource *border_color_table;
unsigned border_color_offset;
+ struct si_scissors scissors;
struct r600_atom clip_regs;
struct r600_atom msaa_sample_locs;
struct r600_atom msaa_config;
return &sctx->gs_shader->info;
else if (sctx->tes_shader)
return &sctx->tes_shader->info;
- else
+ else if (sctx->vs_shader)
return &sctx->vs_shader->info;
+ else
+ return NULL;
}
static inline struct si_shader* si_get_vs_state(struct si_context *sctx)
const struct pipe_scissor_state *state)
{
struct si_context *sctx = (struct si_context *)ctx;
- struct si_state_scissor *scissor;
- struct si_pm4_state *pm4;
int i;
- for (i = start_slot; i < start_slot + num_scissors; i++) {
- int idx = i - start_slot;
- int offset = i * 4 * 2;
+ for (i = 0; i < num_scissors; i++)
+ sctx->scissors.states[start_slot + i] = state[i];
- scissor = CALLOC_STRUCT(si_state_scissor);
- if (scissor == NULL)
- return;
- pm4 = &scissor->pm4;
- scissor->scissor = state[idx];
- si_pm4_set_reg(pm4, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset,
- S_028250_TL_X(state[idx].minx) | S_028250_TL_Y(state[idx].miny) |
- S_028250_WINDOW_OFFSET_DISABLE(1));
- si_pm4_set_reg(pm4, R_028254_PA_SC_VPORT_SCISSOR_0_BR + offset,
- S_028254_BR_X(state[idx].maxx) | S_028254_BR_Y(state[idx].maxy));
- si_pm4_set_state(sctx, scissor[i], scissor);
+ sctx->scissors.dirty_mask |= ((1 << num_scissors) - 1) << start_slot;
+ si_mark_atom_dirty(sctx, &sctx->scissors.atom);
+}
+
+static void si_emit_scissors(struct si_context *sctx, struct r600_atom *atom)
+{
+ struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
+ struct pipe_scissor_state *states = sctx->scissors.states;
+ unsigned mask = sctx->scissors.dirty_mask;
+
+ /* The simple case: Only 1 viewport is active. */
+ if (mask & 1 &&
+ !si_get_vs_info(sctx)->writes_viewport_index) {
+ r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL, 2);
+ radeon_emit(cs, S_028250_TL_X(states[0].minx) |
+ S_028250_TL_Y(states[0].miny) |
+ S_028250_WINDOW_OFFSET_DISABLE(1));
+ radeon_emit(cs, S_028254_BR_X(states[0].maxx) |
+ S_028254_BR_Y(states[0].maxy));
+ sctx->scissors.dirty_mask &= ~1; /* clear one bit */
+ return;
+ }
+
+ while (mask) {
+ int start, count, i;
+
+ u_bit_scan_consecutive_range(&mask, &start, &count);
+
+ r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL +
+ start * 4 * 2, count * 2);
+ for (i = start; i < start+count; i++) {
+ radeon_emit(cs, S_028250_TL_X(states[i].minx) |
+ S_028250_TL_Y(states[i].miny) |
+ S_028250_WINDOW_OFFSET_DISABLE(1));
+ radeon_emit(cs, S_028254_BR_X(states[i].maxx) |
+ S_028254_BR_Y(states[i].maxy));
+ }
}
+ sctx->scissors.dirty_mask = 0;
}
static void si_set_viewport_states(struct pipe_context *ctx,
si_init_atom(&sctx->framebuffer.atom, &sctx->atoms.s.framebuffer, si_emit_framebuffer_state, 0);
si_init_atom(&sctx->db_render_state, &sctx->atoms.s.db_render_state, si_emit_db_render_state, 10);
si_init_atom(&sctx->clip_regs, &sctx->atoms.s.clip_regs, si_emit_clip_regs, 6);
+ si_init_atom(&sctx->scissors.atom, &sctx->atoms.s.scissors, si_emit_scissors, 16*4);
sctx->b.b.create_blend_state = si_create_blend_state;
sctx->b.b.bind_blend_state = si_bind_blend_state;
uint16_t sample_mask;
};
-struct si_state_scissor {
- struct si_pm4_state pm4;
- struct pipe_scissor_state scissor;
-};
-
struct si_state_viewport {
struct si_pm4_state pm4;
struct pipe_viewport_state viewport;
struct si_pm4_state *blend_color;
struct si_pm4_state *clip;
struct si_state_sample_mask *sample_mask;
- struct si_state_scissor *scissor[16];
struct si_state_viewport *viewport[16];
struct si_state_rasterizer *rasterizer;
struct si_state_dsa *dsa;
return si_create_shader_state(ctx, state, PIPE_SHADER_TESS_EVAL);
}
+/**
+ * Normally, we only emit 1 viewport and 1 scissor if no shader is using
+ * the VIEWPORT_INDEX output, and emitting the other viewports and scissors
+ * is delayed. When a shader with VIEWPORT_INDEX appears, this should be
+ * called to emit the rest.
+ */
+static void si_update_viewports_and_scissors(struct si_context *sctx)
+{
+ struct tgsi_shader_info *info = si_get_vs_info(sctx);
+
+ if (!info || !info->writes_viewport_index)
+ return;
+
+ if (sctx->scissors.dirty_mask)
+ si_mark_atom_dirty(sctx, &sctx->scissors.atom);
+}
+
static void si_bind_vs_shader(struct pipe_context *ctx, void *state)
{
struct si_context *sctx = (struct si_context *)ctx;
sctx->vs_shader = sel;
si_mark_atom_dirty(sctx, &sctx->clip_regs);
+ si_update_viewports_and_scissors(sctx);
}
static void si_bind_gs_shader(struct pipe_context *ctx, void *state)
if (enable_changed)
si_shader_change_notify(sctx);
+ si_update_viewports_and_scissors(sctx);
}
static void si_bind_tcs_shader(struct pipe_context *ctx, void *state)
si_shader_change_notify(sctx);
sctx->last_tes_sh_base = -1; /* invalidate derived tess state */
}
+ si_update_viewports_and_scissors(sctx);
}
static void si_make_dummy_ps(struct si_context *sctx)