commit 7103b9ccbc5b7ab9acc6eda2046b3db58bb6645d Author: Michel Dänzer Date: Thu Sep 11 17:12:54 2014 +0900 radeonsi: Improve RASTER_CONFIG calculation for harvested cards diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 21b9c34..91ada67 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2989,15 +2989,114 @@ void si_init_state_functions(struct si_context *sctx) sctx->b.b.draw_vbo = si_draw_vbo; } -static unsigned pkr_mask_to_map(unsigned mask) -{ - switch(mask & 0x3) { - case 0x0: - case 0x1: return 0x0; - case 0x2: return 0x3; - case 0x3: return 0x2; +static void +si_write_harvested_raster_configs(struct si_context *sctx, + struct si_pm4_state *pm4, + unsigned raster_config) +{ + unsigned sh_per_se = MAX2(sctx->screen->b.info.max_sh_per_se, 1); + unsigned num_se = MAX2(sctx->screen->b.info.max_se, 1); + unsigned rb_mask = sctx->screen->b.info.si_backend_enabled_mask; + unsigned num_rb = sctx->screen->b.info.r600_num_backends; + unsigned rb_per_pkr = num_rb / num_se / sh_per_se; + unsigned rb_per_se = num_rb / num_se; + unsigned se0_mask = (1 << rb_per_se) - 1; + unsigned se1_mask = se0_mask << rb_per_se; + unsigned se; + + assert(num_se == 1 || num_se == 2); + assert(sh_per_se == 1 || sh_per_se == 2); + assert(rb_per_pkr == 1 || rb_per_pkr == 2); + + fprintf(stderr, "Original raster_config = 0x%x, rb_mask = 0x%x\n", + raster_config, rb_mask); + + /* XXX: I can't figure out what the *_XSEL and *_YSEL + * fields are for, so I'm leaving them as their default + * values. */ + + se0_mask &= rb_mask; + se1_mask &= rb_mask; + if (num_se == 2 && (!se0_mask || !se1_mask)) { + raster_config &= C_028350_SE_MAP; + + if (!se0_mask) { + raster_config |= + S_028350_SE_MAP(V_028350_RASTER_CONFIG_SE_MAP_3); + } else { + raster_config |= + S_028350_SE_MAP(V_028350_RASTER_CONFIG_SE_MAP_0); + } } - return 0; + + for (se = 0; se < num_se; se++) { + unsigned raster_config_se = raster_config; + unsigned pkr0_mask = ((1 << rb_per_pkr) - 1) << (se * rb_per_se); + unsigned pkr1_mask = pkr0_mask << rb_per_pkr; + + pkr0_mask &= rb_mask; + pkr1_mask &= rb_mask; + if (sh_per_se == 2 && (!pkr0_mask || !pkr1_mask)) { + raster_config_se &= C_028350_PKR_MAP; + + if (!pkr0_mask) { + raster_config_se |= + S_028350_PKR_MAP(V_028350_RASTER_CONFIG_PKR_MAP_3); + } else { + raster_config_se |= + S_028350_PKR_MAP(V_028350_RASTER_CONFIG_PKR_MAP_0); + } + } + + if (rb_per_pkr == 2) { + unsigned rb0_mask = 1 << (se * rb_per_se); + unsigned rb1_mask = rb0_mask << 1; + + rb0_mask &= rb_mask; + rb1_mask &= rb_mask; + if (!rb0_mask || !rb1_mask) { + raster_config_se &= C_028350_RB_MAP_PKR0; + + if (!rb0_mask) { + raster_config_se |= + S_028350_RB_MAP_PKR0(V_028350_RASTER_CONFIG_RB_MAP_3); + } else { + raster_config_se |= + S_028350_RB_MAP_PKR0(V_028350_RASTER_CONFIG_RB_MAP_0); + } + } + + if (sh_per_se == 2) { + rb0_mask = 1 << (se * rb_per_se + rb_per_pkr); + rb1_mask = rb0_mask << 1; + rb0_mask &= rb_mask; + rb1_mask &= rb_mask; + if (!rb0_mask || !rb1_mask) { + raster_config_se &= C_028350_RB_MAP_PKR1; + + if (!rb0_mask) { + raster_config_se |= + S_028350_RB_MAP_PKR1(V_028350_RASTER_CONFIG_RB_MAP_3); + } else { + raster_config_se |= + S_028350_RB_MAP_PKR1(V_028350_RASTER_CONFIG_RB_MAP_0); + } + } + } + } + + fprintf(stderr, "SE%d: raster_config = 0x%x\n", + se, raster_config_se); + + si_pm4_set_reg(pm4, GRBM_GFX_INDEX, + SE_INDEX(se) | SH_BROADCAST_WRITES | + INSTANCE_BROADCAST_WRITES); + si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, raster_config_se); + } + + si_pm4_set_reg(pm4, GRBM_GFX_INDEX, + SE_BROADCAST_WRITES | SH_BROADCAST_WRITES | + INSTANCE_BROADCAST_WRITES); } void si_init_config(struct si_context *sctx) @@ -3071,11 +3170,10 @@ void si_init_config(struct si_context *sctx) break; } } else { - unsigned raster_config = 0; - unsigned sh_per_se = MAX2(sctx->screen->b.info.max_sh_per_se, 1); - unsigned num_se = MAX2(sctx->screen->b.info.max_se, 1); unsigned rb_mask = sctx->screen->b.info.si_backend_enabled_mask; - unsigned max_backends = 2 * sh_per_se * num_se; + unsigned num_rb = sctx->screen->b.info.r600_num_backends; + unsigned raster_config; + switch (sctx->screen->b.family) { case CHIP_TAHITI: case CHIP_PITCAIRN: @@ -3091,69 +3189,19 @@ void si_init_config(struct si_context *sctx) raster_config = 0x00000000; break; default: + fprintf(stderr, + "radeonsi: Unknown GPU, using 0 for raster_config\n"); raster_config = 0x00000000; break; } /* Always use the default config when all backends are enabled. */ - if (rb_mask && util_bitcount(rb_mask) < max_backends) { - /* XXX: I can't figure out what the *_XSEL and *_YSEL - * fields are for, so I'm leaving them as their default - * values. */ - unsigned pkr_mask = (sh_per_se | 0x1); - unsigned se0_pkr0 = rb_mask & pkr_mask; - unsigned se0_pkr1 = (rb_mask >>= sh_per_se) & pkr_mask; - unsigned se1_pkr0 = (rb_mask >>= sh_per_se) & pkr_mask; - unsigned se1_pkr1 = (rb_mask >>= sh_per_se) & pkr_mask; - unsigned se_map = 0; - unsigned se0_pkr_map = 0; - unsigned se1_pkr_map = 0; - unsigned se0_pkr0_rb_map = 0; - unsigned se0_pkr1_rb_map = 0; - unsigned se1_pkr0_rb_map = 0; - unsigned se1_pkr1_rb_map = 0; - if (!se0_pkr0 && !se0_pkr1) { - /* se0 disabled */ - se_map |= 0x1; - } - if (se1_pkr0 || se1_pkr1) { - /* se1 enabled */ - se_map |= 0x2; - } - if (!se0_pkr0) { - /* se0 pkr0 disabled */ - se0_pkr_map |= 0x1; - } - if (se0_pkr1) { - /* se0 pkr1 enabled */ - se0_pkr_map |= 0x2; - } - if (!se1_pkr0) { - /* se1 pkr0 disabled */ - se1_pkr_map |= 0x1; - } - if (se1_pkr1) { - /* se1 pkr1 enabled */ - se1_pkr_map |= 0x2; - } - - se0_pkr0_rb_map = pkr_mask_to_map(se0_pkr0); - se0_pkr1_rb_map = pkr_mask_to_map(se0_pkr1); - se1_pkr0_rb_map = pkr_mask_to_map(se1_pkr0); - se1_pkr1_rb_map = pkr_mask_to_map(se1_pkr1); - - assert(!se0_pkr0 || !se1_pkr0 || (se0_pkr0_rb_map == se1_pkr0_rb_map)); - assert(!se0_pkr1 || !se1_pkr1 || (se0_pkr1_rb_map == se1_pkr1_rb_map)); - raster_config &= C_028350_RB_MAP_PKR0; - raster_config |= S_028350_RB_MAP_PKR0(se0_pkr0_rb_map); - raster_config &= C_028350_RB_MAP_PKR1; - raster_config |= S_028350_RB_MAP_PKR1(se0_pkr1_rb_map); - raster_config &= C_028350_PKR_MAP; - raster_config |= S_028350_PKR_MAP(se0_pkr_map); - raster_config &= C_028350_SE_MAP; - raster_config |= S_028350_SE_MAP(se_map); + if (rb_mask && util_bitcount(rb_mask) >= num_rb) { + si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, + raster_config); + } else { + si_write_harvested_raster_configs(sctx, pm4, raster_config); } - si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, raster_config); } si_pm4_set_reg(pm4, R_028204_PA_SC_WINDOW_SCISSOR_TL, S_028204_WINDOW_OFFSET_DISABLE(1));