diff options
Diffstat (limited to 'src/gallium/drivers/r600/r600_state_common.c')
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 160 |
1 files changed, 139 insertions, 21 deletions
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 173d96e376..78f53eb33b 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -698,6 +698,8 @@ static INLINE struct r600_shader_key r600_shader_selector_key(struct pipe_contex /* Dual-source blending only makes sense with nr_cbufs == 1. */ if (key.nr_cbufs == 1 && rctx->dual_src_blend) key.nr_cbufs = 2; + } else if (sel->type == PIPE_SHADER_VERTEX) { + key.vs_as_es = (rctx->gs_shader != NULL); } return key; } @@ -797,6 +799,12 @@ static void *r600_create_vs_state(struct pipe_context *ctx, return r600_create_shader_state(ctx, state, PIPE_SHADER_VERTEX); } +static void *r600_create_gs_state(struct pipe_context *ctx, + const struct pipe_shader_state *state) +{ + return r600_create_shader_state(ctx, state, PIPE_SHADER_GEOMETRY); +} + static void r600_bind_ps_state(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; @@ -817,6 +825,13 @@ static void r600_bind_vs_state(struct pipe_context *ctx, void *state) rctx->vs_shader = (struct r600_pipe_shader_selector *)state; } +static void r600_bind_gs_state(struct pipe_context *ctx, void *state) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + + rctx->gs_shader = (struct r600_pipe_shader_selector *)state; +} + static void r600_delete_shader_selector(struct pipe_context *ctx, struct r600_pipe_shader_selector *sel) { @@ -857,6 +872,20 @@ static void r600_delete_vs_state(struct pipe_context *ctx, void *state) r600_delete_shader_selector(ctx, sel); } + +static void r600_delete_gs_state(struct pipe_context *ctx, void *state) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + struct r600_pipe_shader_selector *sel = (struct r600_pipe_shader_selector *)state; + + if (rctx->gs_shader == sel) { + rctx->gs_shader = NULL; + } + + r600_delete_shader_selector(ctx, sel); +} + + void r600_constant_buffers_dirty(struct r600_context *rctx, struct r600_constbuf_state *state) { if (state->dirty_mask) { @@ -1149,10 +1178,65 @@ static void r600_setup_txq_cube_array_constants(struct r600_context *rctx, int s pipe_resource_reference(&cb.buffer, NULL); } +static void update_shader_atom(struct pipe_context *ctx, + struct r600_shader_state *state, + struct r600_pipe_shader *shader) +{ + state->shader = shader; + if (shader) { + state->atom.num_dw = shader->command_buffer.num_dw; + state->atom.dirty = true; + r600_context_add_resource_size(ctx, (struct pipe_resource *)shader->bo); + } else { + state->atom.num_dw = 0; + state->atom.dirty = false; + } +} + +static void update_gs_block_state(struct r600_context *rctx, unsigned enable) +{ + if (rctx->shader_stages.geom_enable != enable) { + rctx->shader_stages.geom_enable = enable; + rctx->shader_stages.atom.dirty = true; + } + + if (rctx->gs_rings.enable != enable) { + rctx->gs_rings.enable = enable; + rctx->gs_rings.atom.dirty = true; + + if (enable && !rctx->gs_rings.esgs_ring.buffer) { + unsigned size = 0x1C000; + rctx->gs_rings.esgs_ring.buffer = + pipe_buffer_create(rctx->context.screen, PIPE_BIND_CUSTOM, + PIPE_USAGE_STATIC, size); + rctx->gs_rings.esgs_ring.buffer_size = size; + + size = 0x4000000; + + rctx->gs_rings.gsvs_ring.buffer = + pipe_buffer_create(rctx->context.screen, PIPE_BIND_CUSTOM, + PIPE_USAGE_STATIC, size); + rctx->gs_rings.gsvs_ring.buffer_size = size; + } + + if (enable) { + r600_set_constant_buffer(&rctx->context, PIPE_SHADER_GEOMETRY, + R600_GS_RING_CONST_BUFFER, &rctx->gs_rings.esgs_ring); + r600_set_constant_buffer(&rctx->context, PIPE_SHADER_VERTEX, + R600_GS_RING_CONST_BUFFER, &rctx->gs_rings.gsvs_ring); + } else { + r600_set_constant_buffer(&rctx->context, PIPE_SHADER_GEOMETRY, + R600_GS_RING_CONST_BUFFER, NULL); + r600_set_constant_buffer(&rctx->context, PIPE_SHADER_VERTEX, + R600_GS_RING_CONST_BUFFER, NULL); + } + } +} + static bool r600_update_derived_state(struct r600_context *rctx) { struct pipe_context * ctx = (struct pipe_context*)rctx; - bool ps_dirty = false, vs_dirty = false; + bool ps_dirty = false, vs_dirty = false, gs_dirty = false; bool blend_disable; if (!rctx->blitter->running) { @@ -1170,22 +1254,54 @@ static bool r600_update_derived_state(struct r600_context *rctx) } } - if (unlikely(rctx->vertex_shader.shader != rctx->vs_shader)) { + update_gs_block_state(rctx, rctx->gs_shader != NULL); + + if (rctx->gs_shader) { + r600_shader_select(ctx, rctx->gs_shader, &gs_dirty); + if (unlikely(!rctx->gs_shader->current)) + return false; + + if (rctx->chip_class >= EVERGREEN && !rctx->shader_stages.geom_enable) { + rctx->shader_stages.geom_enable = true; + rctx->shader_stages.atom.dirty = true; + } + + /* gs_shader provides GS and VS (copy shader) */ + if (unlikely(rctx->geometry_shader.shader != rctx->gs_shader->current)) { + update_shader_atom(ctx, &rctx->geometry_shader, rctx->gs_shader->current); + update_shader_atom(ctx, &rctx->vertex_shader, rctx->gs_shader->current->gs_copy_shader); + } + r600_shader_select(ctx, rctx->vs_shader, &vs_dirty); + if (unlikely(!rctx->vs_shader->current)) + return false; + + /* vs_shader is used as ES */ + if (unlikely(rctx->export_shader.shader != rctx->vs_shader->current)) { + update_shader_atom(ctx, &rctx->export_shader, rctx->vs_shader->current); + } + } else { + if (unlikely(rctx->geometry_shader.shader)) { + update_shader_atom(ctx, &rctx->geometry_shader, NULL); + update_shader_atom(ctx, &rctx->export_shader, NULL); + rctx->shader_stages.geom_enable = false; + rctx->shader_stages.atom.dirty = true; + } + r600_shader_select(ctx, rctx->vs_shader, &vs_dirty); if (unlikely(!rctx->vs_shader->current)) return false; - rctx->vertex_shader.shader = rctx->vs_shader; - rctx->vertex_shader.atom.dirty = true; - r600_context_add_resource_size(ctx, (struct pipe_resource *)rctx->vs_shader->current->bo); + if (unlikely(rctx->vertex_shader.shader != rctx->vs_shader->current)) { + update_shader_atom(ctx, &rctx->vertex_shader, rctx->vs_shader->current); - /* Update clip misc state. */ - if (rctx->vs_shader->current->pa_cl_vs_out_cntl != rctx->clip_misc_state.pa_cl_vs_out_cntl || - rctx->vs_shader->current->shader.clip_dist_write != rctx->clip_misc_state.clip_dist_write) { - rctx->clip_misc_state.pa_cl_vs_out_cntl = rctx->vs_shader->current->pa_cl_vs_out_cntl; - rctx->clip_misc_state.clip_dist_write = rctx->vs_shader->current->shader.clip_dist_write; - rctx->clip_misc_state.atom.dirty = true; + /* Update clip misc state. */ + if (rctx->vs_shader->current->pa_cl_vs_out_cntl != rctx->clip_misc_state.pa_cl_vs_out_cntl || + rctx->vs_shader->current->shader.clip_dist_write != rctx->clip_misc_state.clip_dist_write) { + rctx->clip_misc_state.pa_cl_vs_out_cntl = rctx->vs_shader->current->pa_cl_vs_out_cntl; + rctx->clip_misc_state.clip_dist_write = rctx->vs_shader->current->shader.clip_dist_write; + rctx->clip_misc_state.atom.dirty = true; + } } } @@ -1193,7 +1309,7 @@ static bool r600_update_derived_state(struct r600_context *rctx) if (unlikely(!rctx->ps_shader->current)) return false; - if (unlikely(ps_dirty || rctx->pixel_shader.shader != rctx->ps_shader)) { + if (unlikely(rctx->pixel_shader.shader != rctx->ps_shader->current)) { if (rctx->cb_misc_state.nr_ps_color_outputs != rctx->ps_shader->current->nr_ps_color_outputs) { rctx->cb_misc_state.nr_ps_color_outputs = rctx->ps_shader->current->nr_ps_color_outputs; @@ -1215,9 +1331,9 @@ static bool r600_update_derived_state(struct r600_context *rctx) r600_update_db_shader_control(rctx); } - if (!ps_dirty && rctx->ps_shader && rctx->rasterizer && + if (unlikely(!ps_dirty && rctx->ps_shader && rctx->rasterizer && ((rctx->rasterizer->sprite_coord_enable != rctx->ps_shader->current->sprite_coord_enable) || - (rctx->rasterizer->flatshade != rctx->ps_shader->current->flatshade))) { + (rctx->rasterizer->flatshade != rctx->ps_shader->current->flatshade)))) { if (rctx->chip_class >= EVERGREEN) evergreen_update_ps_state(ctx, rctx->ps_shader->current); @@ -1225,11 +1341,7 @@ static bool r600_update_derived_state(struct r600_context *rctx) r600_update_ps_state(ctx, rctx->ps_shader->current); } - rctx->pixel_shader.shader = rctx->ps_shader; - rctx->pixel_shader.atom.num_dw = rctx->ps_shader->current->command_buffer.num_dw; - rctx->pixel_shader.atom.dirty = true; - r600_context_add_resource_size(ctx, - (struct pipe_resource *)rctx->ps_shader->current->bo); + update_shader_atom(ctx, &rctx->pixel_shader, rctx->ps_shader->current); } /* on R600 we stuff masks + txq info into one constant buffer */ @@ -1268,6 +1380,7 @@ static bool r600_update_derived_state(struct r600_context *rctx) rctx->blend_state.cso, blend_disable); } + return true; } @@ -1710,10 +1823,12 @@ bool sampler_state_needs_border_color(const struct pipe_sampler_state *state) void r600_emit_shader(struct r600_context *rctx, struct r600_atom *a) { struct radeon_winsys_cs *cs = rctx->rings.gfx.cs; - struct r600_pipe_shader *shader = ((struct r600_shader_state*)a)->shader->current; + struct r600_pipe_shader *shader = ((struct r600_shader_state*)a)->shader; - r600_emit_command_buffer(cs, &shader->command_buffer); + if (!shader) + return; + r600_emit_command_buffer(cs, &shader->command_buffer); r600_write_value(cs, PKT3(PKT3_NOP, 0, 0)); r600_write_value(cs, r600_context_bo_reloc(rctx, &rctx->rings.gfx, shader->bo, RADEON_USAGE_READ)); } @@ -1723,6 +1838,7 @@ void r600_init_common_state_functions(struct r600_context *rctx) { rctx->context.create_fs_state = r600_create_ps_state; rctx->context.create_vs_state = r600_create_vs_state; + rctx->context.create_gs_state = r600_create_gs_state; rctx->context.create_vertex_elements_state = r600_create_vertex_fetch_shader; rctx->context.bind_blend_state = r600_bind_blend_state; rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state; @@ -1732,6 +1848,7 @@ void r600_init_common_state_functions(struct r600_context *rctx) rctx->context.bind_vertex_elements_state = r600_bind_vertex_elements; rctx->context.bind_vertex_sampler_states = r600_bind_vs_sampler_states; rctx->context.bind_vs_state = r600_bind_vs_state; + rctx->context.bind_gs_state = r600_bind_gs_state; rctx->context.delete_blend_state = r600_delete_blend_state; rctx->context.delete_depth_stencil_alpha_state = r600_delete_dsa_state; rctx->context.delete_fs_state = r600_delete_ps_state; @@ -1739,6 +1856,7 @@ void r600_init_common_state_functions(struct r600_context *rctx) rctx->context.delete_sampler_state = r600_delete_sampler_state; rctx->context.delete_vertex_elements_state = r600_delete_vertex_elements; rctx->context.delete_vs_state = r600_delete_vs_state; + rctx->context.delete_gs_state = r600_delete_gs_state; rctx->context.set_blend_color = r600_set_blend_color; rctx->context.set_clip_state = r600_set_clip_state; rctx->context.set_constant_buffer = r600_set_constant_buffer; |