X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_scene.h;h=679e2c07b28c1c0382c7c524a94c79a2720cac23;hb=31e344799a701630164f6f7907b09e5699a769d9;hp=a1fb8bf541b8ebf0d5ac79ed4f177bb07d97bb37;hpb=1318848f782cce716d6376ca13aebf68b728e24c;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index a1fb8bf541b..679e2c07b28 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -36,73 +36,86 @@ #define LP_SCENE_H #include "os/os_thread.h" -#include "lp_tile_soa.h" #include "lp_rast.h" +#include "lp_debug.h" struct lp_scene_queue; +struct lp_rast_state; /* We're limited to 2K by 2K for 32bit fixed point rasterization. * Will need a 64-bit version for larger framebuffers. */ -#define MAXHEIGHT 2048 -#define MAXWIDTH 2048 -#define TILES_X (MAXWIDTH / TILE_SIZE) -#define TILES_Y (MAXHEIGHT / TILE_SIZE) +#define TILES_X (LP_MAX_WIDTH / TILE_SIZE) +#define TILES_Y (LP_MAX_HEIGHT / TILE_SIZE) -#define CMD_BLOCK_MAX 128 -#define DATA_BLOCK_SIZE (16 * 1024 - sizeof(unsigned) - sizeof(void *)) - +/* Commands per command block (ideally so sizeof(cmd_block) is a power of + * two in size.) + */ +#define CMD_BLOCK_MAX 29 + +/* Bytes per data block. + */ +#define DATA_BLOCK_SIZE (64 * 1024) + +/* Scene temporary storage is clamped to this size: + */ +#define LP_SCENE_MAX_SIZE (36*1024*1024) + +/* The maximum amount of texture storage referenced by a scene is + * clamped to this size: + */ +#define LP_SCENE_MAX_RESOURCE_SIZE (64*1024*1024) /* switch to a non-pointer value for this: */ -typedef void (*lp_rast_cmd)( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); +typedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); + struct cmd_block { - lp_rast_cmd cmd[CMD_BLOCK_MAX]; + uint8_t cmd[CMD_BLOCK_MAX]; union lp_rast_cmd_arg arg[CMD_BLOCK_MAX]; unsigned count; struct cmd_block *next; }; + struct data_block { ubyte data[DATA_BLOCK_SIZE]; unsigned used; struct data_block *next; }; -struct cmd_block_list { - struct cmd_block *head; - struct cmd_block *tail; -}; + /** * For each screen tile we have one of these bins. */ struct cmd_bin { - struct cmd_block_list commands; + const struct lp_rast_state *last_state; /* most recent state set in bin */ + struct cmd_block *head; + struct cmd_block *tail; }; /** - * This stores bulk data which is shared by all bins within a scene. + * This stores bulk data which is used for all memory allocations + * within a scene. + * * Examples include triangle data and state data. The commands in * the per-tile bins will point to chunks of data in this structure. + * + * Include the first block of data statically to ensure we can always + * initiate a scene without relying on malloc succeeding. */ struct data_block_list { + struct data_block first; struct data_block *head; - struct data_block *tail; -}; - - -/** List of texture references */ -struct texture_ref { - struct pipe_resource *texture; - struct texture_ref *prev, *next; /**< linked list w/ u_simple_list.h */ }; +struct resource_ref; /** * All bins and bin data are contained here. @@ -114,20 +127,53 @@ struct texture_ref { */ struct lp_scene { struct pipe_context *pipe; + struct lp_fence *fence; - /* Scene's buffers are mapped at the time the scene is enqueued: + /* The queries still active at end of scene */ + struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES]; + unsigned num_active_queries; + /* If queries were either active or there were begin/end query commands */ + boolean had_queries; + + /* Framebuffer mappings - valid only between begin_rasterization() + * and end_rasterization(). */ - void *cbuf_map[PIPE_MAX_COLOR_BUFS]; - uint8_t *zsbuf_map; + struct { + uint8_t *map; + unsigned stride; + unsigned layer_stride; + unsigned format_bytes; + unsigned sample_stride; + unsigned nr_samples; + } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS]; + + /* The amount of layers in the fb (minimum of all attachments) */ + unsigned fb_max_layer; + + /* fixed point sample positions. */ + int32_t fixed_sample_pos[LP_MAX_SAMPLES][2]; + + /* max samples for bound framebuffer */ + unsigned fb_max_samples; /** the framebuffer to render the scene into */ struct pipe_framebuffer_state fb; - /** list of textures referenced by the scene commands */ - struct texture_ref textures; + /** list of resources referenced by the scene commands */ + struct resource_ref *resources; - boolean write_depth; + /** Total memory used by the scene (in bytes). This sums all the + * data blocks and counts all bins, state, resource references and + * other random allocations within the scene. + */ + unsigned scene_size; + + /** Sum of sizes of all resources referenced by the scene. Sums + * all the textures read by the scene: + */ + unsigned resource_reference_size; + boolean alloc_failed; /** * Number of active tiles in each dimension. * This basically the framebuffer size divided by tile size @@ -135,11 +181,7 @@ struct lp_scene { unsigned tiles_x, tiles_y; int curr_x, curr_y; /**< for iterating over bins */ - pipe_mutex mutex; - - /* Where to place this scene once it has been rasterized: - */ - struct lp_scene_queue *empty_queue; + mtx_t mutex; struct cmd_bin tile[TILES_X][TILES_Y]; struct data_block_list data; @@ -147,50 +189,56 @@ struct lp_scene { -struct lp_scene *lp_scene_create(struct pipe_context *pipe, - struct lp_scene_queue *empty_queue); +struct lp_scene *lp_scene_create(struct pipe_context *pipe); void lp_scene_destroy(struct lp_scene *scene); - - boolean lp_scene_is_empty(struct lp_scene *scene ); - -void lp_scene_reset(struct lp_scene *scene ); +boolean lp_scene_is_oom(struct lp_scene *scene ); -void lp_bin_new_data_block( struct data_block_list *list ); +struct data_block *lp_scene_new_data_block( struct lp_scene *scene ); -void lp_bin_new_cmd_block( struct cmd_block_list *list ); +struct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene, + struct cmd_bin *bin ); -unsigned lp_scene_data_size( const struct lp_scene *scene ); +boolean lp_scene_add_resource_reference(struct lp_scene *scene, + struct pipe_resource *resource, + boolean initializing_scene); -unsigned lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y ); - -void lp_scene_texture_reference( struct lp_scene *scene, - struct pipe_resource *texture ); - -boolean lp_scene_is_resource_referenced( const struct lp_scene *scene, - const struct pipe_resource *texture ); +boolean lp_scene_is_resource_referenced(const struct lp_scene *scene, + const struct pipe_resource *resource ); /** * Allocate space for a command/data in the bin's data buffer. * Grow the block list if needed. */ -static INLINE void * +static inline void * lp_scene_alloc( struct lp_scene *scene, unsigned size) { struct data_block_list *list = &scene->data; - - if (list->tail->used + size > DATA_BLOCK_SIZE) { - lp_bin_new_data_block( list ); + struct data_block *block = list->head; + + assert(size <= DATA_BLOCK_SIZE); + assert(block != NULL); + + if (LP_DEBUG & DEBUG_MEM) + debug_printf("alloc %u block %u/%u tot %u/%u\n", + size, block->used, DATA_BLOCK_SIZE, + scene->scene_size, LP_SCENE_MAX_SIZE); + + if (block->used + size > DATA_BLOCK_SIZE) { + block = lp_scene_new_data_block( scene ); + if (!block) { + /* out of memory */ + return NULL; + } } { - struct data_block *tail = list->tail; - ubyte *data = tail->data + tail->used; - tail->used += size; + ubyte *data = block->data + block->used; + block->used += size; return data; } } @@ -199,21 +247,31 @@ lp_scene_alloc( struct lp_scene *scene, unsigned size) /** * As above, but with specific alignment. */ -static INLINE void * +static inline void * lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, unsigned alignment ) { struct data_block_list *list = &scene->data; - - if (list->tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) { - lp_bin_new_data_block( list ); + struct data_block *block = list->head; + + assert(block != NULL); + + if (LP_DEBUG & DEBUG_MEM) + debug_printf("alloc %u block %u/%u tot %u/%u\n", + size + alignment - 1, + block->used, DATA_BLOCK_SIZE, + scene->scene_size, LP_SCENE_MAX_SIZE); + + if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) { + block = lp_scene_new_data_block( scene ); + if (!block) + return NULL; } { - struct data_block *tail = list->tail; - ubyte *data = tail->data + tail->used; + ubyte *data = block->data + block->used; unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data; - tail->used += offset + size; + block->used += offset + size; return data + offset; } } @@ -221,17 +279,17 @@ lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, /* Put back data if we decide not to use it, eg. culled triangles. */ -static INLINE void +static inline void lp_scene_putback_data( struct lp_scene *scene, unsigned size) { struct data_block_list *list = &scene->data; - assert(list->tail->used >= size); - list->tail->used -= size; + assert(list->head && list->head->used >= size); + list->head->used -= size; } /** Return pointer to a particular tile's bin. */ -static INLINE struct cmd_bin * +static inline struct cmd_bin * lp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y) { return &scene->tile[x][y]; @@ -245,53 +303,82 @@ lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y); /* Add a command to bin[x][y]. */ -static INLINE void +static inline boolean lp_scene_bin_command( struct lp_scene *scene, - unsigned x, unsigned y, - lp_rast_cmd cmd, - union lp_rast_cmd_arg arg ) + unsigned x, unsigned y, + unsigned cmd, + union lp_rast_cmd_arg arg ) { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); - struct cmd_block_list *list = &bin->commands; + struct cmd_block *tail = bin->tail; assert(x < scene->tiles_x); assert(y < scene->tiles_y); - - if (list->tail->count == CMD_BLOCK_MAX) { - lp_bin_new_cmd_block( list ); + assert(cmd < LP_RAST_OP_MAX); + + if (tail == NULL || tail->count == CMD_BLOCK_MAX) { + tail = lp_scene_new_cmd_block( scene, bin ); + if (!tail) { + return FALSE; + } + assert(tail->count == 0); } { - struct cmd_block *tail = list->tail; unsigned i = tail->count; - tail->cmd[i] = cmd; + tail->cmd[i] = cmd & LP_RAST_OP_MASK; tail->arg[i] = arg; tail->count++; } + + return TRUE; +} + + +static inline boolean +lp_scene_bin_cmd_with_state( struct lp_scene *scene, + unsigned x, unsigned y, + const struct lp_rast_state *state, + unsigned cmd, + union lp_rast_cmd_arg arg ) +{ + struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); + + if (state != bin->last_state) { + bin->last_state = state; + if (!lp_scene_bin_command(scene, x, y, + LP_RAST_OP_SET_STATE, + lp_rast_arg_state(state))) + return FALSE; + } + + if (!lp_scene_bin_command( scene, x, y, cmd, arg )) + return FALSE; + + return TRUE; } /* Add a command to all active bins. */ -static INLINE void +static inline boolean lp_scene_bin_everywhere( struct lp_scene *scene, - lp_rast_cmd cmd, + unsigned cmd, const union lp_rast_cmd_arg arg ) { unsigned i, j; - for (i = 0; i < scene->tiles_x; i++) - for (j = 0; j < scene->tiles_y; j++) - lp_scene_bin_command( scene, i, j, cmd, arg ); -} - + for (i = 0; i < scene->tiles_x; i++) { + for (j = 0; j < scene->tiles_y; j++) { + if (!lp_scene_bin_command( scene, i, j, cmd, arg )) + return FALSE; + } + } -void -lp_scene_bin_state_command( struct lp_scene *scene, - lp_rast_cmd cmd, - const union lp_rast_cmd_arg arg ); + return TRUE; +} -static INLINE unsigned +static inline unsigned lp_scene_get_num_bins( const struct lp_scene *scene ) { return scene->tiles_x * scene->tiles_y; @@ -302,15 +389,30 @@ void lp_scene_bin_iter_begin( struct lp_scene *scene ); struct cmd_bin * -lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y ); +lp_scene_bin_iter_next( struct lp_scene *scene, int *x, int *y ); + + + +/* Begin/end binning of a scene + */ +void +lp_scene_begin_binning(struct lp_scene *scene, + struct pipe_framebuffer_state *fb); void -lp_scene_rasterize( struct lp_scene *scene, - struct lp_rasterizer *rast, - boolean write_depth ); +lp_scene_end_binning(struct lp_scene *scene); + + +/* Begin/end rasterization of a scene + */ +void +lp_scene_begin_rasterization(struct lp_scene *scene); void -lp_scene_begin_binning( struct lp_scene *scene, - struct pipe_framebuffer_state *fb ); +lp_scene_end_rasterization(struct lp_scene *scene); + + + + #endif /* LP_BIN_H */