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