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