ilo: hook up pipe context 3D functions

This commit is contained in:
Chia-I Wu 2013-04-16 16:36:03 +08:00
parent 5b310f6230
commit e6186b0769
4 changed files with 287 additions and 5 deletions

View file

@ -25,17 +25,247 @@
* Chia-I Wu <olv@lunarg.com>
*/
#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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;