freedreno_context.h revision 848b8605
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3/* 4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark@freedesktop.org> 27 */ 28 29#ifndef FREEDRENO_CONTEXT_H_ 30#define FREEDRENO_CONTEXT_H_ 31 32#include "draw/draw_context.h" 33#include "pipe/p_context.h" 34#include "indices/u_primconvert.h" 35#include "util/u_blitter.h" 36#include "util/u_double_list.h" 37#include "util/u_slab.h" 38#include "util/u_string.h" 39 40#include "freedreno_screen.h" 41#include "freedreno_gmem.h" 42#include "freedreno_util.h" 43 44struct fd_vertex_stateobj; 45 46struct fd_texture_stateobj { 47 struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS]; 48 unsigned num_textures; 49 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 50 unsigned num_samplers; 51 unsigned dirty_samplers; 52}; 53 54struct fd_program_stateobj { 55 void *vp, *fp; 56 enum { 57 FD_SHADER_DIRTY_VP = (1 << 0), 58 FD_SHADER_DIRTY_FP = (1 << 1), 59 } dirty; 60 uint8_t num_exports; 61 /* Indexed by semantic name or TGSI_SEMANTIC_COUNT + semantic index 62 * for TGSI_SEMANTIC_GENERIC. Special vs exports (position and point- 63 * size) are not included in this 64 */ 65 uint8_t export_linkage[63]; 66}; 67 68struct fd_constbuf_stateobj { 69 struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS]; 70 uint32_t enabled_mask; 71 uint32_t dirty_mask; 72}; 73 74struct fd_vertexbuf_stateobj { 75 struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; 76 unsigned count; 77 uint32_t enabled_mask; 78 uint32_t dirty_mask; 79}; 80 81struct fd_vertex_stateobj { 82 struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS]; 83 unsigned num_elements; 84}; 85 86/* group together the vertex and vertexbuf state.. for ease of passing 87 * around, and because various internal operations (gmem<->mem, etc) 88 * need their own vertex state: 89 */ 90struct fd_vertex_state { 91 struct fd_vertex_stateobj *vtx; 92 struct fd_vertexbuf_stateobj vertexbuf; 93}; 94 95/* Bitmask of stages in rendering that a particular query query is 96 * active. Queries will be automatically started/stopped (generating 97 * additional fd_hw_sample_period's) on entrance/exit from stages that 98 * are applicable to the query. 99 * 100 * NOTE: set the stage to NULL at end of IB to ensure no query is still 101 * active. Things aren't going to work out the way you want if a query 102 * is active across IB's (or between tile IB and draw IB) 103 */ 104enum fd_render_stage { 105 FD_STAGE_NULL = 0x00, 106 FD_STAGE_DRAW = 0x01, 107 FD_STAGE_CLEAR = 0x02, 108 /* TODO before queries which include MEM2GMEM or GMEM2MEM will 109 * work we will need to call fd_hw_query_prepare() from somewhere 110 * appropriate so that queries in the tiling IB get backed with 111 * memory to write results to. 112 */ 113 FD_STAGE_MEM2GMEM = 0x04, 114 FD_STAGE_GMEM2MEM = 0x08, 115 /* used for driver internal draws (ie. util_blitter_blit()): */ 116 FD_STAGE_BLIT = 0x10, 117}; 118 119#define MAX_HW_SAMPLE_PROVIDERS 4 120struct fd_hw_sample_provider; 121struct fd_hw_sample; 122 123struct fd_context { 124 struct pipe_context base; 125 126 struct fd_device *dev; 127 struct fd_screen *screen; 128 129 struct blitter_context *blitter; 130 struct primconvert_context *primconvert; 131 132 /* slab for pipe_transfer allocations: */ 133 struct util_slab_mempool transfer_pool; 134 135 /* slabs for fd_hw_sample and fd_hw_sample_period allocations: */ 136 struct util_slab_mempool sample_pool; 137 struct util_slab_mempool sample_period_pool; 138 139 /* next sample offset.. incremented for each sample in the batch/ 140 * submit, reset to zero on next submit. 141 */ 142 uint32_t next_sample_offset; 143 144 /* sample-providers for hw queries: */ 145 const struct fd_hw_sample_provider *sample_providers[MAX_HW_SAMPLE_PROVIDERS]; 146 147 /* cached samples (in case multiple queries need to reference 148 * the same sample snapshot) 149 */ 150 struct fd_hw_sample *sample_cache[MAX_HW_SAMPLE_PROVIDERS]; 151 152 /* tracking for current stage, to know when to start/stop 153 * any active queries: 154 */ 155 enum fd_render_stage stage; 156 157 /* list of active queries: */ 158 struct list_head active_queries; 159 160 /* list of queries that are not active, but were active in the 161 * current submit: 162 */ 163 struct list_head current_queries; 164 165 /* current query result bo and tile stride: */ 166 struct fd_bo *query_bo; 167 uint32_t query_tile_stride; 168 169 /* table with PIPE_PRIM_MAX entries mapping PIPE_PRIM_x to 170 * DI_PT_x value to use for draw initiator. There are some 171 * slight differences between generation: 172 */ 173 const uint8_t *primtypes; 174 uint32_t primtype_mask; 175 176 /* shaders used by clear, and gmem->mem blits: */ 177 struct fd_program_stateobj solid_prog; // TODO move to screen? 178 179 /* shaders used by mem->gmem blits: */ 180 struct fd_program_stateobj blit_prog; // TODO move to screen? 181 182 /* do we need to mem2gmem before rendering. We don't, if for example, 183 * there was a glClear() that invalidated the entire previous buffer 184 * contents. Keep track of which buffer(s) are cleared, or needs 185 * restore. Masks of PIPE_CLEAR_* 186 * 187 * The 'cleared' bits will be set for buffers which are *entirely* 188 * cleared, and 'partial_cleared' bits will be set if you must 189 * check cleared_scissor. 190 */ 191 enum { 192 /* align bitmask values w/ PIPE_CLEAR_*.. since that is convenient.. */ 193 FD_BUFFER_COLOR = PIPE_CLEAR_COLOR0, 194 FD_BUFFER_DEPTH = PIPE_CLEAR_DEPTH, 195 FD_BUFFER_STENCIL = PIPE_CLEAR_STENCIL, 196 FD_BUFFER_ALL = FD_BUFFER_COLOR | FD_BUFFER_DEPTH | FD_BUFFER_STENCIL, 197 } cleared, partial_cleared, restore, resolve; 198 199 bool needs_flush; 200 201 /* To decide whether to render to system memory, keep track of the 202 * number of draws, and whether any of them require multisample, 203 * depth_test (or depth write), stencil_test, blending, and 204 * color_logic_Op (since those functions are disabled when by- 205 * passing GMEM. 206 */ 207 enum { 208 FD_GMEM_CLEARS_DEPTH_STENCIL = 0x01, 209 FD_GMEM_DEPTH_ENABLED = 0x02, 210 FD_GMEM_STENCIL_ENABLED = 0x04, 211 212 FD_GMEM_MSAA_ENABLED = 0x08, 213 FD_GMEM_BLEND_ENABLED = 0x10, 214 FD_GMEM_LOGICOP_ENABLED = 0x20, 215 } gmem_reason; 216 unsigned num_draws; /* number of draws in current batch */ 217 218 /* Stats/counters: 219 */ 220 struct { 221 uint64_t prims_emitted; 222 uint64_t draw_calls; 223 uint64_t batch_total, batch_sysmem, batch_gmem, batch_restore; 224 } stats; 225 226 /* we can't really sanely deal with wraparound point in ringbuffer 227 * and because of the way tiling works we can't really flush at 228 * arbitrary points (without a big performance hit). When we get 229 * too close to the end of the current ringbuffer, cycle to the next 230 * one (and wait for pending rendering from next rb to complete). 231 * We want the # of ringbuffers to be high enough that we don't 232 * normally have to wait before resetting to the start of the next 233 * rb. 234 */ 235 struct fd_ringbuffer *rings[8]; 236 unsigned rings_idx; 237 238 /* NOTE: currently using a single ringbuffer for both draw and 239 * tiling commands, we need to make sure we need to leave enough 240 * room at the end to append the tiling commands when we flush. 241 * 0x7000 dwords should be a couple times more than we ever need 242 * so should be a nice conservative threshold. 243 */ 244#define FD_TILING_COMMANDS_DWORDS 0x7000 245 246 /* normal draw/clear cmds: */ 247 struct fd_ringbuffer *ring; 248 struct fd_ringmarker *draw_start, *draw_end; 249 250 /* binning pass draw/clear cmds: */ 251 struct fd_ringbuffer *binning_ring; 252 struct fd_ringmarker *binning_start, *binning_end; 253 254 /* Keep track if WAIT_FOR_IDLE is needed for registers we need 255 * to update via RMW: 256 */ 257 bool needs_wfi; 258 259 /* Do we need to re-emit RB_FRAME_BUFFER_DIMENSION? At least on a3xx 260 * it is not a banked context register, so it needs a WFI to update. 261 * Keep track if it has actually changed, to avoid unneeded WFI. 262 * */ 263 bool needs_rb_fbd; 264 265 /* Keep track of DRAW initiators that need to be patched up depending 266 * on whether we using binning or not: 267 */ 268 struct util_dynarray draw_patches; 269 270 struct pipe_scissor_state scissor; 271 272 /* we don't have a disable/enable bit for scissor, so instead we keep 273 * a disabled-scissor state which matches the entire bound framebuffer 274 * and use that when scissor is not enabled. 275 */ 276 struct pipe_scissor_state disabled_scissor; 277 278 /* Track the maximal bounds of the scissor of all the draws within a 279 * batch. Used at the tile rendering step (fd_gmem_render_tiles(), 280 * mem2gmem/gmem2mem) to avoid needlessly moving data in/out of gmem. 281 */ 282 struct pipe_scissor_state max_scissor; 283 284 /* Track the cleared scissor for color/depth/stencil, so we know 285 * which, if any, tiles need to be restored (mem2gmem). Only valid 286 * if the corresponding bit in ctx->cleared is set. 287 */ 288 struct { 289 struct pipe_scissor_state color, depth, stencil; 290 } cleared_scissor; 291 292 /* Current gmem/tiling configuration.. gets updated on render_tiles() 293 * if out of date with current maximal-scissor/cpp: 294 */ 295 struct fd_gmem_stateobj gmem; 296 struct fd_vsc_pipe pipe[8]; 297 struct fd_tile tile[64]; 298 299 /* which state objects need to be re-emit'd: */ 300 enum { 301 FD_DIRTY_BLEND = (1 << 0), 302 FD_DIRTY_RASTERIZER = (1 << 1), 303 FD_DIRTY_ZSA = (1 << 2), 304 FD_DIRTY_FRAGTEX = (1 << 3), 305 FD_DIRTY_VERTTEX = (1 << 4), 306 FD_DIRTY_TEXSTATE = (1 << 5), 307 FD_DIRTY_PROG = (1 << 6), 308 FD_DIRTY_BLEND_COLOR = (1 << 7), 309 FD_DIRTY_STENCIL_REF = (1 << 8), 310 FD_DIRTY_SAMPLE_MASK = (1 << 9), 311 FD_DIRTY_FRAMEBUFFER = (1 << 10), 312 FD_DIRTY_STIPPLE = (1 << 11), 313 FD_DIRTY_VIEWPORT = (1 << 12), 314 FD_DIRTY_CONSTBUF = (1 << 13), 315 FD_DIRTY_VTXSTATE = (1 << 14), 316 FD_DIRTY_VTXBUF = (1 << 15), 317 FD_DIRTY_INDEXBUF = (1 << 16), 318 FD_DIRTY_SCISSOR = (1 << 17), 319 } dirty; 320 321 struct pipe_blend_state *blend; 322 struct pipe_rasterizer_state *rasterizer; 323 struct pipe_depth_stencil_alpha_state *zsa; 324 325 struct fd_texture_stateobj verttex, fragtex; 326 327 struct fd_program_stateobj prog; 328 329 struct fd_vertex_state vtx; 330 331 struct pipe_blend_color blend_color; 332 struct pipe_stencil_ref stencil_ref; 333 unsigned sample_mask; 334 struct pipe_framebuffer_state framebuffer; 335 struct pipe_poly_stipple stipple; 336 struct pipe_viewport_state viewport; 337 struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; 338 struct pipe_index_buffer indexbuf; 339 340 /* GMEM/tile handling fxns: */ 341 void (*emit_tile_init)(struct fd_context *ctx); 342 void (*emit_tile_prep)(struct fd_context *ctx, struct fd_tile *tile); 343 void (*emit_tile_mem2gmem)(struct fd_context *ctx, struct fd_tile *tile); 344 void (*emit_tile_renderprep)(struct fd_context *ctx, struct fd_tile *tile); 345 void (*emit_tile_gmem2mem)(struct fd_context *ctx, struct fd_tile *tile); 346 347 /* optional, for GMEM bypass: */ 348 void (*emit_sysmem_prep)(struct fd_context *ctx); 349 350 /* draw: */ 351 void (*draw)(struct fd_context *pctx, const struct pipe_draw_info *info); 352 void (*clear)(struct fd_context *ctx, unsigned buffers, 353 const union pipe_color_union *color, double depth, unsigned stencil); 354}; 355 356static INLINE struct fd_context * 357fd_context(struct pipe_context *pctx) 358{ 359 return (struct fd_context *)pctx; 360} 361 362static INLINE struct pipe_scissor_state * 363fd_context_get_scissor(struct fd_context *ctx) 364{ 365 if (ctx->rasterizer && ctx->rasterizer->scissor) 366 return &ctx->scissor; 367 return &ctx->disabled_scissor; 368} 369 370static INLINE bool 371fd_supported_prim(struct fd_context *ctx, unsigned prim) 372{ 373 return (1 << prim) & ctx->primtype_mask; 374} 375 376static INLINE void 377fd_reset_wfi(struct fd_context *ctx) 378{ 379 ctx->needs_wfi = true; 380} 381 382/* emit a WAIT_FOR_IDLE only if needed, ie. if there has not already 383 * been one since last draw: 384 */ 385static inline void 386fd_wfi(struct fd_context *ctx, struct fd_ringbuffer *ring) 387{ 388 if (ctx->needs_wfi) { 389 OUT_WFI(ring); 390 ctx->needs_wfi = false; 391 } 392} 393 394/* emit a CP_EVENT_WRITE: 395 */ 396static inline void 397fd_event_write(struct fd_context *ctx, struct fd_ringbuffer *ring, 398 enum vgt_event_type evt) 399{ 400 OUT_PKT3(ring, CP_EVENT_WRITE, 1); 401 OUT_RING(ring, evt); 402 fd_reset_wfi(ctx); 403} 404 405struct pipe_context * fd_context_init(struct fd_context *ctx, 406 struct pipe_screen *pscreen, const uint8_t *primtypes, 407 void *priv); 408 409void fd_context_render(struct pipe_context *pctx); 410 411void fd_context_destroy(struct pipe_context *pctx); 412 413#endif /* FREEDRENO_CONTEXT_H_ */ 414