1cdc920a0Smrg/************************************************************************** 2cdc920a0Smrg * 3cdc920a0Smrg * Copyright 2009 VMware, Inc. 4cdc920a0Smrg * All Rights Reserved. 5cdc920a0Smrg * 6cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7cdc920a0Smrg * copy of this software and associated documentation files (the 8cdc920a0Smrg * "Software"), to deal in the Software without restriction, including 9cdc920a0Smrg * without limitation the rights to use, copy, modify, merge, publish, 10cdc920a0Smrg * distribute, sub license, and/or sell copies of the Software, and to 11cdc920a0Smrg * permit persons to whom the Software is furnished to do so, subject to 12cdc920a0Smrg * the following conditions: 13cdc920a0Smrg * 14cdc920a0Smrg * The above copyright notice and this permission notice (including the 15cdc920a0Smrg * next paragraph) shall be included in all copies or substantial portions 16cdc920a0Smrg * of the Software. 17cdc920a0Smrg * 18cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20cdc920a0Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21cdc920a0Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22cdc920a0Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23cdc920a0Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24cdc920a0Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25cdc920a0Smrg * 26cdc920a0Smrg **************************************************************************/ 27cdc920a0Smrg 28cdc920a0Smrg 29cdc920a0Smrg/** 30cdc920a0Smrg * Binner data structures and bin-related functions. 31cdc920a0Smrg * Note: the "setup" code is concerned with building scenes while 32cdc920a0Smrg * The "rast" code is concerned with consuming/executing scenes. 33cdc920a0Smrg */ 34cdc920a0Smrg 35cdc920a0Smrg#ifndef LP_SCENE_H 36cdc920a0Smrg#define LP_SCENE_H 37cdc920a0Smrg 38cdc920a0Smrg#include "os/os_thread.h" 39cdc920a0Smrg#include "lp_rast.h" 403464ebd5Sriastradh#include "lp_debug.h" 41cdc920a0Smrg 42cdc920a0Smrgstruct lp_scene_queue; 433464ebd5Sriastradhstruct lp_rast_state; 44cdc920a0Smrg 45cdc920a0Smrg/* We're limited to 2K by 2K for 32bit fixed point rasterization. 46cdc920a0Smrg * Will need a 64-bit version for larger framebuffers. 47cdc920a0Smrg */ 483464ebd5Sriastradh#define TILES_X (LP_MAX_WIDTH / TILE_SIZE) 493464ebd5Sriastradh#define TILES_Y (LP_MAX_HEIGHT / TILE_SIZE) 50cdc920a0Smrg 51cdc920a0Smrg 52af69d88dSmrg/* Commands per command block (ideally so sizeof(cmd_block) is a power of 53af69d88dSmrg * two in size.) 54af69d88dSmrg */ 55af69d88dSmrg#define CMD_BLOCK_MAX 29 56af69d88dSmrg 577ec681f3Smrg/* Bytes per data block. This effectively limits the maximum constant buffer 587ec681f3Smrg * size. 59af69d88dSmrg */ 603464ebd5Sriastradh#define DATA_BLOCK_SIZE (64 * 1024) 613464ebd5Sriastradh 623464ebd5Sriastradh/* Scene temporary storage is clamped to this size: 633464ebd5Sriastradh */ 647ec681f3Smrg#define LP_SCENE_MAX_SIZE (36*1024*1024) 653464ebd5Sriastradh 663464ebd5Sriastradh/* The maximum amount of texture storage referenced by a scene is 6701e04c3fSmrg * clamped to this size: 683464ebd5Sriastradh */ 693464ebd5Sriastradh#define LP_SCENE_MAX_RESOURCE_SIZE (64*1024*1024) 70cdc920a0Smrg 71cdc920a0Smrg 72cdc920a0Smrg/* switch to a non-pointer value for this: 73cdc920a0Smrg */ 743464ebd5Sriastradhtypedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *, 753464ebd5Sriastradh const union lp_rast_cmd_arg ); 76cdc920a0Smrg 773464ebd5Sriastradh 78cdc920a0Smrgstruct cmd_block { 793464ebd5Sriastradh uint8_t cmd[CMD_BLOCK_MAX]; 80cdc920a0Smrg union lp_rast_cmd_arg arg[CMD_BLOCK_MAX]; 81cdc920a0Smrg unsigned count; 82cdc920a0Smrg struct cmd_block *next; 83cdc920a0Smrg}; 84cdc920a0Smrg 853464ebd5Sriastradh 86cdc920a0Smrgstruct data_block { 87cdc920a0Smrg ubyte data[DATA_BLOCK_SIZE]; 88cdc920a0Smrg unsigned used; 89cdc920a0Smrg struct data_block *next; 90cdc920a0Smrg}; 91cdc920a0Smrg 923464ebd5Sriastradh 93cdc920a0Smrg 94cdc920a0Smrg/** 95cdc920a0Smrg * For each screen tile we have one of these bins. 96cdc920a0Smrg */ 97cdc920a0Smrgstruct cmd_bin { 983464ebd5Sriastradh const struct lp_rast_state *last_state; /* most recent state set in bin */ 993464ebd5Sriastradh struct cmd_block *head; 1003464ebd5Sriastradh struct cmd_block *tail; 101cdc920a0Smrg}; 102cdc920a0Smrg 103cdc920a0Smrg 104cdc920a0Smrg/** 1053464ebd5Sriastradh * This stores bulk data which is used for all memory allocations 1063464ebd5Sriastradh * within a scene. 1073464ebd5Sriastradh * 108cdc920a0Smrg * Examples include triangle data and state data. The commands in 109cdc920a0Smrg * the per-tile bins will point to chunks of data in this structure. 1103464ebd5Sriastradh * 1113464ebd5Sriastradh * Include the first block of data statically to ensure we can always 1123464ebd5Sriastradh * initiate a scene without relying on malloc succeeding. 113cdc920a0Smrg */ 114cdc920a0Smrgstruct data_block_list { 1153464ebd5Sriastradh struct data_block first; 116cdc920a0Smrg struct data_block *head; 117cdc920a0Smrg}; 118cdc920a0Smrg 1193464ebd5Sriastradhstruct resource_ref; 120cdc920a0Smrg 1217ec681f3Smrgstruct shader_ref; 1227ec681f3Smrg 1237ec681f3Smrgstruct lp_scene_surface { 1247ec681f3Smrg uint8_t *map; 1257ec681f3Smrg unsigned stride; 1267ec681f3Smrg unsigned layer_stride; 1277ec681f3Smrg unsigned format_bytes; 1287ec681f3Smrg unsigned sample_stride; 1297ec681f3Smrg unsigned nr_samples; 1307ec681f3Smrg}; 1317ec681f3Smrg 132cdc920a0Smrg/** 133cdc920a0Smrg * All bins and bin data are contained here. 134cdc920a0Smrg * Per-bin data goes into the 'tile' bins. 135cdc920a0Smrg * Shared data goes into the 'data' buffer. 136cdc920a0Smrg * 137cdc920a0Smrg * When there are multiple threads, will want to double-buffer between 138cdc920a0Smrg * scenes: 139cdc920a0Smrg */ 140cdc920a0Smrgstruct lp_scene { 141cdc920a0Smrg struct pipe_context *pipe; 1423464ebd5Sriastradh struct lp_fence *fence; 143cdc920a0Smrg 144af69d88dSmrg /* The queries still active at end of scene */ 145af69d88dSmrg struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES]; 146af69d88dSmrg unsigned num_active_queries; 147af69d88dSmrg /* If queries were either active or there were begin/end query commands */ 148af69d88dSmrg boolean had_queries; 149af69d88dSmrg 1503464ebd5Sriastradh /* Framebuffer mappings - valid only between begin_rasterization() 1513464ebd5Sriastradh * and end_rasterization(). 152cdc920a0Smrg */ 1537ec681f3Smrg struct lp_scene_surface zsbuf, cbufs[PIPE_MAX_COLOR_BUFS]; 154af69d88dSmrg 155af69d88dSmrg /* The amount of layers in the fb (minimum of all attachments) */ 156af69d88dSmrg unsigned fb_max_layer; 157af69d88dSmrg 1587ec681f3Smrg /* fixed point sample positions. */ 1597ec681f3Smrg int32_t fixed_sample_pos[LP_MAX_SAMPLES][2]; 1607ec681f3Smrg 1617ec681f3Smrg /* max samples for bound framebuffer */ 1627ec681f3Smrg unsigned fb_max_samples; 1637ec681f3Smrg 164cdc920a0Smrg /** the framebuffer to render the scene into */ 165cdc920a0Smrg struct pipe_framebuffer_state fb; 166cdc920a0Smrg 1673464ebd5Sriastradh /** list of resources referenced by the scene commands */ 1683464ebd5Sriastradh struct resource_ref *resources; 1693464ebd5Sriastradh 1707ec681f3Smrg /** list of frag shaders referenced by the scene commands */ 1717ec681f3Smrg struct shader_ref *frag_shaders; 1727ec681f3Smrg 1733464ebd5Sriastradh /** Total memory used by the scene (in bytes). This sums all the 1743464ebd5Sriastradh * data blocks and counts all bins, state, resource references and 1753464ebd5Sriastradh * other random allocations within the scene. 1763464ebd5Sriastradh */ 1773464ebd5Sriastradh unsigned scene_size; 1783464ebd5Sriastradh 1793464ebd5Sriastradh /** Sum of sizes of all resources referenced by the scene. Sums 1803464ebd5Sriastradh * all the textures read by the scene: 1813464ebd5Sriastradh */ 1823464ebd5Sriastradh unsigned resource_reference_size; 183cdc920a0Smrg 1843464ebd5Sriastradh boolean alloc_failed; 1857ec681f3Smrg boolean permit_linear_rasterizer; 1867ec681f3Smrg 187cdc920a0Smrg /** 188cdc920a0Smrg * Number of active tiles in each dimension. 189cdc920a0Smrg * This basically the framebuffer size divided by tile size 190cdc920a0Smrg */ 191cdc920a0Smrg unsigned tiles_x, tiles_y; 192cdc920a0Smrg 193cdc920a0Smrg int curr_x, curr_y; /**< for iterating over bins */ 19401e04c3fSmrg mtx_t mutex; 195cdc920a0Smrg 196cdc920a0Smrg struct cmd_bin tile[TILES_X][TILES_Y]; 197cdc920a0Smrg struct data_block_list data; 198cdc920a0Smrg}; 199cdc920a0Smrg 200cdc920a0Smrg 201cdc920a0Smrg 2023464ebd5Sriastradhstruct lp_scene *lp_scene_create(struct pipe_context *pipe); 203cdc920a0Smrg 204cdc920a0Smrgvoid lp_scene_destroy(struct lp_scene *scene); 205cdc920a0Smrg 206cdc920a0Smrgboolean lp_scene_is_empty(struct lp_scene *scene ); 2073464ebd5Sriastradhboolean lp_scene_is_oom(struct lp_scene *scene ); 208cdc920a0Smrg 209cdc920a0Smrg 2103464ebd5Sriastradhstruct data_block *lp_scene_new_data_block( struct lp_scene *scene ); 211cdc920a0Smrg 2123464ebd5Sriastradhstruct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene, 2133464ebd5Sriastradh struct cmd_bin *bin ); 214cdc920a0Smrg 2153464ebd5Sriastradhboolean lp_scene_add_resource_reference(struct lp_scene *scene, 2163464ebd5Sriastradh struct pipe_resource *resource, 2173464ebd5Sriastradh boolean initializing_scene); 218cdc920a0Smrg 2193464ebd5Sriastradhboolean lp_scene_is_resource_referenced(const struct lp_scene *scene, 2203464ebd5Sriastradh const struct pipe_resource *resource ); 221cdc920a0Smrg 2227ec681f3Smrgboolean lp_scene_add_frag_shader_reference(struct lp_scene *scene, 2237ec681f3Smrg struct lp_fragment_shader_variant *variant); 2247ec681f3Smrg 2257ec681f3Smrg 226cdc920a0Smrg 227cdc920a0Smrg/** 228cdc920a0Smrg * Allocate space for a command/data in the bin's data buffer. 229cdc920a0Smrg * Grow the block list if needed. 230cdc920a0Smrg */ 23101e04c3fSmrgstatic inline void * 232cdc920a0Smrglp_scene_alloc( struct lp_scene *scene, unsigned size) 233cdc920a0Smrg{ 234cdc920a0Smrg struct data_block_list *list = &scene->data; 2353464ebd5Sriastradh struct data_block *block = list->head; 2363464ebd5Sriastradh 2373464ebd5Sriastradh assert(size <= DATA_BLOCK_SIZE); 2383464ebd5Sriastradh assert(block != NULL); 2393464ebd5Sriastradh 2403464ebd5Sriastradh if (LP_DEBUG & DEBUG_MEM) 2413464ebd5Sriastradh debug_printf("alloc %u block %u/%u tot %u/%u\n", 2427ec681f3Smrg size, block->used, (unsigned)DATA_BLOCK_SIZE, 2433464ebd5Sriastradh scene->scene_size, LP_SCENE_MAX_SIZE); 2443464ebd5Sriastradh 2453464ebd5Sriastradh if (block->used + size > DATA_BLOCK_SIZE) { 2463464ebd5Sriastradh block = lp_scene_new_data_block( scene ); 2473464ebd5Sriastradh if (!block) { 2483464ebd5Sriastradh /* out of memory */ 2493464ebd5Sriastradh return NULL; 2503464ebd5Sriastradh } 251cdc920a0Smrg } 252cdc920a0Smrg 253cdc920a0Smrg { 2543464ebd5Sriastradh ubyte *data = block->data + block->used; 2553464ebd5Sriastradh block->used += size; 256cdc920a0Smrg return data; 257cdc920a0Smrg } 258cdc920a0Smrg} 259cdc920a0Smrg 260cdc920a0Smrg 261cdc920a0Smrg/** 262cdc920a0Smrg * As above, but with specific alignment. 263cdc920a0Smrg */ 26401e04c3fSmrgstatic inline void * 265cdc920a0Smrglp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, 266cdc920a0Smrg unsigned alignment ) 267cdc920a0Smrg{ 268cdc920a0Smrg struct data_block_list *list = &scene->data; 2693464ebd5Sriastradh struct data_block *block = list->head; 2703464ebd5Sriastradh 2713464ebd5Sriastradh assert(block != NULL); 2723464ebd5Sriastradh 2733464ebd5Sriastradh if (LP_DEBUG & DEBUG_MEM) 2743464ebd5Sriastradh debug_printf("alloc %u block %u/%u tot %u/%u\n", 2753464ebd5Sriastradh size + alignment - 1, 2767ec681f3Smrg block->used, (unsigned)DATA_BLOCK_SIZE, 2773464ebd5Sriastradh scene->scene_size, LP_SCENE_MAX_SIZE); 2783464ebd5Sriastradh 2793464ebd5Sriastradh if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) { 2803464ebd5Sriastradh block = lp_scene_new_data_block( scene ); 2813464ebd5Sriastradh if (!block) 2823464ebd5Sriastradh return NULL; 283cdc920a0Smrg } 284cdc920a0Smrg 285cdc920a0Smrg { 2863464ebd5Sriastradh ubyte *data = block->data + block->used; 287cdc920a0Smrg unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data; 2883464ebd5Sriastradh block->used += offset + size; 289cdc920a0Smrg return data + offset; 290cdc920a0Smrg } 291cdc920a0Smrg} 292cdc920a0Smrg 293cdc920a0Smrg 294cdc920a0Smrg/** Return pointer to a particular tile's bin. */ 29501e04c3fSmrgstatic inline struct cmd_bin * 296cdc920a0Smrglp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y) 297cdc920a0Smrg{ 298cdc920a0Smrg return &scene->tile[x][y]; 299cdc920a0Smrg} 300cdc920a0Smrg 301cdc920a0Smrg 302cdc920a0Smrg/** Remove all commands from a bin */ 303cdc920a0Smrgvoid 304cdc920a0Smrglp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y); 305cdc920a0Smrg 306cdc920a0Smrg 307cdc920a0Smrg/* Add a command to bin[x][y]. 308cdc920a0Smrg */ 30901e04c3fSmrgstatic inline boolean 310cdc920a0Smrglp_scene_bin_command( struct lp_scene *scene, 3113464ebd5Sriastradh unsigned x, unsigned y, 3123464ebd5Sriastradh unsigned cmd, 3133464ebd5Sriastradh union lp_rast_cmd_arg arg ) 314cdc920a0Smrg{ 315cdc920a0Smrg struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); 3163464ebd5Sriastradh struct cmd_block *tail = bin->tail; 317cdc920a0Smrg 318cdc920a0Smrg assert(x < scene->tiles_x); 319cdc920a0Smrg assert(y < scene->tiles_y); 3203464ebd5Sriastradh assert(cmd < LP_RAST_OP_MAX); 3213464ebd5Sriastradh 3223464ebd5Sriastradh if (tail == NULL || tail->count == CMD_BLOCK_MAX) { 3233464ebd5Sriastradh tail = lp_scene_new_cmd_block( scene, bin ); 3243464ebd5Sriastradh if (!tail) { 3253464ebd5Sriastradh return FALSE; 3263464ebd5Sriastradh } 3273464ebd5Sriastradh assert(tail->count == 0); 328cdc920a0Smrg } 329cdc920a0Smrg 330cdc920a0Smrg { 331cdc920a0Smrg unsigned i = tail->count; 3323464ebd5Sriastradh tail->cmd[i] = cmd & LP_RAST_OP_MASK; 333cdc920a0Smrg tail->arg[i] = arg; 334cdc920a0Smrg tail->count++; 335cdc920a0Smrg } 3363464ebd5Sriastradh 3373464ebd5Sriastradh return TRUE; 3383464ebd5Sriastradh} 3393464ebd5Sriastradh 3403464ebd5Sriastradh 34101e04c3fSmrgstatic inline boolean 3423464ebd5Sriastradhlp_scene_bin_cmd_with_state( struct lp_scene *scene, 3433464ebd5Sriastradh unsigned x, unsigned y, 3443464ebd5Sriastradh const struct lp_rast_state *state, 3453464ebd5Sriastradh unsigned cmd, 3463464ebd5Sriastradh union lp_rast_cmd_arg arg ) 3473464ebd5Sriastradh{ 3483464ebd5Sriastradh struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); 3493464ebd5Sriastradh 3503464ebd5Sriastradh if (state != bin->last_state) { 3513464ebd5Sriastradh bin->last_state = state; 3523464ebd5Sriastradh if (!lp_scene_bin_command(scene, x, y, 3533464ebd5Sriastradh LP_RAST_OP_SET_STATE, 3543464ebd5Sriastradh lp_rast_arg_state(state))) 3553464ebd5Sriastradh return FALSE; 3563464ebd5Sriastradh } 3573464ebd5Sriastradh 3583464ebd5Sriastradh if (!lp_scene_bin_command( scene, x, y, cmd, arg )) 3593464ebd5Sriastradh return FALSE; 3603464ebd5Sriastradh 3613464ebd5Sriastradh return TRUE; 362cdc920a0Smrg} 363cdc920a0Smrg 364cdc920a0Smrg 365cdc920a0Smrg/* Add a command to all active bins. 366cdc920a0Smrg */ 36701e04c3fSmrgstatic inline boolean 368cdc920a0Smrglp_scene_bin_everywhere( struct lp_scene *scene, 3693464ebd5Sriastradh unsigned cmd, 370cdc920a0Smrg const union lp_rast_cmd_arg arg ) 371cdc920a0Smrg{ 372cdc920a0Smrg unsigned i, j; 3733464ebd5Sriastradh for (i = 0; i < scene->tiles_x; i++) { 3743464ebd5Sriastradh for (j = 0; j < scene->tiles_y; j++) { 3753464ebd5Sriastradh if (!lp_scene_bin_command( scene, i, j, cmd, arg )) 3763464ebd5Sriastradh return FALSE; 3773464ebd5Sriastradh } 3783464ebd5Sriastradh } 379cdc920a0Smrg 3803464ebd5Sriastradh return TRUE; 3813464ebd5Sriastradh} 382cdc920a0Smrg 383cdc920a0Smrg 38401e04c3fSmrgstatic inline unsigned 385cdc920a0Smrglp_scene_get_num_bins( const struct lp_scene *scene ) 386cdc920a0Smrg{ 387cdc920a0Smrg return scene->tiles_x * scene->tiles_y; 388cdc920a0Smrg} 389cdc920a0Smrg 390cdc920a0Smrg 391cdc920a0Smrgvoid 392cdc920a0Smrglp_scene_bin_iter_begin( struct lp_scene *scene ); 393cdc920a0Smrg 394cdc920a0Smrgstruct cmd_bin * 395af69d88dSmrglp_scene_bin_iter_next( struct lp_scene *scene, int *x, int *y ); 396cdc920a0Smrg 397cdc920a0Smrg 3983464ebd5Sriastradh 3993464ebd5Sriastradh/* Begin/end binning of a scene 4003464ebd5Sriastradh */ 401cdc920a0Smrgvoid 40201e04c3fSmrglp_scene_begin_binning(struct lp_scene *scene, 40301e04c3fSmrg struct pipe_framebuffer_state *fb); 404cdc920a0Smrg 4053464ebd5Sriastradhvoid 40601e04c3fSmrglp_scene_end_binning(struct lp_scene *scene); 4073464ebd5Sriastradh 4083464ebd5Sriastradh 4093464ebd5Sriastradh/* Begin/end rasterization of a scene 4103464ebd5Sriastradh */ 4113464ebd5Sriastradhvoid 4123464ebd5Sriastradhlp_scene_begin_rasterization(struct lp_scene *scene); 4133464ebd5Sriastradh 4143464ebd5Sriastradhvoid 41501e04c3fSmrglp_scene_end_rasterization(struct lp_scene *scene); 4163464ebd5Sriastradh 4173464ebd5Sriastradh 4183464ebd5Sriastradh 4193464ebd5Sriastradh 4203464ebd5Sriastradh 421cdc920a0Smrg#endif /* LP_BIN_H */ 422