draw llvm: actually set the constant buffers on the context
[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 (boolean)draw->rasterizer->gl_rasterization_rules,
115 (draw->vs.edgeflag_output ? true : false) );
116
117 if (!(opt & PT_PIPELINE)) {
118 draw_pt_emit_prepare( fpme->emit,
119 prim,
120 max_vertices );
121
122 *max_vertices = MAX2( *max_vertices,
123 DRAW_PIPE_MAX_VERTICES );
124 }
125 else {
126 *max_vertices = DRAW_PIPE_MAX_VERTICES;
127 }
128
129 /* return even number */
130 *max_vertices = *max_vertices & ~1;
131
132 draw_llvm_prepare(fpme->llvm);
133
134 /*XXX we only support one constant buffer */
135 fpme->llvm->jit_context.vs_constants =
136 draw->pt.user.vs_constants[0];
137 fpme->llvm->jit_context.gs_constants =
138 draw->pt.user.gs_constants[0];
139 }
140
141
142
143 static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
144 const unsigned *fetch_elts,
145 unsigned fetch_count,
146 const ushort *draw_elts,
147 unsigned draw_count )
148 {
149 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
150 struct draw_context *draw = fpme->draw;
151 struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
152 struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
153 unsigned opt = fpme->opt;
154 unsigned alloc_count = align( fetch_count, 4 );
155
156 struct vertex_header *pipeline_verts =
157 (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
158
159 if (!pipeline_verts) {
160 /* Not much we can do here - just skip the rendering.
161 */
162 assert(0);
163 return;
164 }
165
166 /* Fetch into our vertex buffer
167 */
168 draw_pt_fetch_run( fpme->fetch,
169 fetch_elts,
170 fetch_count,
171 (char *)pipeline_verts );
172
173 /* Run the shader, note that this overwrites the data[] parts of
174 * the pipeline verts. If there is no shader, eg if
175 * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
176 * already in the correct place.*/
177 if (opt & PT_SHADE)
178 {
179 vshader->run_linear(vshader,
180 (const float (*)[4])pipeline_verts->data,
181 ( float (*)[4])pipeline_verts->data,
182 draw->pt.user.vs_constants,
183 fetch_count,
184 fpme->vertex_size,
185 fpme->vertex_size);
186 if (gshader)
187 draw_geometry_shader_run(gshader,
188 (const float (*)[4])pipeline_verts->data,
189 ( float (*)[4])pipeline_verts->data,
190 draw->pt.user.gs_constants,
191 fetch_count,
192 fpme->vertex_size,
193 fpme->vertex_size);
194 }
195
196 if (draw_pt_post_vs_run( fpme->post_vs,
197 pipeline_verts,
198 fetch_count,
199 fpme->vertex_size ))
200 {
201 opt |= PT_PIPELINE;
202 }
203
204 /* Do we need to run the pipeline?
205 */
206 if (opt & PT_PIPELINE) {
207 draw_pipeline_run( fpme->draw,
208 fpme->prim,
209 pipeline_verts,
210 fetch_count,
211 fpme->vertex_size,
212 draw_elts,
213 draw_count );
214 }
215 else {
216 draw_pt_emit( fpme->emit,
217 (const float (*)[4])pipeline_verts->data,
218 fetch_count,
219 fpme->vertex_size,
220 draw_elts,
221 draw_count );
222 }
223
224
225 FREE(pipeline_verts);
226 }
227
228
229 static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
230 unsigned start,
231 unsigned count)
232 {
233 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
234 struct draw_context *draw = fpme->draw;
235 unsigned opt = fpme->opt;
236 unsigned alloc_count = align( count, 4 );
237
238 struct vertex_header *pipeline_verts =
239 (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
240
241 if (!pipeline_verts) {
242 /* Not much we can do here - just skip the rendering.
243 */
244 assert(0);
245 return;
246 }
247
248 fpme->llvm->jit_func( &fpme->llvm->jit_context,
249 pipeline_verts,
250 (const char **)draw->pt.user.vbuffer,
251 start,
252 count,
253 fpme->vertex_size );
254
255 if (draw_pt_post_vs_run( fpme->post_vs,
256 pipeline_verts,
257 count,
258 fpme->vertex_size ))
259 {
260 opt |= PT_PIPELINE;
261 }
262
263 /* Do we need to run the pipeline?
264 */
265 if (opt & PT_PIPELINE) {
266 draw_pipeline_run_linear( fpme->draw,
267 fpme->prim,
268 pipeline_verts,
269 count,
270 fpme->vertex_size);
271 }
272 else {
273 draw_pt_emit_linear( fpme->emit,
274 (const float (*)[4])pipeline_verts->data,
275 fpme->vertex_size,
276 count );
277 }
278
279 FREE(pipeline_verts);
280 }
281
282
283
284 static boolean
285 llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
286 unsigned start,
287 unsigned count,
288 const ushort *draw_elts,
289 unsigned draw_count )
290 {
291 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
292 struct draw_context *draw = fpme->draw;
293 struct draw_vertex_shader *shader = draw->vs.vertex_shader;
294 struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
295 unsigned opt = fpme->opt;
296 unsigned alloc_count = align( count, 4 );
297
298 struct vertex_header *pipeline_verts =
299 (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
300
301 if (!pipeline_verts)
302 return FALSE;
303
304 /* Fetch into our vertex buffer
305 */
306 draw_pt_fetch_run_linear( fpme->fetch,
307 start,
308 count,
309 (char *)pipeline_verts );
310
311 /* Run the shader, note that this overwrites the data[] parts of
312 * the pipeline verts. If there is no shader, ie if
313 * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
314 * already in the correct place.
315 */
316 if (opt & PT_SHADE)
317 {
318 shader->run_linear(shader,
319 (const float (*)[4])pipeline_verts->data,
320 ( float (*)[4])pipeline_verts->data,
321 draw->pt.user.vs_constants,
322 count,
323 fpme->vertex_size,
324 fpme->vertex_size);
325
326 if (geometry_shader)
327 draw_geometry_shader_run(geometry_shader,
328 (const float (*)[4])pipeline_verts->data,
329 ( float (*)[4])pipeline_verts->data,
330 draw->pt.user.gs_constants,
331 count,
332 fpme->vertex_size,
333 fpme->vertex_size);
334 }
335
336 if (draw_pt_post_vs_run( fpme->post_vs,
337 pipeline_verts,
338 count,
339 fpme->vertex_size ))
340 {
341 opt |= PT_PIPELINE;
342 }
343
344 /* Do we need to run the pipeline?
345 */
346 if (opt & PT_PIPELINE) {
347 draw_pipeline_run( fpme->draw,
348 fpme->prim,
349 pipeline_verts,
350 count,
351 fpme->vertex_size,
352 draw_elts,
353 draw_count );
354 }
355 else {
356 draw_pt_emit( fpme->emit,
357 (const float (*)[4])pipeline_verts->data,
358 count,
359 fpme->vertex_size,
360 draw_elts,
361 draw_count );
362 }
363
364 FREE(pipeline_verts);
365 return TRUE;
366 }
367
368
369
370 static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
371 {
372 /* nothing to do */
373 }
374
375 static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
376 {
377 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
378
379 if (fpme->fetch)
380 draw_pt_fetch_destroy( fpme->fetch );
381
382 if (fpme->emit)
383 draw_pt_emit_destroy( fpme->emit );
384
385 if (fpme->post_vs)
386 draw_pt_post_vs_destroy( fpme->post_vs );
387
388 if (fpme->llvm)
389 draw_llvm_destroy( fpme->llvm );
390
391 FREE(middle);
392 }
393
394
395 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_context *draw )
396 {
397 struct llvm_middle_end *fpme = 0;
398
399 if (!draw->engine)
400 return NULL;
401
402 fpme = CALLOC_STRUCT( llvm_middle_end );
403 if (!fpme)
404 goto fail;
405
406 fpme->base.prepare = llvm_middle_end_prepare;
407 fpme->base.run = llvm_middle_end_run;
408 fpme->base.run_linear = llvm_middle_end_linear_run;
409 fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts;
410 fpme->base.finish = llvm_middle_end_finish;
411 fpme->base.destroy = llvm_middle_end_destroy;
412
413 fpme->draw = draw;
414
415 fpme->fetch = draw_pt_fetch_create( draw );
416 if (!fpme->fetch)
417 goto fail;
418
419 fpme->post_vs = draw_pt_post_vs_create( draw );
420 if (!fpme->post_vs)
421 goto fail;
422
423 fpme->emit = draw_pt_emit_create( draw );
424 if (!fpme->emit)
425 goto fail;
426
427 fpme->llvm = draw_llvm_create(draw);
428 if (!fpme->llvm)
429 goto fail;
430
431 return &fpme->base;
432
433 fail:
434 if (fpme)
435 llvm_middle_end_destroy( &fpme->base );
436
437 return NULL;
438 }