• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (36*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 struct shader_ref;
121 
122 /**
123  * All bins and bin data are contained here.
124  * Per-bin data goes into the 'tile' bins.
125  * Shared data goes into the 'data' buffer.
126  *
127  * When there are multiple threads, will want to double-buffer between
128  * scenes:
129  */
130 struct lp_scene {
131    struct pipe_context *pipe;
132    struct lp_fence *fence;
133 
134    /* The queries still active at end of scene */
135    struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES];
136    unsigned num_active_queries;
137    /* If queries were either active or there were begin/end query commands */
138    boolean had_queries;
139 
140    /* Framebuffer mappings - valid only between begin_rasterization()
141     * and end_rasterization().
142     */
143    struct {
144       uint8_t *map;
145       unsigned stride;
146       unsigned layer_stride;
147       unsigned format_bytes;
148       unsigned sample_stride;
149       unsigned nr_samples;
150    } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS];
151 
152    /* The amount of layers in the fb (minimum of all attachments) */
153    unsigned fb_max_layer;
154 
155    /* fixed point sample positions. */
156    int32_t fixed_sample_pos[LP_MAX_SAMPLES][2];
157 
158    /* max samples for bound framebuffer */
159    unsigned fb_max_samples;
160 
161    /** the framebuffer to render the scene into */
162    struct pipe_framebuffer_state fb;
163 
164    /** list of resources referenced by the scene commands */
165    struct resource_ref *resources;
166 
167    /** list of frag shaders referenced by the scene commands */
168    struct shader_ref *frag_shaders;
169 
170    /** Total memory used by the scene (in bytes).  This sums all the
171     * data blocks and counts all bins, state, resource references and
172     * other random allocations within the scene.
173     */
174    unsigned scene_size;
175 
176    /** Sum of sizes of all resources referenced by the scene.  Sums
177     * all the textures read by the scene:
178     */
179    unsigned resource_reference_size;
180 
181    boolean alloc_failed;
182    /**
183     * Number of active tiles in each dimension.
184     * This basically the framebuffer size divided by tile size
185     */
186    unsigned tiles_x, tiles_y;
187 
188    int curr_x, curr_y;  /**< for iterating over bins */
189    mtx_t mutex;
190 
191    struct cmd_bin tile[TILES_X][TILES_Y];
192    struct data_block_list data;
193 };
194 
195 
196 
197 struct lp_scene *lp_scene_create(struct pipe_context *pipe);
198 
199 void lp_scene_destroy(struct lp_scene *scene);
200 
201 boolean lp_scene_is_empty(struct lp_scene *scene );
202 boolean lp_scene_is_oom(struct lp_scene *scene );
203 
204 
205 struct data_block *lp_scene_new_data_block( struct lp_scene *scene );
206 
207 struct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene,
208                                           struct cmd_bin *bin );
209 
210 boolean lp_scene_add_resource_reference(struct lp_scene *scene,
211                                         struct pipe_resource *resource,
212                                         boolean initializing_scene);
213 
214 boolean lp_scene_is_resource_referenced(const struct lp_scene *scene,
215                                         const struct pipe_resource *resource );
216 
217 boolean lp_scene_add_frag_shader_reference(struct lp_scene *scene,
218                                            struct lp_fragment_shader_variant *variant);
219 
220 
221 
222 /**
223  * Allocate space for a command/data in the bin's data buffer.
224  * Grow the block list if needed.
225  */
226 static inline void *
lp_scene_alloc(struct lp_scene * scene,unsigned size)227 lp_scene_alloc( struct lp_scene *scene, unsigned size)
228 {
229    struct data_block_list *list = &scene->data;
230    struct data_block *block = list->head;
231 
232    assert(size <= DATA_BLOCK_SIZE);
233    assert(block != NULL);
234 
235    if (LP_DEBUG & DEBUG_MEM)
236       debug_printf("alloc %u block %u/%u tot %u/%u\n",
237 		   size, block->used, DATA_BLOCK_SIZE,
238 		   scene->scene_size, LP_SCENE_MAX_SIZE);
239 
240    if (block->used + size > DATA_BLOCK_SIZE) {
241       block = lp_scene_new_data_block( scene );
242       if (!block) {
243          /* out of memory */
244          return NULL;
245       }
246    }
247 
248    {
249       ubyte *data = block->data + block->used;
250       block->used += size;
251       return data;
252    }
253 }
254 
255 
256 /**
257  * As above, but with specific alignment.
258  */
259 static inline void *
lp_scene_alloc_aligned(struct lp_scene * scene,unsigned size,unsigned alignment)260 lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size,
261 			unsigned alignment )
262 {
263    struct data_block_list *list = &scene->data;
264    struct data_block *block = list->head;
265 
266    assert(block != NULL);
267 
268    if (LP_DEBUG & DEBUG_MEM)
269       debug_printf("alloc %u block %u/%u tot %u/%u\n",
270 		   size + alignment - 1,
271 		   block->used, DATA_BLOCK_SIZE,
272 		   scene->scene_size, LP_SCENE_MAX_SIZE);
273 
274    if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) {
275       block = lp_scene_new_data_block( scene );
276       if (!block)
277          return NULL;
278    }
279 
280    {
281       ubyte *data = block->data + block->used;
282       unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data;
283       block->used += offset + size;
284       return data + offset;
285    }
286 }
287 
288 
289 /* Put back data if we decide not to use it, eg. culled triangles.
290  */
291 static inline void
lp_scene_putback_data(struct lp_scene * scene,unsigned size)292 lp_scene_putback_data( struct lp_scene *scene, unsigned size)
293 {
294    struct data_block_list *list = &scene->data;
295    assert(list->head && list->head->used >= size);
296    list->head->used -= size;
297 }
298 
299 
300 /** Return pointer to a particular tile's bin. */
301 static inline struct cmd_bin *
lp_scene_get_bin(struct lp_scene * scene,unsigned x,unsigned y)302 lp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y)
303 {
304    return &scene->tile[x][y];
305 }
306 
307 
308 /** Remove all commands from a bin */
309 void
310 lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y);
311 
312 
313 /* Add a command to bin[x][y].
314  */
315 static inline boolean
lp_scene_bin_command(struct lp_scene * scene,unsigned x,unsigned y,unsigned cmd,union lp_rast_cmd_arg arg)316 lp_scene_bin_command( struct lp_scene *scene,
317                       unsigned x, unsigned y,
318                       unsigned cmd,
319                       union lp_rast_cmd_arg arg )
320 {
321    struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
322    struct cmd_block *tail = bin->tail;
323 
324    assert(x < scene->tiles_x);
325    assert(y < scene->tiles_y);
326    assert(cmd < LP_RAST_OP_MAX);
327 
328    if (tail == NULL || tail->count == CMD_BLOCK_MAX) {
329       tail = lp_scene_new_cmd_block( scene, bin );
330       if (!tail) {
331          return FALSE;
332       }
333       assert(tail->count == 0);
334    }
335 
336    {
337       unsigned i = tail->count;
338       tail->cmd[i] = cmd & LP_RAST_OP_MASK;
339       tail->arg[i] = arg;
340       tail->count++;
341    }
342 
343    return TRUE;
344 }
345 
346 
347 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)348 lp_scene_bin_cmd_with_state( struct lp_scene *scene,
349                              unsigned x, unsigned y,
350                              const struct lp_rast_state *state,
351                              unsigned cmd,
352                              union lp_rast_cmd_arg arg )
353 {
354    struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
355 
356    if (state != bin->last_state) {
357       bin->last_state = state;
358       if (!lp_scene_bin_command(scene, x, y,
359                                 LP_RAST_OP_SET_STATE,
360                                 lp_rast_arg_state(state)))
361          return FALSE;
362    }
363 
364    if (!lp_scene_bin_command( scene, x, y, cmd, arg ))
365       return FALSE;
366 
367    return TRUE;
368 }
369 
370 
371 /* Add a command to all active bins.
372  */
373 static inline boolean
lp_scene_bin_everywhere(struct lp_scene * scene,unsigned cmd,const union lp_rast_cmd_arg arg)374 lp_scene_bin_everywhere( struct lp_scene *scene,
375 			 unsigned cmd,
376 			 const union lp_rast_cmd_arg arg )
377 {
378    unsigned i, j;
379    for (i = 0; i < scene->tiles_x; i++) {
380       for (j = 0; j < scene->tiles_y; j++) {
381          if (!lp_scene_bin_command( scene, i, j, cmd, arg ))
382             return FALSE;
383       }
384    }
385 
386    return TRUE;
387 }
388 
389 
390 static inline unsigned
lp_scene_get_num_bins(const struct lp_scene * scene)391 lp_scene_get_num_bins( const struct lp_scene *scene )
392 {
393    return scene->tiles_x * scene->tiles_y;
394 }
395 
396 
397 void
398 lp_scene_bin_iter_begin( struct lp_scene *scene );
399 
400 struct cmd_bin *
401 lp_scene_bin_iter_next( struct lp_scene *scene, int *x, int *y );
402 
403 
404 
405 /* Begin/end binning of a scene
406  */
407 void
408 lp_scene_begin_binning(struct lp_scene *scene,
409                        struct pipe_framebuffer_state *fb);
410 
411 void
412 lp_scene_end_binning(struct lp_scene *scene);
413 
414 
415 /* Begin/end rasterization of a scene
416  */
417 void
418 lp_scene_begin_rasterization(struct lp_scene *scene);
419 
420 void
421 lp_scene_end_rasterization(struct lp_scene *scene);
422 
423 
424 
425 
426 
427 #endif /* LP_BIN_H */
428