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 *
lp_scene_alloc(struct lp_scene * scene,unsigned size)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 *
lp_scene_alloc_aligned(struct lp_scene * scene,unsigned size,unsigned alignment)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
lp_scene_putback_data(struct lp_scene * scene,unsigned size)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 *
lp_scene_get_bin(struct lp_scene * scene,unsigned x,unsigned y)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
lp_scene_bin_command(struct lp_scene * scene,unsigned x,unsigned y,unsigned cmd,union lp_rast_cmd_arg arg)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
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)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
lp_scene_bin_everywhere(struct lp_scene * scene,unsigned cmd,const union lp_rast_cmd_arg arg)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
lp_scene_get_num_bins(const struct lp_scene * scene)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