diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_3d.c | 238 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_3d.h | 35 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_context.c | 17 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_context.h | 2 |
4 files changed, 287 insertions, 5 deletions
diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c index afe6323300f..9d01c92def7 100644 --- a/src/gallium/drivers/ilo/ilo_3d.c +++ b/src/gallium/drivers/ilo/ilo_3d.c @@ -25,17 +25,247 @@ * Chia-I Wu <[email protected]> */ +#include "intel_winsys.h" + +#include "ilo_3d_pipeline.h" #include "ilo_context.h" +#include "ilo_cp.h" +#include "ilo_query.h" +#include "ilo_shader.h" +#include "ilo_state.h" #include "ilo_3d.h" /** + * Hook for CP new-batch. + */ +void +ilo_3d_new_cp_batch(struct ilo_3d *hw3d) +{ + hw3d->new_batch = true; + + /* invalidate the pipeline */ + ilo_3d_pipeline_invalidate(hw3d->pipeline, + ILO_3D_PIPELINE_INVALIDATE_BATCH_BO | + ILO_3D_PIPELINE_INVALIDATE_STATE_BO); + if (!hw3d->cp->hw_ctx) { + ilo_3d_pipeline_invalidate(hw3d->pipeline, + ILO_3D_PIPELINE_INVALIDATE_HW); + } +} + +/** + * Hook for CP pre-flush. + */ +void +ilo_3d_pre_cp_flush(struct ilo_3d *hw3d) +{ +} + +/** + * Hook for CP post-flush + */ +void +ilo_3d_post_cp_flush(struct ilo_3d *hw3d) +{ + if (ilo_debug & ILO_DEBUG_3D) + ilo_3d_pipeline_dump(hw3d->pipeline); +} + +/** + * Create a 3D context. + */ +struct ilo_3d * +ilo_3d_create(struct ilo_cp *cp, int gen, int gt) +{ + struct ilo_3d *hw3d; + + hw3d = CALLOC_STRUCT(ilo_3d); + if (!hw3d) + return NULL; + + hw3d->cp = cp; + hw3d->new_batch = true; + + hw3d->pipeline = ilo_3d_pipeline_create(cp, gen, gt); + if (!hw3d->pipeline) { + FREE(hw3d); + return NULL; + } + + return hw3d; +} + +/** + * Destroy a 3D context. + */ +void +ilo_3d_destroy(struct ilo_3d *hw3d) +{ + ilo_3d_pipeline_destroy(hw3d->pipeline); + FREE(hw3d); +} + +static bool +draw_vbo(struct ilo_3d *hw3d, const struct ilo_context *ilo, + const struct pipe_draw_info *info, + int *prim_generated, int *prim_emitted) +{ + bool need_flush; + int max_len; + + ilo_cp_set_ring(hw3d->cp, ILO_CP_RING_RENDER); + + /* + * Without a better tracking mechanism, when the framebuffer changes, we + * have to assume that the old framebuffer may be sampled from. If that + * happens in the middle of a batch buffer, we need to insert manual + * flushes. + */ + need_flush = (!hw3d->new_batch && (ilo->dirty & ILO_DIRTY_FRAMEBUFFER)); + + /* make sure there is enough room first */ + max_len = ilo_3d_pipeline_estimate_size(hw3d->pipeline, + ILO_3D_PIPELINE_DRAW, ilo); + if (need_flush) { + max_len += ilo_3d_pipeline_estimate_size(hw3d->pipeline, + ILO_3D_PIPELINE_FLUSH, NULL); + } + + if (max_len > ilo_cp_space(hw3d->cp)) { + ilo_cp_flush(hw3d->cp); + need_flush = false; + assert(max_len <= ilo_cp_space(hw3d->cp)); + } + + if (need_flush) + ilo_3d_pipeline_emit_flush(hw3d->pipeline); + + return ilo_3d_pipeline_emit_draw(hw3d->pipeline, ilo, info, + prim_generated, prim_emitted); +} + +static bool +pass_render_condition(struct ilo_3d *hw3d, struct pipe_context *pipe) +{ + uint64_t result; + bool wait; + + if (!hw3d->render_condition.query) + return true; + + switch (hw3d->render_condition.mode) { + case PIPE_RENDER_COND_WAIT: + case PIPE_RENDER_COND_BY_REGION_WAIT: + wait = true; + break; + case PIPE_RENDER_COND_NO_WAIT: + case PIPE_RENDER_COND_BY_REGION_NO_WAIT: + default: + wait = false; + break; + } + + if (pipe->get_query_result(pipe, hw3d->render_condition.query, + wait, (union pipe_query_result *) &result)) { + return (result > 0); + } + else { + return true; + } +} + +static void +ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_3d *hw3d = ilo->hw3d; + int prim_generated, prim_emitted; + + if (!pass_render_condition(hw3d, pipe)) + return; + + /* assume the cache is still in use by the previous batch */ + if (hw3d->new_batch) + ilo_shader_cache_mark_busy(ilo->shader_cache); + + ilo_finalize_states(ilo); + + /* the shaders may be uploaded to a new shader cache */ + if (hw3d->shader_cache_seqno != ilo->shader_cache->seqno) { + ilo_3d_pipeline_invalidate(hw3d->pipeline, + ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO); + } + + /* + * The VBs and/or IB may have different BOs due to being mapped with + * PIPE_TRANSFER_DISCARD_x. We should track that instead of setting the + * dirty flags for the performance reason. + */ + ilo->dirty |= ILO_DIRTY_VERTEX_BUFFERS | ILO_DIRTY_INDEX_BUFFER; + + if (!draw_vbo(hw3d, ilo, info, &prim_generated, &prim_emitted)) + return; + + /* clear dirty status */ + ilo->dirty = 0x0; + hw3d->new_batch = false; + hw3d->shader_cache_seqno = ilo->shader_cache->seqno; + + if (ilo_debug & ILO_DEBUG_NOCACHE) + ilo_3d_pipeline_emit_flush(hw3d->pipeline); +} + +static void +ilo_render_condition(struct pipe_context *pipe, + struct pipe_query *query, + uint mode) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_3d *hw3d = ilo->hw3d; + + /* reference count? */ + hw3d->render_condition.query = query; + hw3d->render_condition.mode = mode; +} + +static void +ilo_texture_barrier(struct pipe_context *pipe) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_3d *hw3d = ilo->hw3d; + + if (ilo->cp->ring != ILO_CP_RING_RENDER) + return; + + ilo_3d_pipeline_emit_flush(hw3d->pipeline); + + /* don't know why */ + if (ilo->gen >= ILO_GEN(7)) + ilo_cp_flush(hw3d->cp); +} + +static void +ilo_get_sample_position(struct pipe_context *pipe, + unsigned sample_count, + unsigned sample_index, + float *out_value) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_3d *hw3d = ilo->hw3d; + + ilo_3d_pipeline_get_sample_position(hw3d->pipeline, + sample_count, sample_index, + &out_value[0], &out_value[1]); +} + +/** * Initialize 3D-related functions. */ void ilo_init_3d_functions(struct ilo_context *ilo) { - ilo->base.draw_vbo = NULL; - ilo->base.render_condition = NULL; - ilo->base.texture_barrier = NULL; - ilo->base.get_sample_position = NULL; + ilo->base.draw_vbo = ilo_draw_vbo; + ilo->base.render_condition = ilo_render_condition; + ilo->base.texture_barrier = ilo_texture_barrier; + ilo->base.get_sample_position = ilo_get_sample_position; } diff --git a/src/gallium/drivers/ilo/ilo_3d.h b/src/gallium/drivers/ilo/ilo_3d.h index ba098cb451c..c9b7bc9ea85 100644 --- a/src/gallium/drivers/ilo/ilo_3d.h +++ b/src/gallium/drivers/ilo/ilo_3d.h @@ -30,7 +30,42 @@ #include "ilo_common.h" +struct ilo_3d_pipeline; struct ilo_context; +struct ilo_cp; +struct ilo_query; + +/** + * 3D context. + */ +struct ilo_3d { + struct ilo_cp *cp; + + bool new_batch; + uint32_t shader_cache_seqno; + + struct { + struct pipe_query *query; + unsigned mode; + } render_condition; + + struct ilo_3d_pipeline *pipeline; +}; + +struct ilo_3d * +ilo_3d_create(struct ilo_cp *cp, int gen, int gt); + +void +ilo_3d_destroy(struct ilo_3d *hw3d); + +void +ilo_3d_new_cp_batch(struct ilo_3d *hw3d); + +void +ilo_3d_pre_cp_flush(struct ilo_3d *hw3d); + +void +ilo_3d_post_cp_flush(struct ilo_3d *hw3d); void ilo_init_3d_functions(struct ilo_context *ilo); diff --git a/src/gallium/drivers/ilo/ilo_context.c b/src/gallium/drivers/ilo/ilo_context.c index 82da56e7196..880c9c1a7ba 100644 --- a/src/gallium/drivers/ilo/ilo_context.c +++ b/src/gallium/drivers/ilo/ilo_context.c @@ -43,11 +43,19 @@ static void ilo_context_new_cp_batch(struct ilo_cp *cp, void *data) { + struct ilo_context *ilo = ilo_context(data); + + if (cp->ring == ILO_CP_RING_RENDER) + ilo_3d_new_cp_batch(ilo->hw3d); } static void ilo_context_pre_cp_flush(struct ilo_cp *cp, void *data) { + struct ilo_context *ilo = ilo_context(data); + + if (cp->ring == ILO_CP_RING_RENDER) + ilo_3d_pre_cp_flush(ilo->hw3d); } static void @@ -61,6 +69,9 @@ ilo_context_post_cp_flush(struct ilo_cp *cp, void *data) /* remember the just flushed bo, on which fences could wait */ ilo->last_cp_bo = cp->bo; ilo->last_cp_bo->reference(ilo->last_cp_bo); + + if (cp->ring == ILO_CP_RING_RENDER) + ilo_3d_post_cp_flush(ilo->hw3d); } static void @@ -103,6 +114,8 @@ ilo_context_destroy(struct pipe_context *pipe) if (ilo->blitter) util_blitter_destroy(ilo->blitter); + if (ilo->hw3d) + ilo_3d_destroy(ilo->hw3d); if (ilo->shader_cache) ilo_shader_cache_destroy(ilo->shader_cache); if (ilo->cp) @@ -177,8 +190,10 @@ ilo_context_create(struct pipe_screen *screen, void *priv) ilo->cp = ilo_cp_create(ilo->winsys, is->has_llc); ilo->shader_cache = ilo_shader_cache_create(ilo->winsys); + if (ilo->cp) + ilo->hw3d = ilo_3d_create(ilo->cp, ilo->gen, ilo->gt); - if (!ilo->cp || !ilo->shader_cache) { + if (!ilo->cp || !ilo->shader_cache || !ilo->hw3d) { ilo_context_destroy(&ilo->base); return NULL; } diff --git a/src/gallium/drivers/ilo/ilo_context.h b/src/gallium/drivers/ilo/ilo_context.h index 58fee1f1821..695f6f4d29a 100644 --- a/src/gallium/drivers/ilo/ilo_context.h +++ b/src/gallium/drivers/ilo/ilo_context.h @@ -57,6 +57,7 @@ struct blitter_context; struct intel_winsys; struct intel_bo; +struct ilo_3d; struct ilo_cp; struct ilo_screen; struct ilo_shader_state; @@ -87,6 +88,7 @@ struct ilo_context { struct intel_bo *last_cp_bo; struct ilo_shader_cache *shader_cache; + struct ilo_3d *hw3d; struct blitter_context *blitter; uint32_t dirty; |