1 /************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29 /** 30 * Binner data structures and bin-related functions. 31 * Note: the "setup" code is concerned with building scenes while 32 * The "rast" code is concerned with consuming/executing scenes. 33 */ 34 35 #ifndef LP_SCENE_H 36 #define LP_SCENE_H 37 38 #include "os/os_thread.h" 39 #include "lp_rast.h" 40 #include "lp_debug.h" 41 42 struct lp_scene_queue; 43 struct lp_rast_state; 44 45 /* We're limited to 2K by 2K for 32bit fixed point rasterization. 46 * Will need a 64-bit version for larger framebuffers. 47 */ 48 #define TILES_X (LP_MAX_WIDTH / TILE_SIZE) 49 #define TILES_Y (LP_MAX_HEIGHT / TILE_SIZE) 50 51 52 /* Commands per command block (ideally so sizeof(cmd_block) is a power of 53 * two in size.) 54 */ 55 #define CMD_BLOCK_MAX 29 56 57 /* Bytes per data block. 58 */ 59 #define DATA_BLOCK_SIZE (64 * 1024) 60 61 /* Scene temporary storage is clamped to this size: 62 */ 63 #define LP_SCENE_MAX_SIZE (9*1024*1024) 64 65 /* The maximum amount of texture storage referenced by a scene is 66 * clamped to this size: 67 */ 68 #define LP_SCENE_MAX_RESOURCE_SIZE (64*1024*1024) 69 70 71 /* switch to a non-pointer value for this: 72 */ 73 typedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *, 74 const union lp_rast_cmd_arg ); 75 76 77 struct cmd_block { 78 uint8_t cmd[CMD_BLOCK_MAX]; 79 union lp_rast_cmd_arg arg[CMD_BLOCK_MAX]; 80 unsigned count; 81 struct cmd_block *next; 82 }; 83 84 85 struct data_block { 86 ubyte data[DATA_BLOCK_SIZE]; 87 unsigned used; 88 struct data_block *next; 89 }; 90 91 92 93 /** 94 * For each screen tile we have one of these bins. 95 */ 96 struct cmd_bin { 97 const struct lp_rast_state *last_state; /* most recent state set in bin */ 98 struct cmd_block *head; 99 struct cmd_block *tail; 100 }; 101 102 103 /** 104 * This stores bulk data which is used for all memory allocations 105 * within a scene. 106 * 107 * Examples include triangle data and state data. The commands in 108 * the per-tile bins will point to chunks of data in this structure. 109 * 110 * Include the first block of data statically to ensure we can always 111 * initiate a scene without relying on malloc succeeding. 112 */ 113 struct data_block_list { 114 struct data_block first; 115 struct data_block *head; 116 }; 117 118 struct resource_ref; 119 120 /** 121 * All bins and bin data are contained here. 122 * Per-bin data goes into the 'tile' bins. 123 * Shared data goes into the 'data' buffer. 124 * 125 * When there are multiple threads, will want to double-buffer between 126 * scenes: 127 */ 128 struct lp_scene { 129 struct pipe_context *pipe; 130 struct lp_fence *fence; 131 132 /* The queries still active at end of scene */ 133 struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES]; 134 unsigned num_active_queries; 135 /* If queries were either active or there were begin/end query commands */ 136 boolean had_queries; 137 138 /* Framebuffer mappings - valid only between begin_rasterization() 139 * and end_rasterization(). 140 */ 141 struct { 142 uint8_t *map; 143 unsigned stride; 144 unsigned layer_stride; 145 unsigned format_bytes; 146 } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS]; 147 148 /* The amount of layers in the fb (minimum of all attachments) */ 149 unsigned fb_max_layer; 150 151 /** the framebuffer to render the scene into */ 152 struct pipe_framebuffer_state fb; 153 154 /** list of resources referenced by the scene commands */ 155 struct resource_ref *resources; 156 157 /** Total memory used by the scene (in bytes). This sums all the 158 * data blocks and counts all bins, state, resource references and 159 * other random allocations within the scene. 160 */ 161 unsigned scene_size; 162 163 /** Sum of sizes of all resources referenced by the scene. Sums 164 * all the textures read by the scene: 165 */ 166 unsigned resource_reference_size; 167 168 boolean alloc_failed; 169 boolean discard; 170 /** 171 * Number of active tiles in each dimension. 172 * This basically the framebuffer size divided by tile size 173 */ 174 unsigned tiles_x, tiles_y; 175 176 int curr_x, curr_y; /**< for iterating over bins */ 177 pipe_mutex mutex; 178 179 struct cmd_bin tile[TILES_X][TILES_Y]; 180 struct data_block_list data; 181 }; 182 183 184 185 struct lp_scene *lp_scene_create(struct pipe_context *pipe); 186 187 void lp_scene_destroy(struct lp_scene *scene); 188 189 boolean lp_scene_is_empty(struct lp_scene *scene ); 190 boolean lp_scene_is_oom(struct lp_scene *scene ); 191 192 193 struct data_block *lp_scene_new_data_block( struct lp_scene *scene ); 194 195 struct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene, 196 struct cmd_bin *bin ); 197 198 boolean lp_scene_add_resource_reference(struct lp_scene *scene, 199 struct pipe_resource *resource, 200 boolean initializing_scene); 201 202 boolean lp_scene_is_resource_referenced(const struct lp_scene *scene, 203 const struct pipe_resource *resource ); 204 205 206 /** 207 * Allocate space for a command/data in the bin's data buffer. 208 * Grow the block list if needed. 209 */ 210 static inline void * 211 lp_scene_alloc( struct lp_scene *scene, unsigned size) 212 { 213 struct data_block_list *list = &scene->data; 214 struct data_block *block = list->head; 215 216 assert(size <= DATA_BLOCK_SIZE); 217 assert(block != NULL); 218 219 if (LP_DEBUG & DEBUG_MEM) 220 debug_printf("alloc %u block %u/%u tot %u/%u\n", 221 size, block->used, DATA_BLOCK_SIZE, 222 scene->scene_size, LP_SCENE_MAX_SIZE); 223 224 if (block->used + size > DATA_BLOCK_SIZE) { 225 block = lp_scene_new_data_block( scene ); 226 if (!block) { 227 /* out of memory */ 228 return NULL; 229 } 230 } 231 232 { 233 ubyte *data = block->data + block->used; 234 block->used += size; 235 return data; 236 } 237 } 238 239 240 /** 241 * As above, but with specific alignment. 242 */ 243 static inline void * 244 lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, 245 unsigned alignment ) 246 { 247 struct data_block_list *list = &scene->data; 248 struct data_block *block = list->head; 249 250 assert(block != NULL); 251 252 if (LP_DEBUG & DEBUG_MEM) 253 debug_printf("alloc %u block %u/%u tot %u/%u\n", 254 size + alignment - 1, 255 block->used, DATA_BLOCK_SIZE, 256 scene->scene_size, LP_SCENE_MAX_SIZE); 257 258 if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) { 259 block = lp_scene_new_data_block( scene ); 260 if (!block) 261 return NULL; 262 } 263 264 { 265 ubyte *data = block->data + block->used; 266 unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data; 267 block->used += offset + size; 268 return data + offset; 269 } 270 } 271 272 273 /* Put back data if we decide not to use it, eg. culled triangles. 274 */ 275 static inline void 276 lp_scene_putback_data( struct lp_scene *scene, unsigned size) 277 { 278 struct data_block_list *list = &scene->data; 279 assert(list->head && list->head->used >= size); 280 list->head->used -= size; 281 } 282 283 284 /** Return pointer to a particular tile's bin. */ 285 static inline struct cmd_bin * 286 lp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y) 287 { 288 return &scene->tile[x][y]; 289 } 290 291 292 /** Remove all commands from a bin */ 293 void 294 lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y); 295 296 297 /* Add a command to bin[x][y]. 298 */ 299 static inline boolean 300 lp_scene_bin_command( struct lp_scene *scene, 301 unsigned x, unsigned y, 302 unsigned cmd, 303 union lp_rast_cmd_arg arg ) 304 { 305 struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); 306 struct cmd_block *tail = bin->tail; 307 308 assert(x < scene->tiles_x); 309 assert(y < scene->tiles_y); 310 assert(cmd < LP_RAST_OP_MAX); 311 312 if (tail == NULL || tail->count == CMD_BLOCK_MAX) { 313 tail = lp_scene_new_cmd_block( scene, bin ); 314 if (!tail) { 315 return FALSE; 316 } 317 assert(tail->count == 0); 318 } 319 320 { 321 unsigned i = tail->count; 322 tail->cmd[i] = cmd & LP_RAST_OP_MASK; 323 tail->arg[i] = arg; 324 tail->count++; 325 } 326 327 return TRUE; 328 } 329 330 331 static inline boolean 332 lp_scene_bin_cmd_with_state( struct lp_scene *scene, 333 unsigned x, unsigned y, 334 const struct lp_rast_state *state, 335 unsigned cmd, 336 union lp_rast_cmd_arg arg ) 337 { 338 struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); 339 340 if (state != bin->last_state) { 341 bin->last_state = state; 342 if (!lp_scene_bin_command(scene, x, y, 343 LP_RAST_OP_SET_STATE, 344 lp_rast_arg_state(state))) 345 return FALSE; 346 } 347 348 if (!lp_scene_bin_command( scene, x, y, cmd, arg )) 349 return FALSE; 350 351 return TRUE; 352 } 353 354 355 /* Add a command to all active bins. 356 */ 357 static inline boolean 358 lp_scene_bin_everywhere( struct lp_scene *scene, 359 unsigned cmd, 360 const union lp_rast_cmd_arg arg ) 361 { 362 unsigned i, j; 363 for (i = 0; i < scene->tiles_x; i++) { 364 for (j = 0; j < scene->tiles_y; j++) { 365 if (!lp_scene_bin_command( scene, i, j, cmd, arg )) 366 return FALSE; 367 } 368 } 369 370 return TRUE; 371 } 372 373 374 static inline unsigned 375 lp_scene_get_num_bins( const struct lp_scene *scene ) 376 { 377 return scene->tiles_x * scene->tiles_y; 378 } 379 380 381 void 382 lp_scene_bin_iter_begin( struct lp_scene *scene ); 383 384 struct cmd_bin * 385 lp_scene_bin_iter_next( struct lp_scene *scene, int *x, int *y ); 386 387 388 389 /* Begin/end binning of a scene 390 */ 391 void 392 lp_scene_begin_binning( struct lp_scene *scene, 393 struct pipe_framebuffer_state *fb, 394 boolean discard ); 395 396 void 397 lp_scene_end_binning( struct lp_scene *scene ); 398 399 400 /* Begin/end rasterization of a scene 401 */ 402 void 403 lp_scene_begin_rasterization(struct lp_scene *scene); 404 405 void 406 lp_scene_end_rasterization(struct lp_scene *scene ); 407 408 409 410 411 412 #endif /* LP_BIN_H */ 413