Home | History | Annotate | Download | only in llvmpipe
      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_tile_soa.h"
     40 #include "lp_rast.h"
     41 #include "lp_debug.h"
     42 
     43 struct lp_scene_queue;
     44 struct lp_rast_state;
     45 
     46 /* We're limited to 2K by 2K for 32bit fixed point rasterization.
     47  * Will need a 64-bit version for larger framebuffers.
     48  */
     49 #define TILES_X (LP_MAX_WIDTH / TILE_SIZE)
     50 #define TILES_Y (LP_MAX_HEIGHT / TILE_SIZE)
     51 
     52 
     53 #define CMD_BLOCK_MAX 128
     54 #define DATA_BLOCK_SIZE (64 * 1024)
     55 
     56 /* Scene temporary storage is clamped to this size:
     57  */
     58 #define LP_SCENE_MAX_SIZE (4*1024*1024)
     59 
     60 /* The maximum amount of texture storage referenced by a scene is
     61  * clamped ot this size:
     62  */
     63 #define LP_SCENE_MAX_RESOURCE_SIZE (64*1024*1024)
     64 
     65 
     66 /* switch to a non-pointer value for this:
     67  */
     68 typedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *,
     69                                   const union lp_rast_cmd_arg );
     70 
     71 
     72 struct cmd_block {
     73    uint8_t cmd[CMD_BLOCK_MAX];
     74    union lp_rast_cmd_arg arg[CMD_BLOCK_MAX];
     75    unsigned count;
     76    struct cmd_block *next;
     77 };
     78 
     79 struct cmd_block_list {
     80    struct cmd_block *head;
     81    struct cmd_block *tail;
     82 };
     83 
     84 struct data_block {
     85    ubyte data[DATA_BLOCK_SIZE];
     86    unsigned used;
     87    struct data_block *next;
     88 };
     89 
     90 
     91 
     92 /**
     93  * For each screen tile we have one of these bins.
     94  */
     95 struct cmd_bin {
     96    ushort x;
     97    ushort y;
     98    const struct lp_rast_state *last_state;       /* most recent state set in bin */
     99    struct cmd_block *head;
    100    struct cmd_block *tail;
    101 };
    102 
    103 
    104 /**
    105  * This stores bulk data which is used for all memory allocations
    106  * within a scene.
    107  *
    108  * Examples include triangle data and state data.  The commands in
    109  * the per-tile bins will point to chunks of data in this structure.
    110  *
    111  * Include the first block of data statically to ensure we can always
    112  * initiate a scene without relying on malloc succeeding.
    113  */
    114 struct data_block_list {
    115    struct data_block first;
    116    struct data_block *head;
    117 };
    118 
    119 struct resource_ref;
    120 
    121 /**
    122  * All bins and bin data are contained here.
    123  * Per-bin data goes into the 'tile' bins.
    124  * Shared data goes into the 'data' buffer.
    125  *
    126  * When there are multiple threads, will want to double-buffer between
    127  * scenes:
    128  */
    129 struct lp_scene {
    130    struct pipe_context *pipe;
    131    struct lp_fence *fence;
    132 
    133    /* Framebuffer mappings - valid only between begin_rasterization()
    134     * and end_rasterization().
    135     */
    136    struct {
    137       uint8_t *map;
    138       unsigned stride;
    139       unsigned blocksize;
    140    } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS];
    141 
    142    /** the framebuffer to render the scene into */
    143    struct pipe_framebuffer_state fb;
    144 
    145    /** list of resources referenced by the scene commands */
    146    struct resource_ref *resources;
    147 
    148    /** Total memory used by the scene (in bytes).  This sums all the
    149     * data blocks and counts all bins, state, resource references and
    150     * other random allocations within the scene.
    151     */
    152    unsigned scene_size;
    153 
    154    /** Sum of sizes of all resources referenced by the scene.  Sums
    155     * all the textures read by the scene:
    156     */
    157    unsigned resource_reference_size;
    158 
    159    boolean alloc_failed;
    160    boolean has_depthstencil_clear;
    161 
    162    /**
    163     * Number of active tiles in each dimension.
    164     * This basically the framebuffer size divided by tile size
    165     */
    166    unsigned tiles_x, tiles_y;
    167 
    168    int curr_x, curr_y;  /**< for iterating over bins */
    169    pipe_mutex mutex;
    170 
    171    struct cmd_bin tile[TILES_X][TILES_Y];
    172    struct data_block_list data;
    173 };
    174 
    175 
    176 
    177 struct lp_scene *lp_scene_create(struct pipe_context *pipe);
    178 
    179 void lp_scene_destroy(struct lp_scene *scene);
    180 
    181 boolean lp_scene_is_empty(struct lp_scene *scene );
    182 boolean lp_scene_is_oom(struct lp_scene *scene );
    183 
    184 
    185 struct data_block *lp_scene_new_data_block( struct lp_scene *scene );
    186 
    187 struct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene,
    188                                           struct cmd_bin *bin );
    189 
    190 boolean lp_scene_add_resource_reference(struct lp_scene *scene,
    191                                         struct pipe_resource *resource,
    192                                         boolean initializing_scene);
    193 
    194 boolean lp_scene_is_resource_referenced(const struct lp_scene *scene,
    195                                         const struct pipe_resource *resource );
    196 
    197 
    198 /**
    199  * Allocate space for a command/data in the bin's data buffer.
    200  * Grow the block list if needed.
    201  */
    202 static INLINE void *
    203 lp_scene_alloc( struct lp_scene *scene, unsigned size)
    204 {
    205    struct data_block_list *list = &scene->data;
    206    struct data_block *block = list->head;
    207 
    208    assert(size <= DATA_BLOCK_SIZE);
    209    assert(block != NULL);
    210 
    211    if (LP_DEBUG & DEBUG_MEM)
    212       debug_printf("alloc %u block %u/%u tot %u/%u\n",
    213 		   size, block->used, DATA_BLOCK_SIZE,
    214 		   scene->scene_size, LP_SCENE_MAX_SIZE);
    215 
    216    if (block->used + size > DATA_BLOCK_SIZE) {
    217       block = lp_scene_new_data_block( scene );
    218       if (!block) {
    219          /* out of memory */
    220          return NULL;
    221       }
    222    }
    223 
    224    {
    225       ubyte *data = block->data + block->used;
    226       block->used += size;
    227       return data;
    228    }
    229 }
    230 
    231 
    232 /**
    233  * As above, but with specific alignment.
    234  */
    235 static INLINE void *
    236 lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size,
    237 			unsigned alignment )
    238 {
    239    struct data_block_list *list = &scene->data;
    240    struct data_block *block = list->head;
    241 
    242    assert(block != NULL);
    243 
    244    if (LP_DEBUG & DEBUG_MEM)
    245       debug_printf("alloc %u block %u/%u tot %u/%u\n",
    246 		   size + alignment - 1,
    247 		   block->used, DATA_BLOCK_SIZE,
    248 		   scene->scene_size, LP_SCENE_MAX_SIZE);
    249 
    250    if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) {
    251       block = lp_scene_new_data_block( scene );
    252       if (!block)
    253          return NULL;
    254    }
    255 
    256    {
    257       ubyte *data = block->data + block->used;
    258       unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data;
    259       block->used += offset + size;
    260       return data + offset;
    261    }
    262 }
    263 
    264 
    265 /* Put back data if we decide not to use it, eg. culled triangles.
    266  */
    267 static INLINE void
    268 lp_scene_putback_data( struct lp_scene *scene, unsigned size)
    269 {
    270    struct data_block_list *list = &scene->data;
    271    assert(list->head && list->head->used >= size);
    272    list->head->used -= size;
    273 }
    274 
    275 
    276 /** Return pointer to a particular tile's bin. */
    277 static INLINE struct cmd_bin *
    278 lp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y)
    279 {
    280    return &scene->tile[x][y];
    281 }
    282 
    283 
    284 /** Remove all commands from a bin */
    285 void
    286 lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y);
    287 
    288 
    289 /* Add a command to bin[x][y].
    290  */
    291 static INLINE boolean
    292 lp_scene_bin_command( struct lp_scene *scene,
    293                       unsigned x, unsigned y,
    294                       unsigned cmd,
    295                       union lp_rast_cmd_arg arg )
    296 {
    297    struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
    298    struct cmd_block *tail = bin->tail;
    299 
    300    assert(x < scene->tiles_x);
    301    assert(y < scene->tiles_y);
    302    assert(cmd < LP_RAST_OP_MAX);
    303 
    304    if (tail == NULL || tail->count == CMD_BLOCK_MAX) {
    305       tail = lp_scene_new_cmd_block( scene, bin );
    306       if (!tail) {
    307          return FALSE;
    308       }
    309       assert(tail->count == 0);
    310    }
    311 
    312    {
    313       unsigned i = tail->count;
    314       tail->cmd[i] = cmd & LP_RAST_OP_MASK;
    315       tail->arg[i] = arg;
    316       tail->count++;
    317    }
    318 
    319    return TRUE;
    320 }
    321 
    322 
    323 static INLINE boolean
    324 lp_scene_bin_cmd_with_state( struct lp_scene *scene,
    325                              unsigned x, unsigned y,
    326                              const struct lp_rast_state *state,
    327                              unsigned cmd,
    328                              union lp_rast_cmd_arg arg )
    329 {
    330    struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
    331 
    332    if (state != bin->last_state) {
    333       bin->last_state = state;
    334       if (!lp_scene_bin_command(scene, x, y,
    335                                 LP_RAST_OP_SET_STATE,
    336                                 lp_rast_arg_state(state)))
    337          return FALSE;
    338    }
    339 
    340    if (!lp_scene_bin_command( scene, x, y, cmd, arg ))
    341       return FALSE;
    342 
    343    return TRUE;
    344 }
    345 
    346 
    347 /* Add a command to all active bins.
    348  */
    349 static INLINE boolean
    350 lp_scene_bin_everywhere( struct lp_scene *scene,
    351 			 unsigned cmd,
    352 			 const union lp_rast_cmd_arg arg )
    353 {
    354    unsigned i, j;
    355    for (i = 0; i < scene->tiles_x; i++) {
    356       for (j = 0; j < scene->tiles_y; j++) {
    357          if (!lp_scene_bin_command( scene, i, j, cmd, arg ))
    358             return FALSE;
    359       }
    360    }
    361 
    362    return TRUE;
    363 }
    364 
    365 
    366 static INLINE unsigned
    367 lp_scene_get_num_bins( const struct lp_scene *scene )
    368 {
    369    return scene->tiles_x * scene->tiles_y;
    370 }
    371 
    372 
    373 void
    374 lp_scene_bin_iter_begin( struct lp_scene *scene );
    375 
    376 struct cmd_bin *
    377 lp_scene_bin_iter_next( struct lp_scene *scene );
    378 
    379 
    380 
    381 /* Begin/end binning of a scene
    382  */
    383 void
    384 lp_scene_begin_binning( struct lp_scene *scene,
    385                         struct pipe_framebuffer_state *fb );
    386 
    387 void
    388 lp_scene_end_binning( struct lp_scene *scene );
    389 
    390 
    391 /* Begin/end rasterization of a scene
    392  */
    393 void
    394 lp_scene_begin_rasterization(struct lp_scene *scene);
    395 
    396 void
    397 lp_scene_end_rasterization(struct lp_scene *scene );
    398 
    399 
    400 
    401 
    402 
    403 #endif /* LP_BIN_H */
    404