X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Ffreedreno_context.h;h=f92790c0ecf4353f526c51454fee7935184f29a7;hb=b3efa2a4da206112f6c9b5adb2df37c2efe646e6;hp=733c64b18070be22ada8b0d46e35f0ea8954a854;hpb=4299849ec7a873edf46a3a366749282fdec020fe;p=mesa.git diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 733c64b1807..f92790c0ecf 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -1,5 +1,3 @@ -/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ - /* * Copyright (C) 2012 Rob Clark * @@ -52,31 +50,33 @@ struct fd_texture_stateobj { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; unsigned num_samplers; unsigned valid_samplers; + /* number of samples per sampler, 2 bits per sampler: */ + uint32_t samples; }; struct fd_program_stateobj { - void *vp, *fp; - - /* rest only used by fd2.. split out: */ - uint8_t num_exports; - /* Indexed by semantic name or TGSI_SEMANTIC_COUNT + semantic index - * for TGSI_SEMANTIC_GENERIC. Special vs exports (position and point- - * size) are not included in this - */ - uint8_t export_linkage[63]; + void *vs, *hs, *ds, *gs, *fs; }; struct fd_constbuf_stateobj { struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS]; uint32_t enabled_mask; - uint32_t dirty_mask; +}; + +struct fd_shaderbuf_stateobj { + struct pipe_shader_buffer sb[PIPE_MAX_SHADER_BUFFERS]; + uint32_t enabled_mask; +}; + +struct fd_shaderimg_stateobj { + struct pipe_image_view si[PIPE_MAX_SHADER_IMAGES]; + uint32_t enabled_mask; }; struct fd_vertexbuf_stateobj { struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; unsigned count; uint32_t enabled_mask; - uint32_t dirty_mask; }; struct fd_vertex_stateobj { @@ -86,6 +86,9 @@ struct fd_vertex_stateobj { struct fd_streamout_stateobj { struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; + /* Bitmask of stream that should be reset. */ + unsigned reset; + unsigned num_targets; /* Track offset from vtxcnt for streamout data. This counter * is just incremented by # of vertices on each draw until @@ -98,6 +101,12 @@ struct fd_streamout_stateobj { unsigned offsets[PIPE_MAX_SO_BUFFERS]; }; +#define MAX_GLOBAL_BUFFERS 16 +struct fd_global_bindings_stateobj { + struct pipe_resource *buf[MAX_GLOBAL_BUFFERS]; + uint32_t enabled_mask; +}; + /* group together the vertex and vertexbuf state.. for ease of passing * around, and because various internal operations (gmem<->mem, etc) * need their own vertex state: @@ -120,7 +129,8 @@ enum fd_dirty_3d_state { FD_DIRTY_VIEWPORT = BIT(8), FD_DIRTY_VTXSTATE = BIT(9), FD_DIRTY_VTXBUF = BIT(10), - FD_DIRTY_INDEXBUF = BIT(11), + FD_DIRTY_MIN_SAMPLES = BIT(11), + FD_DIRTY_SCISSOR = BIT(12), FD_DIRTY_STREAMOUT = BIT(13), FD_DIRTY_UCP = BIT(14), @@ -142,15 +152,26 @@ enum fd_dirty_shader_state { FD_DIRTY_SHADER_PROG = BIT(0), FD_DIRTY_SHADER_CONST = BIT(1), FD_DIRTY_SHADER_TEX = BIT(2), + FD_DIRTY_SHADER_SSBO = BIT(3), + FD_DIRTY_SHADER_IMAGE = BIT(4), }; struct fd_context { struct pipe_context base; + /* We currently need to serialize emitting GMEM batches, because of + * VSC state access in the context. + * + * In practice this lock should not be contended, since pipe_context + * use should be single threaded. But it is needed to protect the + * case, with batch reordering where a ctxB batch triggers flushing + * a ctxA batch + */ + mtx_t gmem_lock; + struct fd_device *dev; struct fd_screen *screen; - - struct util_queue flush_queue; + struct fd_pipe *pipe; struct blitter_context *blitter; void *clear_rs_state; @@ -159,15 +180,26 @@ struct fd_context { /* slab for pipe_transfer allocations: */ struct slab_child_pool transfer_pool; + /** + * query related state: + */ + /*@{*/ /* slabs for fd_hw_sample and fd_hw_sample_period allocations: */ struct slab_mempool sample_pool; struct slab_mempool sample_period_pool; /* sample-providers for hw queries: */ - const struct fd_hw_sample_provider *sample_providers[MAX_HW_SAMPLE_PROVIDERS]; + const struct fd_hw_sample_provider *hw_sample_providers[MAX_HW_SAMPLE_PROVIDERS]; /* list of active queries: */ - struct list_head active_queries; + struct list_head hw_active_queries; + + /* sample-providers for accumulating hw queries: */ + const struct fd_acc_sample_provider *acc_sample_providers[MAX_HW_SAMPLE_PROVIDERS]; + + /* list of active accumulating queries: */ + struct list_head acc_active_queries; + /*@}*/ /* table with PIPE_PRIM_MAX entries mapping PIPE_PRIM_x to * DI_PT_x value to use for draw initiator. There are some @@ -189,7 +221,9 @@ struct fd_context { uint64_t prims_emitted; uint64_t prims_generated; uint64_t draw_calls; - uint64_t batch_total, batch_sysmem, batch_gmem, batch_restore; + uint64_t batch_total, batch_sysmem, batch_gmem, batch_nondraw, batch_restore; + uint64_t staging_uploads, shadow_uploads; + uint64_t vs_regs, hs_regs, ds_regs, gs_regs, fs_regs; } stats; /* Current batch.. the rule here is that you can deref ctx->batch @@ -200,8 +234,20 @@ struct fd_context { */ struct fd_batch *batch; + /* NULL if there has been rendering since last flush. Otherwise + * keeps a reference to the last fence so we can re-use it rather + * than having to flush no-op batch. + */ struct pipe_fence_handle *last_fence; + /* track last known reset status globally and per-context to + * determine if more resets occurred since then. If global reset + * count increases, it means some other context crashed. If + * per-context reset count increases, it means we crashed the + * gpu. + */ + uint32_t context_reset_count, global_reset_count; + /* Are we in process of shadowing a resource? Used to detect recursion * in transfer_map, and skip unneeded synchronization. */ @@ -221,15 +267,8 @@ struct fd_context { */ struct pipe_scissor_state disabled_scissor; - /* Current gmem/tiling configuration.. gets updated on render_tiles() - * if out of date with current maximal-scissor/cpp: - * - * (NOTE: this is kind of related to the batch, but moving it there - * means we'd always have to recalc tiles ever batch) - */ - struct fd_gmem_stateobj gmem; - struct fd_vsc_pipe pipe[8]; - struct fd_tile tile[512]; + /* Per vsc pipe bo's (a2xx-a5xx): */ + struct fd_bo *vsc_pipe_bo[32]; /* which state objects need to be re-emit'd: */ enum fd_dirty_3d_state dirty; @@ -237,6 +276,7 @@ struct fd_context { /* per shader-stage dirty status: */ enum fd_dirty_shader_state dirty_shader[PIPE_SHADER_TYPES]; + void *compute; struct pipe_blend_state *blend; struct pipe_rasterizer_state *rasterizer; struct pipe_depth_stencil_alpha_state *zsa; @@ -250,11 +290,17 @@ struct fd_context { struct pipe_blend_color blend_color; struct pipe_stencil_ref stencil_ref; unsigned sample_mask; + unsigned min_samples; + /* local context fb state, for when ctx->batch is null: */ + struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple stipple; struct pipe_viewport_state viewport; + struct pipe_scissor_state viewport_scissor; struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; - struct pipe_index_buffer indexbuf; + struct fd_shaderbuf_stateobj shaderbuf[PIPE_SHADER_TYPES]; + struct fd_shaderimg_stateobj shaderimg[PIPE_SHADER_TYPES]; struct fd_streamout_stateobj streamout; + struct fd_global_bindings_stateobj global_bindings; struct pipe_clip_state ucp; struct pipe_query *cond_query; @@ -265,10 +311,11 @@ struct fd_context { /* GMEM/tile handling fxns: */ void (*emit_tile_init)(struct fd_batch *batch); - void (*emit_tile_prep)(struct fd_batch *batch, struct fd_tile *tile); - void (*emit_tile_mem2gmem)(struct fd_batch *batch, struct fd_tile *tile); - void (*emit_tile_renderprep)(struct fd_batch *batch, struct fd_tile *tile); - void (*emit_tile_gmem2mem)(struct fd_batch *batch, struct fd_tile *tile); + void (*emit_tile_prep)(struct fd_batch *batch, const struct fd_tile *tile); + void (*emit_tile_mem2gmem)(struct fd_batch *batch, const struct fd_tile *tile); + void (*emit_tile_renderprep)(struct fd_batch *batch, const struct fd_tile *tile); + void (*emit_tile)(struct fd_batch *batch, const struct fd_tile *tile); + void (*emit_tile_gmem2mem)(struct fd_batch *batch, const struct fd_tile *tile); void (*emit_tile_fini)(struct fd_batch *batch); /* optional */ /* optional, for GMEM bypass: */ @@ -276,20 +323,26 @@ struct fd_context { void (*emit_sysmem_fini)(struct fd_batch *batch); /* draw: */ - bool (*draw_vbo)(struct fd_context *ctx, const struct pipe_draw_info *info); - void (*clear)(struct fd_context *ctx, unsigned buffers, + bool (*draw_vbo)(struct fd_context *ctx, const struct pipe_draw_info *info, + unsigned index_offset); + bool (*clear)(struct fd_context *ctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil); - /* constant emit: (note currently not used/needed for a2xx) */ - void (*emit_const)(struct fd_ringbuffer *ring, enum shader_t type, - uint32_t regid, uint32_t offset, uint32_t sizedwords, - const uint32_t *dwords, struct pipe_resource *prsc); - /* emit bo addresses as constant: */ - void (*emit_const_bo)(struct fd_ringbuffer *ring, enum shader_t type, boolean write, - uint32_t regid, uint32_t num, struct pipe_resource **prscs, uint32_t *offsets); + /* compute: */ + void (*launch_grid)(struct fd_context *ctx, const struct pipe_grid_info *info); + + /* query: */ + struct fd_query * (*create_query)(struct fd_context *ctx, unsigned query_type, unsigned index); + void (*query_prepare)(struct fd_batch *batch, uint32_t num_tiles); + void (*query_prepare_tile)(struct fd_batch *batch, uint32_t n, + struct fd_ringbuffer *ring); + void (*query_set_stage)(struct fd_batch *batch, enum fd_render_stage stage); + + /* blitter: */ + bool (*blit)(struct fd_context *ctx, const struct pipe_blit_info *info); - /* indirect-branch emit: */ - void (*emit_ib)(struct fd_ringbuffer *ring, struct fd_ringbuffer *target); + /* handling for barriers: */ + void (*framebuffer_barrier)(struct fd_context *ctx); /* * Common pre-cooked VBO state (used for a3xx and later): @@ -311,6 +364,20 @@ struct fd_context { * - solid_vbuf / 12 / R32G32B32_FLOAT */ struct fd_vertex_state blit_vbuf_state; + + /* + * Info about state of previous draw, for state that comes from + * pipe_draw_info (ie. not part of a CSO). This allows us to + * skip some register emit when the state doesn't change from + * draw-to-draw + */ + struct { + bool dirty; /* last draw state unknown */ + bool primitive_restart; + uint32_t index_start; + uint32_t instance_start; + uint32_t restart_index; + } last; }; static inline struct fd_context * @@ -341,6 +408,7 @@ fd_context_unlock(struct fd_context *ctx) static inline void fd_context_all_dirty(struct fd_context *ctx) { + ctx->last.dirty = true; ctx->dirty = ~0; for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) ctx->dirty_shader[i] = ~0; @@ -350,8 +418,16 @@ static inline void fd_context_all_clean(struct fd_context *ctx) { ctx->dirty = 0; - for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) + for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) { + /* don't mark compute state as clean, since it is not emitted + * during normal draw call. The places that call _all_dirty(), + * it is safe to mark compute state dirty as well, but the + * inverse is not true. + */ + if (i == PIPE_SHADER_COMPUTE) + continue; ctx->dirty_shader[i] = 0; + } } static inline struct pipe_scissor_state * @@ -368,12 +444,46 @@ fd_supported_prim(struct fd_context *ctx, unsigned prim) return (1 << prim) & ctx->primtype_mask; } +static inline struct fd_batch * +fd_context_batch(struct fd_context *ctx) +{ + if (unlikely(!ctx->batch)) { + struct fd_batch *batch = + fd_batch_from_fb(&ctx->screen->batch_cache, ctx, &ctx->framebuffer); + util_copy_framebuffer_state(&batch->framebuffer, &ctx->framebuffer); + ctx->batch = batch; + fd_context_all_dirty(ctx); + } + return ctx->batch; +} + +static inline void +fd_batch_set_stage(struct fd_batch *batch, enum fd_render_stage stage) +{ + struct fd_context *ctx = batch->ctx; + + /* special case: internal blits (like mipmap level generation) + * go through normal draw path (via util_blitter_blit()).. but + * we need to ignore the FD_STAGE_DRAW which will be set, so we + * don't enable queries which should be paused during internal + * blits: + */ + if ((batch->stage == FD_STAGE_BLIT) && + (stage != FD_STAGE_NULL)) + return; + + if (ctx->query_set_stage) + ctx->query_set_stage(batch, stage); + + batch->stage = stage; +} + void fd_context_setup_common_vbos(struct fd_context *ctx); void fd_context_cleanup_common_vbos(struct fd_context *ctx); struct pipe_context * fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, const uint8_t *primtypes, - void *priv); + void *priv, unsigned flags); void fd_context_destroy(struct pipe_context *pctx);