diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index c0b057cc334..904267da1bd 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -908,7 +908,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_RASTERIZER; if (state->flatshade_first) prov_vtx = 0; - tmp = S_0286D4_FLAT_SHADE_ENA(state->flatshade); + tmp = S_0286D4_FLAT_SHADE_ENA(1); if (state->sprite_coord_enable) { tmp |= S_0286D4_PNT_SPRITE_ENA(1) | S_0286D4_PNT_SPRITE_OVRD_X(2) | @@ -2246,7 +2246,7 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader int pos_index = -1, face_index = -1; int ninterp = 0; boolean have_linear = FALSE, have_centroid = FALSE, have_perspective = FALSE; - unsigned spi_baryc_cntl, sid, tmp, idx = 0; + unsigned spi_baryc_cntl; rstate->nregs = 0; @@ -2267,31 +2267,7 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader if (rshader->input[i].centroid) have_centroid = TRUE; } - - sid = rshader->input[i].spi_sid; - - if (sid) { - - tmp = S_028644_SEMANTIC(sid); - - if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || - rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || - rshader->input[i].name == TGSI_SEMANTIC_POSITION) { - tmp |= S_028644_FLAT_SHADE(1); - } - - if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && - rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { - tmp |= S_028644_PT_SPRITE_TEX(1); - } - - r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + idx * 4, - tmp, 0xFFFFFFFF, NULL, 0); - - idx++; - } } - for (i = 0; i < rshader->noutput; i++) { if (rshader->output[i].name == TGSI_SEMANTIC_POSITION) db_shader_control |= S_02880C_Z_EXPORT_ENABLE(1); @@ -2392,8 +2368,6 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader r600_pipe_state_add_reg(rstate, R_03A200_SQ_LOOP_CONST_0, 0x01000FFF, 0xFFFFFFFF, NULL, 0); - - shader->sprite_coord_enable = rctx->sprite_coord_enable; } void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *shader) diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 92cb34dacad..330e3202bab 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -68,6 +68,7 @@ enum r600_pipe_state_id { R600_PIPE_STATE_RESOURCE, R600_PIPE_STATE_POLYGON_OFFSET, R600_PIPE_STATE_FETCH_SHADER, + R600_PIPE_STATE_SPI, R600_PIPE_NSTATES }; @@ -132,7 +133,6 @@ struct r600_pipe_shader { struct r600_resource *bo_fetch; struct r600_vertex_element vertex_elements; struct tgsi_token *tokens; - unsigned sprite_coord_enable; }; struct r600_pipe_sampler_state { @@ -215,7 +215,9 @@ struct r600_pipe_context { /* shader information */ boolean clamp_vertex_color; boolean clamp_fragment_color; + boolean spi_dirty; unsigned sprite_coord_enable; + boolean flatshade; boolean export_16bpc; unsigned alpha_ref; boolean alpha_ref_dirty; diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 863a7a4ba5a..ce65da668df 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -958,7 +958,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_RASTERIZER; if (state->flatshade_first) prov_vtx = 0; - tmp = S_0286D4_FLAT_SHADE_ENA(state->flatshade); + tmp = S_0286D4_FLAT_SHADE_ENA(1); if (state->sprite_coord_enable) { tmp |= S_0286D4_PNT_SPRITE_ENA(1) | S_0286D4_PNT_SPRITE_OVRD_X(2) | @@ -2049,7 +2049,6 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad struct r600_shader *rshader = &shader->shader; unsigned i, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1, db_shader_control; int pos_index = -1, face_index = -1; - unsigned tmp, sid; rstate->nregs = 0; @@ -2058,30 +2057,6 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad pos_index = i; if (rshader->input[i].name == TGSI_SEMANTIC_FACE) face_index = i; - - sid = rshader->input[i].spi_sid; - - tmp = S_028644_SEMANTIC(sid); - - if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || - rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || - rshader->input[i].name == TGSI_SEMANTIC_POSITION) { - tmp |= S_028644_FLAT_SHADE(1); - } - - if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && - rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { - tmp |= S_028644_PT_SPRITE_TEX(1); - } - - if (rshader->input[i].centroid) - tmp |= S_028644_SEL_CENTROID(1); - - if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR) - tmp |= S_028644_SEL_LINEAR(1); - - r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, - tmp, 0xFFFFFFFF, NULL, 0); } db_shader_control = 0; @@ -2159,8 +2134,6 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad r600_pipe_state_add_reg(rstate, R_03E200_SQ_LOOP_CONST_0, 0x01000FFF, 0xFFFFFFFF, NULL, 0); - - shader->sprite_coord_enable = rctx->sprite_coord_enable; } void r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *shader) diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index b81fba10467..3d0345addce 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -34,6 +34,8 @@ #include "r600_pipe.h" #include "r600d.h" +static void r600_spi_update(struct r600_pipe_context *rctx); + static bool r600_conv_pipe_prim(unsigned pprim, unsigned *prim) { static const int prim_conv[] = { @@ -101,9 +103,8 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state) rctx->clamp_vertex_color = rs->clamp_vertex_color; rctx->clamp_fragment_color = rs->clamp_fragment_color; - + rctx->flatshade = rs->flatshade; rctx->sprite_coord_enable = rs->sprite_coord_enable; - rctx->rasterizer = rs; rctx->states[rs->rstate.id] = &rs->rstate; @@ -114,6 +115,8 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state) } else { r600_polygon_offset_update(rctx); } + if (rctx->ps_shader && rctx->vs_shader) + rctx->spi_dirty = true; } void r600_delete_rs_state(struct pipe_context *ctx, void *state) @@ -277,6 +280,7 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state) r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate); } if (rctx->ps_shader && rctx->vs_shader) { + rctx->spi_dirty = true; r600_adjust_gprs(rctx); } } @@ -291,6 +295,7 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state) r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate); } if (rctx->ps_shader && rctx->vs_shader) { + rctx->spi_dirty = true; r600_adjust_gprs(rctx); } } @@ -338,6 +343,63 @@ static void r600_update_alpha_ref(struct r600_pipe_context *rctx) rctx->alpha_ref_dirty = false; } +/* FIXME optimize away spi update when it's not needed */ +static void r600_spi_block_init(struct r600_pipe_context *rctx, struct r600_pipe_state *rstate) +{ + int i; + rstate->nregs = 0; + rstate->id = R600_PIPE_STATE_SPI; + for (i = 0; i < 32; i++) { + r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, 0, 0xFFFFFFFF, NULL, 0); + } +} + +static void r600_spi_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_shader *shader = rctx->ps_shader; + struct r600_pipe_state *rstate = &rctx->spi; + struct r600_shader *rshader = &shader->shader; + unsigned i, tmp, sid; + + if (rctx->spi.id == 0) + r600_spi_block_init(rctx, &rctx->spi); + + rstate->nregs = 0; + for (i = 0; i < rshader->ninput; i++) { + + sid = rshader->input[i].spi_sid; + + if (!sid && (rctx->chip_class >= EVERGREEN)) + continue; + + tmp = S_028644_SEMANTIC(sid); + + if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || + rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || + rshader->input[i].name == TGSI_SEMANTIC_POSITION) { + tmp |= S_028644_FLAT_SHADE(rctx->flatshade); + } + + if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && + rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { + tmp |= S_028644_PT_SPRITE_TEX(1); + } + + if (rctx->chip_class < EVERGREEN) { + if (rshader->input[i].centroid) + tmp |= S_028644_SEL_CENTROID(1); + + if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR) + tmp |= S_028644_SEL_LINEAR(1); + } + + r600_pipe_state_mod_reg(rstate, tmp); + } + + rctx->spi_dirty = false; + r600_context_pipe_state_set(&rctx->ctx, rstate); +} + void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, struct pipe_resource *buffer) { @@ -490,8 +552,6 @@ static int r600_shader_rebuild(struct pipe_context * ctx, struct r600_pipe_shade static void r600_update_derived_state(struct r600_pipe_context *rctx) { - struct pipe_context * ctx = (struct pipe_context*)rctx; - if (!rctx->blitter->running) { if (rctx->have_depth_fb || rctx->have_depth_texture) r600_flush_depth_textures(rctx); @@ -511,21 +571,13 @@ static void r600_update_derived_state(struct r600_pipe_context *rctx) r600_shader_rebuild(&rctx->context, rctx->ps_shader); } + if (rctx->spi_dirty) { + r600_spi_update(rctx); + } + if (rctx->alpha_ref_dirty) { r600_update_alpha_ref(rctx); } - - if (rctx->ps_shader && rctx->sprite_coord_enable && - (rctx->ps_shader->sprite_coord_enable != rctx->sprite_coord_enable)) { - - if (rctx->chip_class >= EVERGREEN) - evergreen_pipe_shader_ps(ctx, rctx->ps_shader); - else - r600_pipe_shader_ps(ctx, rctx->ps_shader); - - r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate); - } - } void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)