* one which will mean "unknown" for the purpose of state tracking and
* the number shouldn't be a commonly-used one. */
#define SI_BASE_VERTEX_UNKNOWN INT_MIN
+#define SI_START_INSTANCE_UNKNOWN INT_MIN
+#define SI_DRAW_ID_UNKNOWN INT_MIN
#define SI_RESTART_INDEX_UNKNOWN INT_MIN
#define SI_INSTANCE_COUNT_UNKNOWN INT_MIN
#define SI_NUM_SMOOTH_AA_SAMPLES 8
bool do_update_shaders;
bool compute_shaderbuf_sgprs_dirty;
bool compute_image_sgprs_dirty;
+ bool vs_uses_base_instance;
+ bool vs_uses_draw_id;
/* shader descriptors */
struct si_descriptors descriptors[SI_NUM_DESCS];
static inline void si_invalidate_draw_sh_constants(struct si_context *sctx)
{
sctx->last_base_vertex = SI_BASE_VERTEX_UNKNOWN;
+ sctx->last_start_instance = SI_START_INSTANCE_UNKNOWN;
+ sctx->last_drawid = SI_DRAW_ID_UNKNOWN;
}
static inline void si_invalidate_draw_constants(struct si_context *sctx)
sel->info.stage == MESA_SHADER_VERTEX &&
sel->so.num_outputs;
+ if (sel->info.stage == MESA_SHADER_VERTEX) {
+ shader->uses_base_instance = sel->info.uses_base_instance ||
+ shader->key.part.vs.prolog.instance_divisor_is_one ||
+ shader->key.part.vs.prolog.instance_divisor_is_fetched;
+ } else if (sel->info.stage == MESA_SHADER_TESS_CTRL) {
+ shader->uses_base_instance = shader->previous_stage_sel &&
+ (shader->previous_stage_sel->info.uses_base_instance ||
+ shader->key.part.tcs.ls_prolog.instance_divisor_is_one ||
+ shader->key.part.tcs.ls_prolog.instance_divisor_is_fetched);
+ } else if (sel->info.stage == MESA_SHADER_GEOMETRY) {
+ shader->uses_base_instance = shader->previous_stage_sel &&
+ (shader->previous_stage_sel->info.uses_base_instance ||
+ shader->key.part.gs.vs_prolog.instance_divisor_is_one ||
+ shader->key.part.gs.vs_prolog.instance_divisor_is_fetched);
+ }
+
si_fix_resource_usage(sscreen, shader);
si_shader_dump(sscreen, shader, debug, stderr, true);
/* Base vertex and start instance. */
base_vertex = original_index_size ? info->index_bias : draws[0].start;
+ bool set_draw_id = sctx->vs_uses_draw_id;
+ bool set_base_instance = sctx->vs_uses_base_instance;
+
if (sctx->num_vs_blit_sgprs) {
/* Re-emit draw constants after we leave u_blitter. */
si_invalidate_draw_sh_constants(sctx);
radeon_emit_array(cs, sctx->vs_blit_sh_data, sctx->num_vs_blit_sgprs);
} else if (base_vertex != sctx->last_base_vertex ||
sctx->last_base_vertex == SI_BASE_VERTEX_UNKNOWN ||
- info->start_instance != sctx->last_start_instance ||
- info->drawid != sctx->last_drawid || sh_base_reg != sctx->last_sh_base_reg) {
- radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 3);
- radeon_emit(cs, base_vertex);
- radeon_emit(cs, info->drawid);
- radeon_emit(cs, info->start_instance);
+ (set_base_instance &&
+ (info->start_instance != sctx->last_start_instance ||
+ sctx->last_start_instance == SI_START_INSTANCE_UNKNOWN)) ||
+ (set_draw_id &&
+ (info->drawid != sctx->last_drawid ||
+ sctx->last_drawid == SI_DRAW_ID_UNKNOWN)) ||
+ sh_base_reg != sctx->last_sh_base_reg) {
+ if (set_base_instance) {
+ radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 3);
+ radeon_emit(cs, base_vertex);
+ radeon_emit(cs, info->drawid);
+ radeon_emit(cs, info->start_instance);
+
+ sctx->last_start_instance = info->start_instance;
+ sctx->last_drawid = info->drawid;
+ } else if (set_draw_id) {
+ radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);
+ radeon_emit(cs, base_vertex);
+ radeon_emit(cs, info->drawid);
+
+ sctx->last_drawid = info->drawid;
+ } else {
+ radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, base_vertex);
+ }
sctx->last_base_vertex = base_vertex;
- sctx->last_start_instance = info->start_instance;
- sctx->last_drawid = info->drawid;
sctx->last_sh_base_reg = sh_base_reg;
}
+ /* Don't update draw_id in the following code if it doesn't increment. */
+ set_draw_id &= info->increment_draw_id;
+
if (index_size) {
if (dispatch_prim_discard_cs) {
for (unsigned i = 0; i < num_draws; i++) {
for (unsigned i = 0; i < num_draws; i++) {
uint64_t va = index_va + draws[i].start * index_size;
- if (i > 0 && info->increment_draw_id) {
+ if (i > 0 && set_draw_id) {
unsigned draw_id = info->drawid + i;
radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_DRAWID * 4, draw_id);
* NOT_EOP doesn't work on gfx9 and older.
*/
S_0287F0_NOT_EOP(sctx->chip_class >= GFX10 &&
- !info->increment_draw_id &&
+ !set_draw_id &&
i < num_draws - 1 &&
!(sctx->ngg_culling & SI_NGG_CULL_GS_FAST_LAUNCH_ALL)));
}
radeon_emit(cs, index_va >> 32);
if (i > 0) {
- if (info->increment_draw_id) {
+ if (set_draw_id) {
unsigned draw_id = info->drawid + i;
radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_DRAWID * 4, draw_id);
for (unsigned i = 0; i < num_draws; i++) {
if (i > 0) {
- if (info->increment_draw_id) {
+ if (set_draw_id) {
unsigned draw_id = info->drawid + i;
radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);