OSDN Git Service

Merge branch '7.8'
[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_vbuf.h"
32 #include "draw/draw_vertex.h"
33 #include "draw/draw_pt.h"
34 #include "draw/draw_vs.h"
35 #include "draw/draw_gs.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_fetch *fetch;
45    struct pt_post_vs *post_vs;
46
47
48    unsigned vertex_data_offset;
49    unsigned vertex_size;
50    unsigned prim;
51    unsigned opt;
52
53    struct draw_llvm *llvm;
54    struct draw_llvm_variant *variants;
55    struct draw_llvm_variant *current_variant;
56    int nr_variants;
57 };
58
59
60 static void
61 llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
62                          unsigned prim,
63                          unsigned opt,
64                          unsigned *max_vertices )
65 {
66    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
67    struct draw_context *draw = fpme->draw;
68    struct draw_vertex_shader *vs = draw->vs.vertex_shader;
69    struct draw_geometry_shader *gs = draw->gs.geometry_shader;
70    struct draw_llvm_variant_key key;
71    struct draw_llvm_variant *variant = NULL;
72    unsigned i;
73    unsigned instance_id_index = ~0;
74
75    /* Add one to num_outputs because the pipeline occasionally tags on
76     * an additional texcoord, eg for AA lines.
77     */
78    unsigned nr = MAX2( vs->info.num_inputs,
79                        vs->info.num_outputs + 1 );
80
81    /* Scan for instanceID system value.
82     */
83    for (i = 0; i < vs->info.num_inputs; i++) {
84       if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
85          instance_id_index = i;
86          break;
87       }
88    }
89
90    fpme->prim = prim;
91    fpme->opt = opt;
92
93    /* Always leave room for the vertex header whether we need it or
94     * not.  It's hard to get rid of it in particular because of the
95     * viewport code in draw_pt_post_vs.c.
96     */
97    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
98
99
100
101    draw_pt_fetch_prepare( fpme->fetch,
102                           vs->info.num_inputs,
103                           fpme->vertex_size,
104                           instance_id_index );
105    if (opt & PT_SHADE) {
106       vs->prepare(vs, draw);
107       draw_geometry_shader_prepare(gs, draw);
108    }
109
110
111    /* XXX: it's not really gl rasterization rules we care about here,
112     * but gl vs dx9 clip spaces.
113     */
114    draw_pt_post_vs_prepare( fpme->post_vs,
115                             (boolean)draw->bypass_clipping,
116                             (boolean)(draw->identity_viewport),
117                             (boolean)draw->rasterizer->gl_rasterization_rules,
118                             (draw->vs.edgeflag_output ? true : false) );
119
120    if (!(opt & PT_PIPELINE)) {
121       draw_pt_emit_prepare( fpme->emit,
122                             prim,
123                             max_vertices );
124
125       *max_vertices = MAX2( *max_vertices,
126                             DRAW_PIPE_MAX_VERTICES );
127    }
128    else {
129       *max_vertices = DRAW_PIPE_MAX_VERTICES;
130    }
131
132    /* return even number */
133    *max_vertices = *max_vertices & ~1;
134
135    draw_llvm_make_variant_key(fpme->llvm, &key);
136
137    variant = fpme->variants;
138    while(variant) {
139       if(memcmp(&variant->key, &key, sizeof key) == 0)
140          break;
141
142       variant = variant->next;
143    }
144
145    if (!variant) {
146       variant = draw_llvm_prepare(fpme->llvm, nr);
147       variant->next = fpme->variants;
148       fpme->variants = variant;
149       ++fpme->nr_variants;
150    }
151    fpme->current_variant = variant;
152
153    /*XXX we only support one constant buffer */
154    fpme->llvm->jit_context.vs_constants =
155       draw->pt.user.vs_constants[0];
156    fpme->llvm->jit_context.gs_constants =
157       draw->pt.user.gs_constants[0];
158 }
159
160
161
162 static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
163                                  const unsigned *fetch_elts,
164                                  unsigned fetch_count,
165                                  const ushort *draw_elts,
166                                  unsigned draw_count )
167 {
168    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
169    struct draw_context *draw = fpme->draw;
170    struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
171    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
172    unsigned opt = fpme->opt;
173    unsigned alloc_count = align( fetch_count, 4 );
174
175    struct vertex_header *pipeline_verts =
176       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
177
178    if (!pipeline_verts) {
179       /* Not much we can do here - just skip the rendering.
180        */
181       assert(0);
182       return;
183    }
184
185    /* Fetch into our vertex buffer
186     */
187    draw_pt_fetch_run( fpme->fetch,
188                       fetch_elts,
189                       fetch_count,
190                       (char *)pipeline_verts );
191
192    /* Run the shader, note that this overwrites the data[] parts of
193     * the pipeline verts.  If there is no shader, eg if
194     * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
195     * already in the correct place.*/
196    if (opt & PT_SHADE)
197    {
198       vshader->run_linear(vshader,
199                           (const float (*)[4])pipeline_verts->data,
200                           (      float (*)[4])pipeline_verts->data,
201                           draw->pt.user.vs_constants,
202                           fetch_count,
203                           fpme->vertex_size,
204                           fpme->vertex_size);
205       if (gshader)
206          draw_geometry_shader_run(gshader,
207                                   (const float (*)[4])pipeline_verts->data,
208                                   (      float (*)[4])pipeline_verts->data,
209                                   draw->pt.user.gs_constants,
210                                   fetch_count,
211                                   fpme->vertex_size,
212                                   fpme->vertex_size);
213    }
214
215    if (draw_pt_post_vs_run( fpme->post_vs,
216                             pipeline_verts,
217                             fetch_count,
218                             fpme->vertex_size ))
219    {
220       opt |= PT_PIPELINE;
221    }
222
223    /* Do we need to run the pipeline?
224     */
225    if (opt & PT_PIPELINE) {
226       draw_pipeline_run( fpme->draw,
227                          fpme->prim,
228                          pipeline_verts,
229                          fetch_count,
230                          fpme->vertex_size,
231                          draw_elts,
232                          draw_count );
233    }
234    else {
235       draw_pt_emit( fpme->emit,
236                     (const float (*)[4])pipeline_verts->data,
237                     fetch_count,
238                     fpme->vertex_size,
239                     draw_elts,
240                     draw_count );
241    }
242
243
244    FREE(pipeline_verts);
245 }
246
247
248 static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
249                                        unsigned start,
250                                        unsigned count)
251 {
252    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
253    struct draw_context *draw = fpme->draw;
254    unsigned opt = fpme->opt;
255    unsigned alloc_count = align( count, 4 );
256
257    struct vertex_header *pipeline_verts =
258       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
259
260    if (!pipeline_verts) {
261       /* Not much we can do here - just skip the rendering.
262        */
263       assert(0);
264       return;
265    }
266
267 #if 0
268    debug_printf("#### Pipeline = %p (data = %p)\n",
269                 pipeline_verts, pipeline_verts->data);
270 #endif
271    fpme->current_variant->jit_func( &fpme->llvm->jit_context,
272                                     pipeline_verts,
273                                     (const char **)draw->pt.user.vbuffer,
274                                     start,
275                                     count,
276                                     fpme->vertex_size,
277                                     draw->pt.vertex_buffer );
278
279    if (draw_pt_post_vs_run( fpme->post_vs,
280                             pipeline_verts,
281                             count,
282                             fpme->vertex_size ))
283    {
284       opt |= PT_PIPELINE;
285    }
286
287    /* Do we need to run the pipeline?
288     */
289    if (opt & PT_PIPELINE) {
290       draw_pipeline_run_linear( fpme->draw,
291                                 fpme->prim,
292                                 pipeline_verts,
293                                 count,
294                                 fpme->vertex_size);
295    }
296    else {
297       draw_pt_emit_linear( fpme->emit,
298                            (const float (*)[4])pipeline_verts->data,
299                            fpme->vertex_size,
300                            count );
301    }
302
303    FREE(pipeline_verts);
304 }
305
306
307
308 static boolean
309 llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
310                                  unsigned start,
311                                  unsigned count,
312                                  const ushort *draw_elts,
313                                  unsigned draw_count )
314 {
315    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
316    struct draw_context *draw = fpme->draw;
317    unsigned opt = fpme->opt;
318    unsigned alloc_count = align( count, 4 );
319
320    struct vertex_header *pipeline_verts =
321       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
322
323    if (!pipeline_verts)
324       return FALSE;
325
326    fpme->current_variant->jit_func( &fpme->llvm->jit_context,
327                                     pipeline_verts,
328                                     (const char **)draw->pt.user.vbuffer,
329                                     start,
330                                     count,
331                                     fpme->vertex_size,
332                                     draw->pt.vertex_buffer );
333
334    if (draw_pt_post_vs_run( fpme->post_vs,
335                             pipeline_verts,
336                             count,
337                             fpme->vertex_size ))
338    {
339       opt |= PT_PIPELINE;
340    }
341
342    /* Do we need to run the pipeline?
343     */
344    if (opt & PT_PIPELINE) {
345       draw_pipeline_run( fpme->draw,
346                          fpme->prim,
347                          pipeline_verts,
348                          count,
349                          fpme->vertex_size,
350                          draw_elts,
351                          draw_count );
352    }
353    else {
354       draw_pt_emit( fpme->emit,
355                     (const float (*)[4])pipeline_verts->data,
356                     count,
357                     fpme->vertex_size,
358                     draw_elts,
359                     draw_count );
360    }
361
362    FREE(pipeline_verts);
363    return TRUE;
364 }
365
366
367
368 static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
369 {
370    /* nothing to do */
371 }
372
373 static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
374 {
375    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
376
377    if (fpme->fetch)
378       draw_pt_fetch_destroy( fpme->fetch );
379
380    if (fpme->emit)
381       draw_pt_emit_destroy( fpme->emit );
382
383    if (fpme->post_vs)
384       draw_pt_post_vs_destroy( fpme->post_vs );
385
386    if (fpme->llvm)
387       draw_llvm_destroy( fpme->llvm );
388
389    FREE(middle);
390 }
391
392
393 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_context *draw )
394 {
395    struct llvm_middle_end *fpme = 0;
396
397    if (!draw->engine)
398       return NULL;
399
400    fpme = CALLOC_STRUCT( llvm_middle_end );
401    if (!fpme)
402       goto fail;
403
404    fpme->base.prepare         = llvm_middle_end_prepare;
405    fpme->base.run             = llvm_middle_end_run;
406    fpme->base.run_linear      = llvm_middle_end_linear_run;
407    fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts;
408    fpme->base.finish          = llvm_middle_end_finish;
409    fpme->base.destroy         = llvm_middle_end_destroy;
410
411    fpme->draw = draw;
412
413    fpme->fetch = draw_pt_fetch_create( draw );
414    if (!fpme->fetch)
415       goto fail;
416
417    fpme->post_vs = draw_pt_post_vs_create( draw );
418    if (!fpme->post_vs)
419       goto fail;
420
421    fpme->emit = draw_pt_emit_create( draw );
422    if (!fpme->emit)
423       goto fail;
424
425    fpme->llvm = draw_llvm_create(draw);
426    if (!fpme->llvm)
427       goto fail;
428
429    fpme->variants = NULL;
430    fpme->current_variant = NULL;
431    fpme->nr_variants = 0;
432
433    return &fpme->base;
434
435  fail:
436    if (fpme)
437       llvm_middle_end_destroy( &fpme->base );
438
439    return NULL;
440 }