• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 opt;
52 };
53 
fetch_pipeline_prepare(struct draw_pt_middle_end * middle,unsigned prim,unsigned opt,unsigned * max_vertices)54 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
55                                     unsigned prim,
56 				    unsigned opt,
57                                     unsigned *max_vertices )
58 {
59    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
60    struct draw_context *draw = fpme->draw;
61    struct draw_vertex_shader *vs = draw->vs.vertex_shader;
62    unsigned i;
63    unsigned instance_id_index = ~0;
64 
65    unsigned gs_out_prim = (draw->gs.geometry_shader ?
66                            draw->gs.geometry_shader->output_primitive :
67                            prim);
68 
69    /* Add one to num_outputs because the pipeline occasionally tags on
70     * an additional texcoord, eg for AA lines.
71     */
72    unsigned nr = MAX2( vs->info.num_inputs,
73 		       vs->info.num_outputs + 1 );
74 
75    /* Scan for instanceID system value.
76     */
77    for (i = 0; i < vs->info.num_inputs; i++) {
78       if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
79          instance_id_index = i;
80          break;
81       }
82    }
83 
84    fpme->input_prim = prim;
85    fpme->opt = opt;
86 
87    /* Always leave room for the vertex header whether we need it or
88     * not.  It's hard to get rid of it in particular because of the
89     * viewport code in draw_pt_post_vs.c.
90     */
91    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
92 
93 
94 
95    draw_pt_fetch_prepare( fpme->fetch,
96                           vs->info.num_inputs,
97                           fpme->vertex_size,
98                           instance_id_index );
99    /* XXX: it's not really gl rasterization rules we care about here,
100     * but gl vs dx9 clip spaces.
101     */
102    draw_pt_post_vs_prepare( fpme->post_vs,
103 			    draw->clip_xy,
104 			    draw->clip_z,
105 			    draw->clip_user,
106                             draw->guard_band_xy,
107 			    draw->identity_viewport,
108 			    (boolean)draw->rasterizer->gl_rasterization_rules,
109 			    (draw->vs.edgeflag_output ? TRUE : FALSE) );
110 
111    draw_pt_so_emit_prepare( fpme->so_emit );
112 
113    if (!(opt & PT_PIPELINE)) {
114       draw_pt_emit_prepare( fpme->emit,
115 			    gs_out_prim,
116                             max_vertices );
117 
118       *max_vertices = MAX2( *max_vertices, 4096 );
119    }
120    else {
121       /* limit max fetches by limiting max_vertices */
122       *max_vertices = 4096;
123    }
124 
125    /* No need to prepare the shader.
126     */
127    vs->prepare(vs, draw);
128 }
129 
130 
fetch(struct pt_fetch * fetch,const struct draw_fetch_info * fetch_info,char * output)131 static void fetch( struct pt_fetch *fetch,
132                    const struct draw_fetch_info *fetch_info,
133                    char *output)
134 {
135    if (fetch_info->linear) {
136       draw_pt_fetch_run_linear( fetch,
137                                 fetch_info->start,
138                                 fetch_info->count,
139                                 output );
140    }
141    else {
142       draw_pt_fetch_run( fetch,
143                          fetch_info->elts,
144                          fetch_info->count,
145                          output );
146    }
147 }
148 
149 
pipeline(struct fetch_pipeline_middle_end * fpme,const struct draw_vertex_info * vert_info,const struct draw_prim_info * prim_info)150 static void pipeline(struct fetch_pipeline_middle_end *fpme,
151                      const struct draw_vertex_info *vert_info,
152                      const struct draw_prim_info *prim_info)
153 {
154    if (prim_info->linear)
155       draw_pipeline_run_linear( fpme->draw,
156                                 vert_info,
157                                 prim_info);
158    else
159       draw_pipeline_run( fpme->draw,
160                          vert_info,
161                          prim_info );
162 }
163 
emit(struct pt_emit * emit,const struct draw_vertex_info * vert_info,const struct draw_prim_info * prim_info)164 static void emit(struct pt_emit *emit,
165                  const struct draw_vertex_info *vert_info,
166                  const struct draw_prim_info *prim_info)
167 {
168    if (prim_info->linear) {
169       draw_pt_emit_linear(emit, vert_info, prim_info);
170    }
171    else {
172       draw_pt_emit(emit, vert_info, prim_info);
173    }
174 }
175 
176 
draw_vertex_shader_run(struct draw_vertex_shader * vshader,const void * constants[PIPE_MAX_CONSTANT_BUFFERS],unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],const struct draw_vertex_info * input_verts,struct draw_vertex_info * output_verts)177 static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
178                                    const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
179                                    unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
180                                    const struct draw_vertex_info *input_verts,
181                                    struct draw_vertex_info *output_verts )
182 {
183    output_verts->vertex_size = input_verts->vertex_size;
184    output_verts->stride = input_verts->vertex_size;
185    output_verts->count = input_verts->count;
186    output_verts->verts =
187       (struct vertex_header *)MALLOC(output_verts->vertex_size *
188                                      align(output_verts->count, 4));
189 
190    vshader->run_linear(vshader,
191                        (const float (*)[4])input_verts->verts->data,
192                        (      float (*)[4])output_verts->verts->data,
193                        constants,
194                        const_size,
195                        input_verts->count,
196                        input_verts->vertex_size,
197                        input_verts->vertex_size);
198 }
199 
fetch_pipeline_generic(struct draw_pt_middle_end * middle,const struct draw_fetch_info * fetch_info,const struct draw_prim_info * prim_info)200 static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
201                                     const struct draw_fetch_info *fetch_info,
202                                     const struct draw_prim_info *prim_info )
203 {
204    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
205    struct draw_context *draw = fpme->draw;
206    struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
207    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
208    struct draw_prim_info gs_prim_info;
209    struct draw_vertex_info fetched_vert_info;
210    struct draw_vertex_info vs_vert_info;
211    struct draw_vertex_info gs_vert_info;
212    struct draw_vertex_info *vert_info;
213    unsigned opt = fpme->opt;
214 
215    fetched_vert_info.count = fetch_info->count;
216    fetched_vert_info.vertex_size = fpme->vertex_size;
217    fetched_vert_info.stride = fpme->vertex_size;
218    fetched_vert_info.verts =
219       (struct vertex_header *)MALLOC(fpme->vertex_size *
220                                      align(fetch_info->count,  4));
221    if (!fetched_vert_info.verts) {
222       assert(0);
223       return;
224    }
225 
226    /* Fetch into our vertex buffer.
227     */
228    fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
229 
230    /* Finished with fetch:
231     */
232    fetch_info = NULL;
233    vert_info = &fetched_vert_info;
234 
235    /* Run the shader, note that this overwrites the data[] parts of
236     * the pipeline verts.
237     */
238    if (fpme->opt & PT_SHADE) {
239       draw_vertex_shader_run(vshader,
240                              draw->pt.user.vs_constants,
241                              draw->pt.user.vs_constants_size,
242                              vert_info,
243                              &vs_vert_info);
244 
245       FREE(vert_info->verts);
246       vert_info = &vs_vert_info;
247    }
248 
249    if ((fpme->opt & PT_SHADE) && gshader) {
250       draw_geometry_shader_run(gshader,
251                                draw->pt.user.gs_constants,
252                                draw->pt.user.gs_constants_size,
253                                vert_info,
254                                prim_info,
255                                &gs_vert_info,
256                                &gs_prim_info);
257 
258       FREE(vert_info->verts);
259       vert_info = &gs_vert_info;
260       prim_info = &gs_prim_info;
261    }
262 
263 
264    /* Stream output needs to be done before clipping.
265     *
266     * XXX: Stream output surely needs to respect the prim_info->elt
267     *      lists.
268     */
269    draw_pt_so_emit( fpme->so_emit,
270                     vert_info,
271                     prim_info );
272 
273    if (draw_pt_post_vs_run( fpme->post_vs,
274                             vert_info ))
275    {
276       opt |= PT_PIPELINE;
277    }
278 
279    /* Do we need to run the pipeline?
280     */
281    if (opt & PT_PIPELINE) {
282       pipeline( fpme,
283                 vert_info,
284                 prim_info );
285    }
286    else {
287       emit( fpme->emit,
288             vert_info,
289             prim_info );
290    }
291    FREE(vert_info->verts);
292 }
293 
fetch_pipeline_run(struct draw_pt_middle_end * middle,const unsigned * fetch_elts,unsigned fetch_count,const ushort * draw_elts,unsigned draw_count,unsigned prim_flags)294 static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
295                                 const unsigned *fetch_elts,
296                                 unsigned fetch_count,
297                                 const ushort *draw_elts,
298                                 unsigned draw_count,
299                                 unsigned prim_flags )
300 {
301    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
302    struct draw_fetch_info fetch_info;
303    struct draw_prim_info prim_info;
304 
305    fetch_info.linear = FALSE;
306    fetch_info.start = 0;
307    fetch_info.elts = fetch_elts;
308    fetch_info.count = fetch_count;
309 
310    prim_info.linear = FALSE;
311    prim_info.start = 0;
312    prim_info.count = draw_count;
313    prim_info.elts = draw_elts;
314    prim_info.prim = fpme->input_prim;
315    prim_info.flags = prim_flags;
316    prim_info.primitive_count = 1;
317    prim_info.primitive_lengths = &draw_count;
318 
319    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
320 }
321 
322 
fetch_pipeline_linear_run(struct draw_pt_middle_end * middle,unsigned start,unsigned count,unsigned prim_flags)323 static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
324                                        unsigned start,
325                                        unsigned count,
326                                        unsigned prim_flags)
327 {
328    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
329    struct draw_fetch_info fetch_info;
330    struct draw_prim_info prim_info;
331 
332    fetch_info.linear = TRUE;
333    fetch_info.start = start;
334    fetch_info.count = count;
335    fetch_info.elts = NULL;
336 
337    prim_info.linear = TRUE;
338    prim_info.start = 0;
339    prim_info.count = count;
340    prim_info.elts = NULL;
341    prim_info.prim = fpme->input_prim;
342    prim_info.flags = prim_flags;
343    prim_info.primitive_count = 1;
344    prim_info.primitive_lengths = &count;
345 
346    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
347 }
348 
349 
350 
fetch_pipeline_linear_run_elts(struct draw_pt_middle_end * middle,unsigned start,unsigned count,const ushort * draw_elts,unsigned draw_count,unsigned prim_flags)351 static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
352                                                unsigned start,
353                                                unsigned count,
354                                                const ushort *draw_elts,
355                                                unsigned draw_count,
356                                                unsigned prim_flags )
357 {
358    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
359    struct draw_fetch_info fetch_info;
360    struct draw_prim_info prim_info;
361 
362    fetch_info.linear = TRUE;
363    fetch_info.start = start;
364    fetch_info.count = count;
365    fetch_info.elts = NULL;
366 
367    prim_info.linear = FALSE;
368    prim_info.start = 0;
369    prim_info.count = draw_count;
370    prim_info.elts = draw_elts;
371    prim_info.prim = fpme->input_prim;
372    prim_info.flags = prim_flags;
373    prim_info.primitive_count = 1;
374    prim_info.primitive_lengths = &draw_count;
375 
376    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
377 
378    return TRUE;
379 }
380 
381 
382 
fetch_pipeline_finish(struct draw_pt_middle_end * middle)383 static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
384 {
385    /* nothing to do */
386 }
387 
fetch_pipeline_destroy(struct draw_pt_middle_end * middle)388 static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
389 {
390    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
391 
392    if (fpme->fetch)
393       draw_pt_fetch_destroy( fpme->fetch );
394 
395    if (fpme->emit)
396       draw_pt_emit_destroy( fpme->emit );
397 
398    if (fpme->so_emit)
399       draw_pt_so_emit_destroy( fpme->so_emit );
400 
401    if (fpme->post_vs)
402       draw_pt_post_vs_destroy( fpme->post_vs );
403 
404    FREE(middle);
405 }
406 
407 
draw_pt_fetch_pipeline_or_emit(struct draw_context * draw)408 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
409 {
410    struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
411    if (!fpme)
412       goto fail;
413 
414    fpme->base.prepare        = fetch_pipeline_prepare;
415    fpme->base.run            = fetch_pipeline_run;
416    fpme->base.run_linear     = fetch_pipeline_linear_run;
417    fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
418    fpme->base.finish         = fetch_pipeline_finish;
419    fpme->base.destroy        = fetch_pipeline_destroy;
420 
421    fpme->draw = draw;
422 
423    fpme->fetch = draw_pt_fetch_create( draw );
424    if (!fpme->fetch)
425       goto fail;
426 
427    fpme->post_vs = draw_pt_post_vs_create( draw );
428    if (!fpme->post_vs)
429       goto fail;
430 
431    fpme->emit = draw_pt_emit_create( draw );
432    if (!fpme->emit)
433       goto fail;
434 
435    fpme->so_emit = draw_pt_so_emit_create( draw );
436    if (!fpme->so_emit)
437       goto fail;
438 
439    return &fpme->base;
440 
441  fail:
442    if (fpme)
443       fetch_pipeline_destroy( &fpme->base );
444 
445    return NULL;
446 }
447