draw: make sure geometry shader correctly iterates the output buffer
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_shade_pipeline.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 #include "util/u_math.h"
29 #include "util/u_memory.h"
30 #include "util/u_prim.h"
31 #include "draw/draw_context.h"
32 #include "draw/draw_vbuf.h"
33 #include "draw/draw_vertex.h"
34 #include "draw/draw_pt.h"
35 #include "draw/draw_vs.h"
36 #include "draw/draw_gs.h"
37
38
39 struct fetch_pipeline_middle_end {
40 struct draw_pt_middle_end base;
41 struct draw_context *draw;
42
43 struct pt_emit *emit;
44 struct pt_so_emit *so_emit;
45 struct pt_fetch *fetch;
46 struct pt_post_vs *post_vs;
47
48 unsigned vertex_data_offset;
49 unsigned vertex_size;
50 unsigned input_prim;
51 unsigned output_prim;
52 unsigned opt;
53 };
54
55 static int max_out_vertex_count(
56 struct fetch_pipeline_middle_end *fpme, int count)
57 {
58 struct draw_context *draw = fpme->draw;
59 unsigned alloc_count = align( count, 4 );
60
61 if (draw->gs.geometry_shader) {
62 unsigned input_primitives = count / u_vertices_per_prim(fpme->input_prim);
63 /* max GS output is number of input primitives * max output
64 * vertices per each invocation */
65 unsigned gs_max_verts = input_primitives *
66 draw->gs.geometry_shader->max_output_vertices;
67 if (gs_max_verts > count)
68 alloc_count = align(gs_max_verts, 4);
69 }
70 /*debug_printf("------- alloc count = %d (input = %d)\n",
71 alloc_count, count);*/
72 return alloc_count;
73 }
74
75 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
76 unsigned in_prim,
77 unsigned out_prim,
78 unsigned opt,
79 unsigned *max_vertices )
80 {
81 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
82 struct draw_context *draw = fpme->draw;
83 struct draw_vertex_shader *vs = draw->vs.vertex_shader;
84 unsigned i;
85 unsigned instance_id_index = ~0;
86
87 /* Add one to num_outputs because the pipeline occasionally tags on
88 * an additional texcoord, eg for AA lines.
89 */
90 unsigned nr = MAX2( vs->info.num_inputs,
91 vs->info.num_outputs + 1 );
92
93 /* Scan for instanceID system value.
94 */
95 for (i = 0; i < vs->info.num_inputs; i++) {
96 if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
97 instance_id_index = i;
98 break;
99 }
100 }
101
102 fpme->input_prim = in_prim;
103 fpme->output_prim = out_prim;
104 fpme->opt = opt;
105
106 /* Always leave room for the vertex header whether we need it or
107 * not. It's hard to get rid of it in particular because of the
108 * viewport code in draw_pt_post_vs.c.
109 */
110 fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
111
112
113
114 draw_pt_fetch_prepare( fpme->fetch,
115 vs->info.num_inputs,
116 fpme->vertex_size,
117 instance_id_index );
118 /* XXX: it's not really gl rasterization rules we care about here,
119 * but gl vs dx9 clip spaces.
120 */
121 draw_pt_post_vs_prepare( fpme->post_vs,
122 (boolean)draw->bypass_clipping,
123 (boolean)draw->identity_viewport,
124 (boolean)draw->rasterizer->gl_rasterization_rules,
125 (draw->vs.edgeflag_output ? true : false) );
126
127 draw_pt_so_emit_prepare( fpme->so_emit, out_prim );
128
129 if (!(opt & PT_PIPELINE)) {
130 draw_pt_emit_prepare( fpme->emit,
131 out_prim,
132 max_vertices );
133
134 *max_vertices = MAX2( *max_vertices,
135 DRAW_PIPE_MAX_VERTICES );
136 }
137 else {
138 *max_vertices = DRAW_PIPE_MAX_VERTICES;
139 }
140
141 /* return even number */
142 *max_vertices = *max_vertices & ~1;
143
144 /* No need to prepare the shader.
145 */
146 vs->prepare(vs, draw);
147 }
148
149
150
151 static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
152 const unsigned *fetch_elts,
153 unsigned fetch_count,
154 const ushort *draw_elts,
155 unsigned draw_count )
156 {
157 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
158 struct draw_context *draw = fpme->draw;
159 struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
160 struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
161 unsigned opt = fpme->opt;
162 struct vertex_header *pipeline_verts;
163 unsigned alloc_count = max_out_vertex_count(fpme, fetch_count);
164
165 pipeline_verts =
166 (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
167
168 if (!pipeline_verts) {
169 /* Not much we can do here - just skip the rendering.
170 */
171 assert(0);
172 return;
173 }
174
175 /* Fetch into our vertex buffer
176 */
177 draw_pt_fetch_run( fpme->fetch,
178 fetch_elts,
179 fetch_count,
180 (char *)pipeline_verts );
181
182 /* Run the shader, note that this overwrites the data[] parts of
183 * the pipeline verts.
184 */
185 if (opt & PT_SHADE)
186 {
187 vshader->run_linear(vshader,
188 (const float (*)[4])pipeline_verts->data,
189 ( float (*)[4])pipeline_verts->data,
190 draw->pt.user.vs_constants,
191 fetch_count,
192 fpme->vertex_size,
193 fpme->vertex_size);
194 if (gshader)
195 fetch_count =
196 draw_geometry_shader_run(gshader,
197 (const float (*)[4])pipeline_verts->data,
198 ( float (*)[4])pipeline_verts->data,
199 draw->pt.user.gs_constants,
200 fetch_count,
201 fpme->vertex_size,
202 fpme->vertex_size);
203 }
204
205 /* stream output needs to be done before clipping */
206 draw_pt_so_emit( fpme->so_emit,
207 (const float (*)[4])pipeline_verts->data,
208 fetch_count,
209 fpme->vertex_size );
210
211 if (draw_pt_post_vs_run( fpme->post_vs,
212 pipeline_verts,
213 fetch_count,
214 fpme->vertex_size ))
215 {
216 opt |= PT_PIPELINE;
217 }
218
219 /* Do we need to run the pipeline?
220 */
221 if (opt & PT_PIPELINE) {
222 draw_pipeline_run( fpme->draw,
223 fpme->output_prim,
224 pipeline_verts,
225 fetch_count,
226 fpme->vertex_size,
227 draw_elts,
228 draw_count );
229 }
230 else {
231 draw_pt_emit( fpme->emit,
232 (const float (*)[4])pipeline_verts->data,
233 fetch_count,
234 fpme->vertex_size,
235 draw_elts,
236 draw_count );
237 }
238
239
240 FREE(pipeline_verts);
241 }
242
243
244 static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
245 unsigned start,
246 unsigned count)
247 {
248 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
249 struct draw_context *draw = fpme->draw;
250 struct draw_vertex_shader *shader = draw->vs.vertex_shader;
251 struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
252 unsigned opt = fpme->opt;
253 struct vertex_header *pipeline_verts;
254 unsigned alloc_count = max_out_vertex_count(fpme, count);
255
256 pipeline_verts =
257 (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
258
259 if (!pipeline_verts) {
260 /* Not much we can do here - just skip the rendering.
261 */
262 assert(0);
263 return;
264 }
265
266 /* Fetch into our vertex buffer
267 */
268 draw_pt_fetch_run_linear( fpme->fetch,
269 start,
270 count,
271 (char *)pipeline_verts );
272
273 /* Run the shader, note that this overwrites the data[] parts of
274 * the pipeline verts.
275 */
276 if (opt & PT_SHADE)
277 {
278 shader->run_linear(shader,
279 (const float (*)[4])pipeline_verts->data,
280 ( float (*)[4])pipeline_verts->data,
281 draw->pt.user.vs_constants,
282 count,
283 fpme->vertex_size,
284 fpme->vertex_size);
285
286 if (geometry_shader)
287 count = draw_geometry_shader_run(geometry_shader,
288 (const float (*)[4])pipeline_verts->data,
289 ( float (*)[4])pipeline_verts->data,
290 draw->pt.user.gs_constants,
291 count,
292 fpme->vertex_size,
293 fpme->vertex_size);
294 }
295
296 /* stream output needs to be done before clipping */
297 draw_pt_so_emit( fpme->so_emit,
298 (const float (*)[4])pipeline_verts->data,
299 count,
300 fpme->vertex_size );
301
302 if (draw_pt_post_vs_run( fpme->post_vs,
303 pipeline_verts,
304 count,
305 fpme->vertex_size ))
306 {
307 opt |= PT_PIPELINE;
308 }
309
310 /* Do we need to run the pipeline?
311 */
312 if (opt & PT_PIPELINE) {
313 draw_pipeline_run_linear( fpme->draw,
314 fpme->output_prim,
315 pipeline_verts,
316 count,
317 fpme->vertex_size);
318 }
319 else {
320 draw_pt_emit_linear( fpme->emit,
321 (const float (*)[4])pipeline_verts->data,
322 fpme->vertex_size,
323 count );
324 }
325
326 FREE(pipeline_verts);
327 }
328
329
330
331 static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
332 unsigned start,
333 unsigned count,
334 const ushort *draw_elts,
335 unsigned draw_count )
336 {
337 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
338 struct draw_context *draw = fpme->draw;
339 struct draw_vertex_shader *shader = draw->vs.vertex_shader;
340 struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
341 unsigned opt = fpme->opt;
342 struct vertex_header *pipeline_verts;
343 unsigned alloc_count = max_out_vertex_count(fpme, count);
344
345 pipeline_verts =
346 (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
347
348 if (!pipeline_verts)
349 return FALSE;
350
351 /* Fetch into our vertex buffer
352 */
353 draw_pt_fetch_run_linear( fpme->fetch,
354 start,
355 count,
356 (char *)pipeline_verts );
357
358 /* Run the shader, note that this overwrites the data[] parts of
359 * the pipeline verts.
360 */
361 if (opt & PT_SHADE)
362 {
363 shader->run_linear(shader,
364 (const float (*)[4])pipeline_verts->data,
365 ( float (*)[4])pipeline_verts->data,
366 draw->pt.user.vs_constants,
367 count,
368 fpme->vertex_size,
369 fpme->vertex_size);
370
371 if (geometry_shader)
372 count = draw_geometry_shader_run(geometry_shader,
373 (const float (*)[4])pipeline_verts->data,
374 ( float (*)[4])pipeline_verts->data,
375 draw->pt.user.gs_constants,
376 count,
377 fpme->vertex_size,
378 fpme->vertex_size);
379 }
380
381 /* stream output needs to be done before clipping */
382 draw_pt_so_emit( fpme->so_emit,
383 (const float (*)[4])pipeline_verts->data,
384 count,
385 fpme->vertex_size );
386
387 if (draw_pt_post_vs_run( fpme->post_vs,
388 pipeline_verts,
389 count,
390 fpme->vertex_size ))
391 {
392 opt |= PT_PIPELINE;
393 }
394
395 /* Do we need to run the pipeline?
396 */
397 if (opt & PT_PIPELINE) {
398 draw_pipeline_run( fpme->draw,
399 fpme->output_prim,
400 pipeline_verts,
401 count,
402 fpme->vertex_size,
403 draw_elts,
404 draw_count );
405 }
406 else {
407 draw_pt_emit( fpme->emit,
408 (const float (*)[4])pipeline_verts->data,
409 count,
410 fpme->vertex_size,
411 draw_elts,
412 draw_count );
413 }
414
415 FREE(pipeline_verts);
416 return TRUE;
417 }
418
419
420
421 static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
422 {
423 /* nothing to do */
424 }
425
426 static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
427 {
428 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
429
430 if (fpme->fetch)
431 draw_pt_fetch_destroy( fpme->fetch );
432
433 if (fpme->emit)
434 draw_pt_emit_destroy( fpme->emit );
435
436 if (fpme->so_emit)
437 draw_pt_so_emit_destroy( fpme->so_emit );
438
439 if (fpme->post_vs)
440 draw_pt_post_vs_destroy( fpme->post_vs );
441
442 FREE(middle);
443 }
444
445
446 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
447 {
448 struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
449 if (!fpme)
450 goto fail;
451
452 fpme->base.prepare = fetch_pipeline_prepare;
453 fpme->base.run = fetch_pipeline_run;
454 fpme->base.run_linear = fetch_pipeline_linear_run;
455 fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
456 fpme->base.finish = fetch_pipeline_finish;
457 fpme->base.destroy = fetch_pipeline_destroy;
458
459 fpme->draw = draw;
460
461 fpme->fetch = draw_pt_fetch_create( draw );
462 if (!fpme->fetch)
463 goto fail;
464
465 fpme->post_vs = draw_pt_post_vs_create( draw );
466 if (!fpme->post_vs)
467 goto fail;
468
469 fpme->emit = draw_pt_emit_create( draw );
470 if (!fpme->emit)
471 goto fail;
472
473 fpme->so_emit = draw_pt_so_emit_create( draw );
474 if (!fpme->so_emit)
475 goto fail;
476
477 return &fpme->base;
478
479 fail:
480 if (fpme)
481 fetch_pipeline_destroy( &fpme->base );
482
483 return NULL;
484 }