OSDN Git Service

Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
[android-x86/external-mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_shade_pipeline_llvm.c
1 /**************************************************************************
2  *
3  * Copyright 2010 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 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 "draw/draw_context.h"
31 #include "draw/draw_gs.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_llvm.h"
37
38
39 struct llvm_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
49    unsigned vertex_data_offset;
50    unsigned vertex_size;
51    unsigned input_prim;
52    unsigned opt;
53
54    struct draw_llvm *llvm;
55    struct draw_llvm_variant *current_variant;
56 };
57
58
59 static void
60 llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
61                          unsigned in_prim,
62                          unsigned opt,
63                          unsigned *max_vertices )
64 {
65    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
66    struct draw_context *draw = fpme->draw;
67    struct llvm_vertex_shader *shader =
68       llvm_vertex_shader(draw->vs.vertex_shader);
69    char store[DRAW_LLVM_MAX_VARIANT_KEY_SIZE];
70    struct draw_llvm_variant_key *key;
71    struct draw_llvm_variant *variant = NULL;
72    struct draw_llvm_variant_list_item *li;
73    unsigned i;
74    unsigned instance_id_index = ~0;
75
76
77    unsigned out_prim = (draw->gs.geometry_shader ? 
78                         draw->gs.geometry_shader->output_primitive :
79                         in_prim);
80
81    /* Add one to num_outputs because the pipeline occasionally tags on
82     * an additional texcoord, eg for AA lines.
83     */
84    unsigned nr = MAX2( shader->base.info.num_inputs,
85                        shader->base.info.num_outputs + 1 );
86
87    /* Scan for instanceID system value.
88     */
89    for (i = 0; i < shader->base.info.num_inputs; i++) {
90       if (shader->base.info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
91          instance_id_index = i;
92          break;
93       }
94    }
95
96    fpme->input_prim = in_prim;
97    fpme->opt = opt;
98
99    /* Always leave room for the vertex header whether we need it or
100     * not.  It's hard to get rid of it in particular because of the
101     * viewport code in draw_pt_post_vs.c.
102     */
103    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
104
105
106    /* XXX: it's not really gl rasterization rules we care about here,
107     * but gl vs dx9 clip spaces.
108     */
109    draw_pt_post_vs_prepare( fpme->post_vs,
110                             draw->clip_xy,
111                             draw->clip_z,
112                             draw->clip_user,
113                             draw->identity_viewport,
114                             (boolean)draw->rasterizer->gl_rasterization_rules,
115                             (draw->vs.edgeflag_output ? TRUE : FALSE) );
116
117    draw_pt_so_emit_prepare( fpme->so_emit );
118
119    if (!(opt & PT_PIPELINE)) {
120       draw_pt_emit_prepare( fpme->emit,
121                             out_prim,
122                             max_vertices );
123
124       *max_vertices = MAX2( *max_vertices, 4096 );
125    }
126    else {
127       /* limit max fetches by limiting max_vertices */
128       *max_vertices = 4096;
129    }
130
131    /* return even number */
132    *max_vertices = *max_vertices & ~1;
133    
134    key = draw_llvm_make_variant_key(fpme->llvm, store);
135
136    li = first_elem(&shader->variants);
137    while(!at_end(&shader->variants, li)) {
138       if(memcmp(&li->base->key, key, shader->variant_key_size) == 0) {
139          variant = li->base;
140          break;
141       }
142       li = next_elem(li);
143    }
144
145    if (variant) {
146       move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
147    }
148    else {
149       unsigned i;
150       if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) {
151          /*
152           * XXX: should we flush here ?
153           */
154          for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
155             struct draw_llvm_variant_list_item *item =
156                last_elem(&fpme->llvm->vs_variants_list);
157             draw_llvm_destroy_variant(item->base);
158          }
159       }
160
161       variant = draw_llvm_create_variant(fpme->llvm, nr, key);
162
163       if (variant) {
164          insert_at_head(&shader->variants, &variant->list_item_local);
165          insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
166          fpme->llvm->nr_variants++;
167          shader->variants_cached++;
168       }
169    }
170
171    fpme->current_variant = variant;
172
173    /*XXX we only support one constant buffer */
174    fpme->llvm->jit_context.vs_constants =
175       draw->pt.user.vs_constants[0];
176    fpme->llvm->jit_context.gs_constants =
177       draw->pt.user.gs_constants[0];
178    fpme->llvm->jit_context.planes =
179       (float (*) [12][4]) draw->pt.user.planes[0];
180    fpme->llvm->jit_context.viewport =
181       (float *)draw->viewport.scale;
182     
183 }
184
185
186 static void pipeline(struct llvm_middle_end *llvm,
187                      const struct draw_vertex_info *vert_info,
188                      const struct draw_prim_info *prim_info)
189 {
190    if (prim_info->linear)
191       draw_pipeline_run_linear( llvm->draw,
192                                 vert_info,
193                                 prim_info);
194    else
195       draw_pipeline_run( llvm->draw,
196                          vert_info,
197                          prim_info );
198 }
199
200 static void emit(struct pt_emit *emit,
201                  const struct draw_vertex_info *vert_info,
202                  const struct draw_prim_info *prim_info)
203 {
204    if (prim_info->linear) {
205       draw_pt_emit_linear(emit, vert_info, prim_info);
206    }
207    else {
208       draw_pt_emit(emit, vert_info, prim_info);
209    }
210 }
211
212 static void
213 llvm_pipeline_generic( struct draw_pt_middle_end *middle,
214                        const struct draw_fetch_info *fetch_info,
215                        const struct draw_prim_info *prim_info )
216 {
217    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
218    struct draw_context *draw = fpme->draw;
219    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
220    struct draw_prim_info gs_prim_info;
221    struct draw_vertex_info llvm_vert_info;
222    struct draw_vertex_info gs_vert_info;
223    struct draw_vertex_info *vert_info;
224    unsigned opt = fpme->opt;
225    unsigned clipped = 0;
226
227    llvm_vert_info.count = fetch_info->count;
228    llvm_vert_info.vertex_size = fpme->vertex_size;
229    llvm_vert_info.stride = fpme->vertex_size;
230    llvm_vert_info.verts =
231       (struct vertex_header *)MALLOC(fpme->vertex_size *
232                                      align(fetch_info->count,  4));
233    if (!llvm_vert_info.verts) {
234       assert(0);
235       return;
236    }
237
238    if (fetch_info->linear)
239       clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
240                                        llvm_vert_info.verts,
241                                        (const char **)draw->pt.user.vbuffer,
242                                        fetch_info->start,
243                                        fetch_info->count,
244                                        fpme->vertex_size,
245                                        draw->pt.vertex_buffer,
246                                        draw->instance_id);
247    else
248       clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
249                                             llvm_vert_info.verts,
250                                             (const char **)draw->pt.user.vbuffer,
251                                             fetch_info->elts,
252                                             fetch_info->count,
253                                             fpme->vertex_size,
254                                             draw->pt.vertex_buffer,
255                                             draw->instance_id);
256
257    /* Finished with fetch and vs:
258     */
259    fetch_info = NULL;
260    vert_info = &llvm_vert_info;
261
262
263    if ((opt & PT_SHADE) && gshader) {
264       draw_geometry_shader_run(gshader,
265                                draw->pt.user.gs_constants,
266                                draw->pt.user.gs_constants_size,
267                                vert_info,
268                                prim_info,
269                                &gs_vert_info,
270                                &gs_prim_info);
271
272       FREE(vert_info->verts);
273       vert_info = &gs_vert_info;
274       prim_info = &gs_prim_info;
275
276       clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info );
277
278    }
279
280    /* stream output needs to be done before clipping */
281    draw_pt_so_emit( fpme->so_emit,
282                     vert_info,
283                     prim_info );
284
285    if (clipped) {
286       opt |= PT_PIPELINE;
287    }
288
289    /* Do we need to run the pipeline? Now will come here if clipped
290     */
291    if (opt & PT_PIPELINE) {
292       pipeline( fpme,
293                 vert_info,
294                 prim_info );
295    }
296    else {
297       emit( fpme->emit,
298             vert_info,
299             prim_info );
300    }
301    FREE(vert_info->verts);
302 }
303
304
305 static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
306                                  const unsigned *fetch_elts,
307                                  unsigned fetch_count,
308                                  const ushort *draw_elts,
309                                  unsigned draw_count,
310                                  unsigned prim_flags )
311 {
312    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
313    struct draw_fetch_info fetch_info;
314    struct draw_prim_info prim_info;
315
316    fetch_info.linear = FALSE;
317    fetch_info.start = 0;
318    fetch_info.elts = fetch_elts;
319    fetch_info.count = fetch_count;
320
321    prim_info.linear = FALSE;
322    prim_info.start = 0;
323    prim_info.count = draw_count;
324    prim_info.elts = draw_elts;
325    prim_info.prim = fpme->input_prim;
326    prim_info.flags = prim_flags;
327    prim_info.primitive_count = 1;
328    prim_info.primitive_lengths = &draw_count;
329
330    llvm_pipeline_generic( middle, &fetch_info, &prim_info );
331 }
332
333
334 static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
335                                        unsigned start,
336                                        unsigned count,
337                                        unsigned prim_flags)
338 {
339    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
340    struct draw_fetch_info fetch_info;
341    struct draw_prim_info prim_info;
342
343    fetch_info.linear = TRUE;
344    fetch_info.start = start;
345    fetch_info.count = count;
346    fetch_info.elts = NULL;
347
348    prim_info.linear = TRUE;
349    prim_info.start = 0;
350    prim_info.count = count;
351    prim_info.elts = NULL;
352    prim_info.prim = fpme->input_prim;
353    prim_info.flags = prim_flags;
354    prim_info.primitive_count = 1;
355    prim_info.primitive_lengths = &count;
356
357    llvm_pipeline_generic( middle, &fetch_info, &prim_info );
358 }
359
360
361
362 static boolean
363 llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
364                                  unsigned start,
365                                  unsigned count,
366                                  const ushort *draw_elts,
367                                  unsigned draw_count,
368                                  unsigned prim_flags )
369 {
370    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
371    struct draw_fetch_info fetch_info;
372    struct draw_prim_info prim_info;
373
374    fetch_info.linear = TRUE;
375    fetch_info.start = start;
376    fetch_info.count = count;
377    fetch_info.elts = NULL;
378
379    prim_info.linear = FALSE;
380    prim_info.start = 0;
381    prim_info.count = draw_count;
382    prim_info.elts = draw_elts;
383    prim_info.prim = fpme->input_prim;
384    prim_info.flags = prim_flags;
385    prim_info.primitive_count = 1;
386    prim_info.primitive_lengths = &draw_count;
387
388    llvm_pipeline_generic( middle, &fetch_info, &prim_info );
389
390    return TRUE;
391 }
392
393
394
395 static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
396 {
397    /* nothing to do */
398 }
399
400 static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
401 {
402    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
403
404    if (fpme->fetch)
405       draw_pt_fetch_destroy( fpme->fetch );
406
407    if (fpme->emit)
408       draw_pt_emit_destroy( fpme->emit );
409
410    if (fpme->so_emit)
411       draw_pt_so_emit_destroy( fpme->so_emit );
412
413    if (fpme->post_vs)
414       draw_pt_post_vs_destroy( fpme->post_vs );
415
416    FREE(middle);
417 }
418
419
420 struct draw_pt_middle_end *
421 draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw)
422 {
423    struct llvm_middle_end *fpme = 0;
424
425    if (!draw->engine)
426       return NULL;
427
428    fpme = CALLOC_STRUCT( llvm_middle_end );
429    if (!fpme)
430       goto fail;
431
432    fpme->base.prepare         = llvm_middle_end_prepare;
433    fpme->base.run             = llvm_middle_end_run;
434    fpme->base.run_linear      = llvm_middle_end_linear_run;
435    fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts;
436    fpme->base.finish          = llvm_middle_end_finish;
437    fpme->base.destroy         = llvm_middle_end_destroy;
438
439    fpme->draw = draw;
440
441    fpme->fetch = draw_pt_fetch_create( draw );
442    if (!fpme->fetch)
443       goto fail;
444
445    fpme->post_vs = draw_pt_post_vs_create( draw );
446    if (!fpme->post_vs)
447       goto fail;
448
449    fpme->emit = draw_pt_emit_create( draw );
450    if (!fpme->emit)
451       goto fail;
452
453    fpme->so_emit = draw_pt_so_emit_create( draw );
454    if (!fpme->so_emit)
455       goto fail;
456
457    fpme->llvm = draw->llvm;
458    if (!fpme->llvm)
459       goto fail;
460
461    fpme->current_variant = NULL;
462
463    return &fpme->base;
464
465  fail:
466    if (fpme)
467       llvm_middle_end_destroy( &fpme->base );
468
469    return NULL;
470 }